message:
Keypad pin as an interrupt (Wiring or programming)

I have this project of a "phone". It consists of:
- Arduino DUE,
- 4x4 Keypad,
- SD Data shield,
- a phone receiver detect (on/off)
- an Amp and a Speaker.

In the beginning, after the phone receiver is being picked, I am playing a .wav file of an intro on how to choose a language.
And this .wav should be interrupted when the user presses the 4th row of a keypad (Buttons A/B/C/D).
I only need one pin as far as I know, in this setup - pin 38 (Column 4 pin). As I understand, there is no proper way to declare a keypad input pin as an interrupt on DUE. Or is it?

So my question - how to wire a keypad input pin as an interrupt?
I have read about wiring with a diode. But most of the threads lack any specifics.

Can someone push me in the right direction?
Cheers!

Code:

    #include <DAC.h>
    #include <SD.h>
    #include <SPI.h>
    #include <Audio.h>
    #include <Key.h>
    #include <Keypad.h>

    const byte ROW_NUM = 4;
    const byte COLUMN_NUM = 4;

    int code1 = 12345;  //The code I used, you can change it
    int code2 = 45678;  //The code I used, you can change it
    int code3 = 78900;  //The code I used, you can change it

    int tot, i1, i2, i3, i4, i5;
    char c1, c2, c3, c4;

    char hexaKeys[ROW_NUM][COLUMN_NUM] = {
      {'1', '2', '3', 'A'},
      {'4', '5', '6', 'B'},
      {'7', '8', '9', 'C'},
      {'*', '0', '#', 'D'}
    };

    byte hookPinA = 23;  // your interrupt pin
    byte interruptPin = 22;  // your interrupt pin

    byte pin_rows[ROW_NUM] = {52, 50, 48, 46}; //connect to the row pinouts of the keypad
    byte pin_column[COLUMN_NUM] = {44, 42, 40, 38}; //connect to the column pinouts of the keypad

    int keyCounter = 0;

    Keypad myKeypad = Keypad(makeKeymap(hexaKeys), pin_rows, pin_column, ROW_NUM, COLUMN_NUM);

    char keypresses[5];
    char language;
    char key;

    int goIntoKeys = 0;

    volatile uint8_t interruptState = 0;
    volatile byte hookOffState = 0;

    void setup() {
      // debug output at 9600 baud
      Serial.begin(9600);
      SD.begin(10);
      analogWriteResolution(12);

    //for( int i=0; i< ROW_NUM; ++i) pinMode(pin_rows[i], INPUT_PULLUP);
    //for( int i=0; i< COLUMN_NUM; ++i) pinMode(pin_column[i], INPUT_PULLUP);

     pinMode(hookPinA, INPUT_PULLUP);

     attachInterrupt(digitalPinToInterrupt(hookPinA), hookOffToggle, CHANGE);

    // EIFR |= bit(INTF0); // clear INT0 interrupt flag

     attachInterrupt(digitalPinToInterrupt(interruptPin), interruptToggle, RISING); //test interrupt with a regular button

     pinMode(38, INPUT_PULLUP);
     attachInterrupt(digitalPinToInterrupt(38), interruptToggle, RISING);

      DACC->DACC_CHDR = DACC_CHDR_CH1; //disable DAC1

    }

    int state = 0;
    const int STATE_OFF = 0;
    const int STATE_IDLE = 1;
    const int STATE_LISTEN_KEY = 2;
    const int STATE_PLAYER = 3;

    bool isLanguageKey(char customKey) {
      return ('A' == customKey || 'B' == customKey || 'C' == customKey || 'D' == customKey);
    }

    void loop() {
      switch (state) {
        case STATE_OFF:
        //listen for a telephone receiver to be removed
          if (hookOffState == 1) {
          Serial.print("HOOK OFF ");
          Serial.println(hookOffState);
            interruptState = 0;
            state = STATE_IDLE;
                   }
                   else if (hookOffState == 0) {
          Serial.print("HOOK ON ");
          Serial.println(hookOffState);
                   }
            break;
        case STATE_IDLE:
        //listen for a language key. Cannot dial a number before
          Serial.print("interrupt IDLE ");
          Serial.println(interruptState);
                   if (interruptState == 1) {
             buttonBeep();
            processLanguage();
            state = STATE_LISTEN_KEY;
                   }
                   else if (hookOffState == 0){
                    state = STATE_OFF;
                   }
                   else {
          playSound("intro.wav");
            }
          break;
        case STATE_LISTEN_KEY:
        //listen for any key
          Serial.print("interrupt LISTEN KEY ");
          Serial.println(interruptState);
          if (isKeyPressed()) {
            interruptState = 0;
            if (isLanguageKey(key)) {
              buttonBeep();
              processLanguage();
            }
            else {
          Serial.print("interruptStateF ");
          Serial.println(interruptState);
                   buttonBeep();
              keypresses[keyCounter] = key;
              keyDial();
              keyCounter++;
              if (keyCounter > 4) {
                state = STATE_PLAYER;
                //when 5 numbers are pressed - try to open the .wav file
              }
            }
          }
                   else if (hookOffState == 0){
                    state = STATE_OFF;
                   }
          break;
        case STATE_PLAYER:
            //Play the audio and go back to state LISTEN
          calculateAndPlay();
          keyCounter = 0;
          interruptState = 0;
          state = STATE_LISTEN_KEY;
          break;
        default:
          break;
      }
    }

    void hookOffToggle(){
     if (digitalRead(hookPinA) == 1) {
      hookOffState = 1;
     }
      else  {
          hookOffState = 0;
      }
    }

    void interruptToggle() {
        interruptState = 1;
    }

    void kalba() {
      Serial.println("Kalba? Language? Valoda? Yazik?");
    }

    bool isKeyPressed() {
      key = myKeypad.getKey();
      return key != NO_KEY;
    }

    bool langKeyPressed() {
      key = myKeypad.getKey();
      return key != NO_KEY && isLanguageKey(key);
    }

    void processLanguage() { //press A/B/C/D keys - select 1 out of 4 languages
      //goIntoKeys = 1;
      keyCounter = 0;
      if (key == 'A') {
        Serial.println("   LT    ");
      }
      if (key == 'B') {
        Serial.println("   EN    ");
      }
      if (key == 'C') {
        Serial.println("   LV    ");
      }
      if (key == 'D') {
        Serial.println("   RU    ");
      }
      language = key;
    }

    void keyDial() {    // LCD displays the number dialed in 3 slots.
      keypresses[keyCounter] = 0x00;//null-byte
      keypresses[keyCounter] = key;

      if (key != NO_KEY)   {
        Serial.println(keypresses[keyCounter]);
      }
    }

    void buttonBeep(){
          for (int j = 0; j < 200; j++) {
            for (int i = 0; i < 200; i++)
              analogWrite(DAC0, i);
            for (int i = 200; i >= 0; i--)
              analogWrite(DAC0, i);
          }
    }

    void backgroundHumm() {
          for (int j = 0; j < 256; j++) {
            for (int i = 0; i < 256; i++)
              analogWrite(DAC0, j);
              for (int j = 256; j >= 0; j--) {
                for (int i = 256; i >= 0; i--)
              analogWrite(DAC0, j);
          }
      }
    }

    void calculateAndPlay() {
      //if we have 4+1 numbers - proceed
      //the keys pressed are stored into chars I convert them to int then i did some multiplication to get the code as an int of xxxx
      i1 = (keypresses[0] - 48) * 10000;
      i2 = (keypresses[1] - 48) * 1000;
      i3 = (keypresses[2] - 48) * 100;
      i4 = (keypresses[3] - 48) * 10;
      i5 = (keypresses[4] - 48) * 1;

      tot = i1 + i2 + i3 + i4 + i5;
      if (language == 'A') {
        if (tot == code1) //if the code is correct you trigger to play .wav
        {
          playSound("ledaiLT.wav");
        }
        else if (tot == code2)
        {
          playSound("zuvisLT.wav");
        }
        else if (tot == code3)
        {
          playSound("draugLT.wav");
        }
        else //if the code is wrong you get a beep and audio message
      {
          playSound("blogasLT.wav");
        }
      }
      if (language == 'B') {
        if (tot == code1) //if the code is correct you trigger to play .wav
        {
          playSound("ledaiEN.wav");
        }
        else if (tot == code2)
        {
          playSound("zuvisEN.wav");
        }
        else if (tot == code3)
        {
          playSound("draugEN.wav");
        }
        else //if the code is wrong you get a beep and audio message
        {
          playSound("blogasEN.wav");
        }
      }
      if (language == 'C') {
        if (tot == code1) //if the code is correct you trigger to play .wav
        {
          playSound("ledaiLV.wav");
        }
        else if (tot == code2)
        {
          playSound("zuvisLV.wav");
        }
        else if (tot == code3)
        {
          playSound("draugLV.wav");
        }
        else //if the code is wrong you get a beep and audio message
        {
          playSound("blogasLV.wav");
        }
      }
      if (language == 'D') {
        if (tot == code1) //if the code is correct you trigger to play .wav
        {
          playSound("ledaiRU.wav");
        }
        else if (tot == code2)
        {
          playSound("zuvisRU.wav");
        }
        else if (tot == code3)
        {
          playSound("draugRU.wav");
        }
        else //if the code is wrong you get a beep and audio message
        {
          playSound("blogasRU.wav");
        }
      }
    }

    // Playing assigned filename
    void playSound(const char* cName) {
      File myFile = SD.open(cName);
      const int S = 1024; // Number of samples to read in block
      short buffer[S];
      // until the file is not finished
      Serial.println("playing ");
      Serial.println(cName);

      Audio.begin(44100, 200);
      delay(200);
      while (myFile.available()) {
        myFile.read(buffer, sizeof(buffer));
        // Prepare samples
        int volume = 512;
        //max volume 1024
        Audio.prepare(buffer, S, volume);
        Audio.write(buffer, S);
       if ( interruptState ) break;
         else if ( hookOffState == 0 ) break;
      }
      Audio.end();
      myFile.close();
      delay(50);
      DACC->DACC_CHDR = DACC_CHDR_CH1; //disable DAC1
    }

The schematics (if you can call it that) below:
[![enter image description here][1]][1]

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

EDIT:
@Damago solution works! I just wanted to share here the solution for future searches. What you need to do is to get the 4th column of 4x4 keypad to work as an interrupt properly:
Set all row pins as output and column pins as input with pullup.

    for( int i=0; i< ROW_NUM; ++i) pinMode(pin_rows[i], OUTPUT);
    for( int i=0; i< COLUMN_NUM; ++i) pinMode(pin_column[i], INPUT_PULLUP);

Set row pins to low:

    for( int i=0; i< ROW_NUM; ++i) digitalWrite(pin_rows[i], LOW);

Attach the 4th column pin as interrupt:

    attachInterrupt(digitalPinToInterrupt(pin_column[3]), interruptToggle, FALLING);

And of course, fix the syntax overall (it was a bit messy :) )

Full sketch below:

    #include <DAC.h>
    #include <SD.h>
    #include <SPI.h>
    #include <Audio.h>
    #include <Keypad.h>

    const byte ROW_NUM = 4;
    const byte COLUMN_NUM = 4;

    int code1 = 12345;  //The code I used, you can change it
    int code2 = 45678;  //The code I used, you can change it
    int code3 = 78900;  //The code I used, you can change it

    int tot, i1, i2, i3, i4, i5;
    char c1, c2, c3, c4;

    char hexaKeys[ROW_NUM][COLUMN_NUM] = {
      {'1', '2', '3', 'A'},
      {'4', '5', '6', 'B'},
      {'7', '8', '9', 'C'},
      {'*', '0', '#', 'D'}
    };

    byte hookPinA = 23;  // your interrupt pin
    byte pin_rows[ROW_NUM] = {52, 50, 48, 46}; //connect to the row pinouts of the keypad
    byte pin_column[COLUMN_NUM] = {44, 42, 40, 38}; //connect to the column pinouts of the keypad

    Keypad myKeypad = Keypad(makeKeymap(hexaKeys), pin_rows, pin_column, ROW_NUM, COLUMN_NUM);

    char keypresses[5];
    char language;
    char key;

    volatile uint8_t interruptState = 0;
    volatile byte hookOffState = 0;
    int keyCounter = 0;

    void setup() {
      // debug output at 9600 baud
      Serial.begin(9600);
      SD.begin(10);
      analogWriteResolution(12);

    for( int i=0; i< ROW_NUM; ++i) pinMode(pin_rows[i], OUTPUT);
    for( int i=0; i< COLUMN_NUM; ++i) pinMode(pin_column[i], INPUT_PULLUP);

    for( int i=0; i< ROW_NUM; ++i) digitalWrite(pin_rows[i], LOW);
     pinMode(hookPinA, INPUT_PULLUP);
     attachInterrupt(digitalPinToInterrupt(hookPinA), hookOffToggle, CHANGE);
     attachInterrupt(digitalPinToInterrupt(pin_column[3]), interruptToggle, FALLING);

      DACC->DACC_CHDR = DACC_CHDR_CH1; //disable DAC1
    }

    int state = 0;
    const int STATE_OFF = 0;
    const int STATE_IDLE = 1;
    const int STATE_LISTEN_KEY = 2;
    const int STATE_PLAYER = 3;

    bool isLanguageKey(char customKey) {
      return ('A' == customKey || 'B' == customKey || 'C' == customKey || 'D' == customKey);
    }

    void loop() {
      switch (state) {
        case STATE_OFF:
        //listen for a telephone receiver to be removed
          if (hookOffState == 1) {
            interruptState = 0;
            state = STATE_IDLE;
                          }
                   else if (hookOffState == 0) {
                   }
            break;
        case STATE_IDLE:
        //listen for a language key. Cannot dial a number before
                   if (interruptState == 1) {
             isKeyPressed(); //get the key input
             buttonBeep();
            processLanguage();
            state = STATE_LISTEN_KEY;
                   }
                   else if (hookOffState == 0){
                    state = STATE_OFF;
                   }
                   else {
          playSound("intro.wav");
            }
          break;
        case STATE_LISTEN_KEY:
        //listen for any key
          if (isKeyPressed()) {
            interruptState = 0;
            if (isLanguageKey(key)) {
              buttonBeep();
              processLanguage();
            }
            else  {
              buttonBeep();
              keypresses[keyCounter] = key;
              keyCounter++;
              if (keyCounter > 4) {
                state = STATE_PLAYER;
                //when 5 numbers are pressed - try to open the .wav file
              }
            }
          }
                   else if (hookOffState == 0){
                    state = STATE_OFF;
                   }
          break;
        case STATE_PLAYER:
            //Play the audio and go back to state LISTEN
          calculateAndPlay();
          keyCounter = 0;
          interruptState = 0;
          state = STATE_LISTEN_KEY;
          break;
        default:
          break;
      }
    }

    void hookOffToggle() {     //detect a telephone receiver to be removed
    hookOffState = digitalRead(hookPinA);
    }

    void interruptToggle() {
        interruptState = 1;
    }

    bool isKeyPressed() {
      key = myKeypad.getKey();
      return key != NO_KEY;
    }

    bool langKeyPressed() {
      key = myKeypad.getKey();
      return key != NO_KEY && isLanguageKey(key);
    }

    void processLanguage() { //press A/B/C/D keys - select 1 out of 4 languages
      keyCounter = 0;
      if (key == 'A') {
        Serial.println("   LT    ");
      }
      if (key == 'B') {
        Serial.println("   EN    ");
      }
      if (key == 'C') {
        Serial.println("   LV    ");
      }
      if (key == 'D') {
        Serial.println("   RU    ");
      }
      language = key;
    }

    void buttonBeep(){
          for (int j = 0; j < 200; j++) {
            for (int i = 0; i < 200; i++)
              analogWrite(DAC0, i);
            for (int i = 200; i >= 0; i--)
              analogWrite(DAC0, i);
          }
    }

    void backgroundHumm() {
          for (int j = 0; j < 256; j++) {
            for (int i = 0; i < 256; i++)
              analogWrite(DAC0, j);
              for (int j = 256; j >= 0; j--) {
                for (int i = 256; i >= 0; i--)
              analogWrite(DAC0, j);
          }
      }
    }

    void calculateAndPlay() {
      //if we have 4+1 numbers - proceed
      //the keys pressed are stored into chars I convert them to int then i did some multiplication to get the code as an int of xxxx
      i1 = (keypresses[0] - 48) * 10000;
      i2 = (keypresses[1] - 48) * 1000;
      i3 = (keypresses[2] - 48) * 100;
      i4 = (keypresses[3] - 48) * 10;
      i5 = (keypresses[4] - 48) * 1;

      tot = i1 + i2 + i3 + i4 + i5;
      if (language == 'A') {
        if (tot == code1) //if the code is correct you trigger to play .wav
        {
          playSound("ledaiLT.wav");
        }
        else if (tot == code2)
        {
          playSound("zuvisLT.wav");
        }
        else if (tot == code3)
        {
          playSound("draugLT.wav");
        }
        else //if the code is wrong you get a beep and audio message
      {
          playSound("blogasLT.wav");
        }
      }
      if (language == 'B') {
        if (tot == code1) //if the code is correct you trigger to play .wav
        {
          playSound("ledaiEN.wav");
        }
        else if (tot == code2)
        {
          playSound("zuvisEN.wav");
        }
        else if (tot == code3)
        {
          playSound("draugEN.wav");
        }
        else //if the code is wrong you get a beep and audio message
        {
          playSound("blogasEN.wav");
        }
      }
      if (language == 'C') {
        if (tot == code1) //if the code is correct you trigger to play .wav
        {
          playSound("ledaiLV.wav");
        }
        else if (tot == code2)
        {
          playSound("zuvisLV.wav");
        }
        else if (tot == code3)
        {
          playSound("draugLV.wav");
        }
        else //if the code is wrong you get a beep and audio message
        {
          playSound("blogasLV.wav");
        }
      }
      if (language == 'D') {
        if (tot == code1) //if the code is correct you trigger to play .wav
        {
          playSound("ledaiRU.wav");
        }
        else if (tot == code2)
        {
          playSound("zuvisRU.wav");
        }
        else if (tot == code3)
        {
          playSound("draugRU.wav");
        }
        else //if the code is wrong you get a beep and audio message
        {
          playSound("blogasRU.wav");
        }
      }
    }

    // Playing assigned filename
    void playSound(const char* cName) {
      File myFile = SD.open(cName);
      const int S = 1024; // Number of samples to read in block
      short buffer[S];
      // until the file is not finished
      Serial.println("playing ");
      Serial.println(cName);

      Audio.begin(44100, 200);
      delay(200);
      while (myFile.available()) {
        myFile.read(buffer, sizeof(buffer));
        // Prepare samples
        int volume = 512;
        //max volume 1024
        Audio.prepare(buffer, S, volume);
        Audio.write(buffer, S);
       if ( interruptState ) break;
       else if ( hookOffState == 0 ) break;
      }
      Audio.end();
      myFile.close();
      delay(50);
      DACC->DACC_CHDR = DACC_CHDR_CH1; //disable DAC1
    }

body:
There is a bit of a problem here. You cannot simply use one diode.
There voltage is present on the keyboard pins only during getKey() function evaluation.

The keyboard works this way:
when you call a myKeypad.getKey(); then arduino does the following:
- changes the first column from input (high impedance) to output
- outputs 0V voltage to first column,
- scans all rows if they are 0V (normally they are pulled up - you know what pullup is).
- if any key in this column is pressed then the column voltage of 0V is pulling down the corresponding row voltage. That is there is a connection between row and column.

Here is the exact code:

  pin_mode(columnPins[c],OUTPUT);
  pin_write(columnPins[c], LOW); // Begin column pulse output.
  for (byte r=0; r<sizeKpd.rows; r++) {
   bitWrite(bitMap[r], c, !pin_read(rowPins[r]));  // keypress is active low so invert to high.
  }
  // Set pin to high impedance input. Effectively ends column pulse.
  pin_write(columnPins[c],HIGH);
  pin_mode(columnPins[c],INPUT);

It is not impossible to do this this way but it would require either modifying keyboard or creating a bit more complicated circuit. However it really does not make real sense.

I would do this different way: I would completely skip interrupt here. You are checking for a flag set inside interrupt:

    if ( interruptState ) break;

I would directly check here for the voltage on a specific pin. You have to (simply):
- set row pin (46 as far as I understand from your code) to output, and set it to low,
- set column pins (all of them) to input-pullup - as I understand
{44, 42, 40, 38}
- check if any of those pins is 'LOW', if yes - then break;

As far as I understand the library you don't even have to revert any pins back, the library re-initializes the pins correctly on every GetKey()

If for any reason the operation above takes too long you can shorten it using direct port manipulation as in https://forum.arduino.cc/t/arduino-due-how-to-direrct-port-access/251656 but note, that it is not as simple on Arduino Due as on AVR based ones.


sender: user

sender: assistant

body:
If you want to use interrupts, it requires a separate pin to detect the falling edge on column 4 (pin 38). In the following example, I used pin 28 for the column 4 interrupt. These can be connected together via a 1K resistor to protect against pin 28 inadvertently outputting low while the other is outputting high.

Pin 38 is pulled low during the call of `myKeypad.getKey()` thus triggering the ISR.

Working copies are made of the variables that are updated in the ISRs. This will require changes to the state machine to process `column4Pressed` obtained from the ISR.

```cpp
const byte hookPinA = 23;  // your interrupt pin
const byte interruptPin = 22;  // your interrupt pin

const byte column4InterruptPin = 28;  // Column 4 interrupt pin connected to column4Pin via a wire link. Could add a 1K series resistor to protect against short circuit to ground if it were output low when pin 38 is output high.
const byte column4Pin = 38;  // Column 4 pin connected to column4InterruptPin via a wire link.

// States updated by ISR.
volatile byte isr_hookOffState = 0;
volatile byte isr_interruptState = 0;
volatile bool isr_column4Pressed = false;

// Working copies of ISR data.
byte hookOffState = 0;
byte interruptState = 0;
bool column4Pressed = false;

// Use a single byte for the state variable and initialise it to OFF.
enum class State : byte
{
    OFF = 0,
    IDLE = 1,
    LISTEN_KEY = 2,
    PLAYER = 3
} state = State::OFF;

void setup()
{
    pinMode(hookPinA, INPUT_PULLUP);
    attachInterrupt(digitalPinToInterrupt(hookPinA), hookOffToggle, CHANGE);

    pinMode(interruptPin, INPUT);
    attachInterrupt(digitalPinToInterrupt(interruptPin), interruptToggle, RISING); // test interrupt with a regular button

    pinMode(column4InterruptPin, INPUT_PULLUP);
    attachInterrupt(digitalPinToInterrupt(column4InterruptPin), interruptColumn4, FALLING);  // Triggered by pulling column 4 low, e.g. digitalWrite(column4Pin, LOW) or within myKeypad.getKey().
}

void loop()
{
    // Get a fresh copy of the ISR data and reset the interrupt state flag atomically
    // by temporarily disabling interrupts.
    cli();
    hookOffState = isr_hookOffState;
    interruptState = isr_interruptState;
    column4Pressed = isr_column4Pressed;
    isr_interruptState = 0;  // Reset to detect next interrupt.
    isr_column4Pressed = false; // Reset to detect next interrupt.
    sei();

    // Alternative method to test whether any button in column 4 is pressed.
    // This is how to do it without using interrupts.
    /*
    pinMode(column4Pin, OUTPUT);
    digitalWrite(column4Pin, LOW);
    column4Pressed = !digitalRead(52) || !digitalRead(50) || !digitalRead(48) || !digitalRead(46);
    digitalWrite(column4Pin, HIGH);
    pinMode(column4Pin, INPUT);
    */

    // Process the working copies of the ISR data.
    // You will need to change the state machine logic to process column4Pressed obtained from the ISR.

    switch (state)
    {
    case State::OFF:
        break;
    case State::IDLE:
        break;
    case State::LISTEN_KEY:
        break;
    case State::PLAYER:
        break;
    }
}

void hookOffToggle()
{
    isr_hookOffState = digitalRead(hookPinA);
}

void interruptToggle()
{
    isr_interruptState = 1;
}

void interruptColumn4()
{
    // Test whether any button in column 4 is pressed.
    isr_column4Pressed = !digitalRead(52) || !digitalRead(50) || !digitalRead(48) || !digitalRead(46);
}
```

Here is the Wokwi simulation which uses an Arduino Mega and pin 2 for the column 4 interrupt. Note that there is no protection resistor between pins 2 and 38. The Wokwi simulator will create a Value Change Dump (VCD) file for viewing in your favourite trace analyser:

Alternatively, if you don't want to use interrupts, you could pull column 4 (pin 38) low and test the row pins for a logic low. See the commented code in `loop()`.


message:
Need help in writing a function

I am reading an accelerometer using arduino. Basically i receive positive values and I need to get only first row of negative values.
E.g. I receive values > -0.5 , then I start to have values < -0.5 (which i put them into an array , and then in case I get again values greater than -0.5 I want to stop it.

Also if in 30 seconds it should stop anyway.
This is what I did till now but is not working like expected

    void reading_mpu_brake(){
              unsigned long StartTime = millis();

          float acc[500];
          int read_time[500];

          byte arrayIndex = 0;

        while(1){
          unsigned long CurrentTime = millis();
          if (CurrentTime - StartTime < interval) {
            mpu.update();
            if (mpu.getAccX() < -0.05){
              total_acc = sqrt((pow((mpu.getAccX() - offsetx), 2) + pow((mpu.getAccY() - offsety), 2) + pow((mpu.getAccZ() - offsetz), 2) ));

              acc[arrayIndex] = total_acc;
              read_time[arrayIndex] = millis();

              Serial.print(acc[arrayIndex]);
              Serial.print(" | ");
              Serial.print(mpu.getAccX());
              Serial.print(" | ");
              Serial.println(read_time[arrayIndex]);
              Serial.println(arrayIndex);
               arrayIndex++;
            }
          }
          else if (CurrentTime - StartTime > interval)
          {
            Serial.println("Over time");
            break;

          }

        }

Now is working and get values less than -0.5 but if after several good values if I get positive values and then again negative it will put in array also the last one which I don t.

So basically I need to stop it after first bunch of good values...

Any help appreciated

Thank you!

L.E.
Seems I miss a good explanation so I will try again.

1 - I call the function and it start monitoring values for 30 seconds.

Case 1 :
I receive 0.6 , 0.7 , 0.4 , 0.2 , -0.2 , -0.6 , -0.7 , -0.8 , -0.4 , 0.3 , 0.5 ...etc

In this case I get into acc array values : -0.6 , -0.7 , -0.8
then after 30 sec gone the function exit

That is OK partially .

Case 2 :
I receive 0.6 , 0.7 , 0.4 , 0.2 , -0.2 , -0.6 , -0.7 , -0.8 , -0.4 , 0.3 , 0.5 , -0.6 , -0.7 , 0.6...etc

In this case I get into array values -0.6 , -0.7 , -0.8  and if the 30 secs are not gone I also get -0.6 , -0.7 .

What I want is function to exit after get first bunch of good values (-0.6 , -0.7 , -0.8) .

Hope now is more clear

body:
    float acc[500];
    int read_time[500];

Right, so a float is 4 bytes on this platform, so that array takes 2000 bytes. And an int is 2 bytes, so that other array is another 1000 bytes.

The Uno has 2KB of RAM, so those two declarations alone take up more RAM than the device has.

I'm a little surprised it works at all, but certainly "not working as expected" is indeed an expected outcome here.


message:
'GIMSK' was not declared in this scope

I'm programming an ATTiny 85 using the Arduino IDE and an Arduino Nano as "Arduino as ISP" to program the ATTiny. I succeeded a week ago and now I want to program a second chip but get the `'GIMSK' was not declared in this scope` error during compile.

The GIMSK is called at the start of the `sleep()` function. I tried adding `#include <avr/interrupt.h>` but continue to receive the compile error.

    #include <avr/sleep.h>    // Sleep Modes
    #include <avr/power.h>
    #include <elapsedMillis.h>
    const int hallPin = 2;     // the number of the hall effect pin
    const int magnetPin =  1;      // the number of the magnet pin
    const long debouncing_time = 15; //Debouncing Time in milliseconds
    // variables will change:
    volatile int hallState = 0;         // variable for storing the hall counter
    volatile unsigned long last_micros;
    elapsedMillis timer;

    void setup()
    {
      pinMode(magnetPin, OUTPUT);
      pinMode(hallPin, INPUT);
      digitalWrite(hallPin, HIGH);    // pullup enabled.
      // Attach an interrupt to the ISR vector
      attachInterrupt(0, pin_ISR, RISING); //default interupt pin is always 0 on attiny85 (physical pin 7)
      timer = 0;
    }

    void sleep()
    {
        GIMSK |= _BV(PCIE);                     // Enable Pin Change Interrupts
        PCMSK |= _BV(PCINT2);                   // Use PB2 as interrupt pin
        ADCSRA &= ~_BV(ADEN);                   // ADC off
        set_sleep_mode(SLEEP_MODE_PWR_DOWN);    // replaces above statement
        sleep_enable();                         // Sets the Sleep Enable bit in the MCUCR Register (SE BIT)
        sei();                                  // Enable interrupts
        sleep_cpu();                            // sleep
        cli();                                  // Disable interrupts
        PCMSK &= ~_BV(PCINT2);                  // Turn off PB2 as interrupt pin
        sleep_disable();                        // Clear SE bit
        ADCSRA |= _BV(ADEN);                    // ADC on
        sei();                                  // Enable interrupts
    } // sleep
    etc.

Can anyone give me a pointer? I had saved my work so I'm puzzled by the error.

Thank you.

----

Solution:

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

*Programming configuration for the ATTiny 85 via the Nano as ISP.*

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

body:
In order to program the ATtiny85, you need a suitable board support
package, and you have to configure the Arduino IDE in order to target
that specific chip.

From the description of your issue, it sounds like you did that a week
ago, and then, maybe by accident, you undid the IDE configuration. Now
the IDE is targeting a type of MCU that does not have a register named
`GIMSK`. Double check that you have the right target configured.

Another possibility would be that the Arduino.h file for the core you
are using does not automatically include avr/io.h. If this is the case,
add

```c
#include <avr/io.h>
```

at the top of your code.


message:
I can change value of only one register on 8-Bit Register integrated circuit (74hc273 / DM74LS273)?

First, please be patient, I'm not electronical person. I am learning Arduino and electronics for hobby and this is my fist time with integrated circuits.

- Situation: I'm want to extend the Arduino Nano pins (De/Multiplexer) and keep the state (High/Low) of the new pins until I decide to change it again. For keep the states I think that D-type Flipflop memory-based system can help .
- **Question 1**: On this system can  I change only one bit with a unique signal or need to set all bit states ?
- Example (reference image):

1) Memory, previous state: `Q0=0, Q1=1, Q2=1, Q3=0`
2) Arduino: **Set pin17** (D2) **to High** -> Memory: Waiting new data.
3) Arduino: **Set pin16** (D3) **to High** -> Mux: Pass the value to memory at **D0**
4) Memory: **Read 1 on D0** (this is my doubt. D1, D2 and D3 don't matter ?)
5) Arduino: **Set pin17** (D2) **to LOW** -> Memory: Save new data
6) Memory, new state: `Q0=1, Q1=1, Q2=1, Q3=0` ? ***or*** `Q0=1, Q1=0, Q2=0, Q3=0` ?

**Question 2**: Are this correct ?
**Question 3**: Are there a more efficient way to do this?

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

**Notes:**
- I used a simulator to diagramed the memory based on this datasheet: https://pdf1.alldatasheet.com/datasheet-pdf/view/8337/NSC/74273.html It seems that it is possible, but I want to be sure.
- My currently solution is use separated flipflops, but I want to simplify it.
- Connections on reference image are simplified.
- Sorry about the poor diagram, I don't know programs for beautiful electronical diagrams.
- Sorry about typos, not-native English person here.

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

body:
**Question 1** and **Question 2**: I was wrong, this is not the correct way. *@jsotola* and *@the_busybe*e, thanks for the clarification

**Question 3**: *@Nick_Gammon* and *@Majenko* I think you are right, using i2c are more efficient ways to do. But, the *@StarCat* proposal is more compatible with my current solution. **74hc259** allows me set the state one by one and keep it until I change it again.


message:
Why do I have to burn the code to make it run?

Why do I have to burn the code twice to actually burn it on to the Arduino board? I have to execute this command twice - only *then* is the chip getting programmed.

I'm using this command to burn the program into the Arduino Uno board using a Rasp Pi 3, via SSH from Windows 10.
```
avr-gcc -mmcu=atmega328 filename.c | avr-objcopy -O ihex -j .text -j .data a.out a.hex | avrdude -C avrdude.conf -v -p atmega328p -c arduino -P /dev/ttyACM* -b 115200 -D -U flash:w:a.hex:i
```

body:
On a Unix shell, separating commands with the pipe character (`|`) means
“run these commands in parallel, feeding the standard output of each one
to the standard input of next one”.

In this context, it makes no sense to use pipes, as both avr-objcopy and
avrdude read their data from files, not from stdin. Furthermore, running
these in parallel means that avrdude will _not_ have access to a.hex
when it starts.

The solution is to run the commands _sequentially_ instead of in
parallel. Type and run one command at a time.

Alternatively, if you really want to have everything in a single line,
separate the commands with a semicolon (`;`, meaning “run the next
command when the previous one is done”) or, better yet, double ampersand
(`&&` = “run the next command only if the previous one exits
successfully”).


message:
Arduino How can I add 30s delay and turn off the led to the following code

const int buttonPin =  2;
    boolean currentState = LOW;
    boolean lastState    = LOW;
    boolean stateChange  = false;

    int currentButton = 0;
    int lastButton    = 4;
    int ledArray[]    = {9, 10, 11, 12};
    long previousMillis = 0;
    long interval = 1000 ;

    void setup() {
            pinMode(buttonPin, INPUT);
            for (int i=0; i<5; i++){
                pinMode(ledArray[i],OUTPUT);
            }
            Serial.begin(9600);
    }

    void loop(){
                currentState = debounceButton();
                stateChange = checkForChange(currentState, lastState);
                currentButton = getButtonNumber(lastButton, currentState, stateChange);
                indicatorLight(currentButton);
                lastState  = currentState;
                lastButton = currentButton;
    }

    boolean debounceButton()
                {
                boolean firstCheck   = LOW;
                boolean secondCheck  = LOW;
                boolean current = LOW;
                firstCheck  = digitalRead(buttonPin);
                delay(50);
                secondCheck = digitalRead(buttonPin);
                        if (firstCheck == secondCheck){
                            current = firstCheck;
                        }
                return current;
    }

    boolean checkForChange(boolean current, boolean last)
            {
            boolean change;
                    if (current != last){
                        change = true;
                    }
                            else {
                            change = false;
                            }
                    return change;
    }

    int getButtonNumber(int button, boolean state, boolean change)
                {
                if (change == true && state == LOW){
                    button++;
                            if (button > 3){
                            button = 0;
                            }
                            Serial.println("g");

                }
                return button;
    }

    void indicatorLight(int button)
             {
                    for (int i=0; i<4; i++) {
                                digitalWrite(ledArray[i], LOW);
                            }
                            digitalWrite(ledArray[button], HIGH);
      }

body:
You have the right idea to debounce the buttons, but there is a 50 ms delay per button which blocks the loop for a total of 200 ms with four buttons.

So consider using a non-blocking debouncer of which there are many examples on the internet, but here is a [simple debouncer][1] I put on GitHub. It could be implemented something like the following example:

```cpp
#include "debouncer.h"

const uint16_t LED_OFF_TIME_DELAY_ms = 2000;  // milliseconds. For testing.
//const uint16_t LED_OFF_TIME_DELAY_ms = 30000;  // milliseconds.

struct ButtonLed
{
  Debouncer button;
  byte button_pin;
  byte led_pin;
};

const ButtonLed BUTTONS_LEDS[] =
{
  { Debouncer(5, 50, LED_OFF_TIME_DELAY_ms), 5, 11 },
  { Debouncer(4, 50, LED_OFF_TIME_DELAY_ms), 4, 10 },
  { Debouncer(3, 50, LED_OFF_TIME_DELAY_ms), 3, 9 },
  { Debouncer(2, 50, LED_OFF_TIME_DELAY_ms), 2, 8 }
};

void setup()
{
  for (const auto& button_led : BUTTONS_LEDS)
  {
    pinMode(button_led.button_pin, INPUT_PULLUP);
    pinMode(button_led.led_pin, OUTPUT);
    digitalWrite(button_led.led_pin, LOW);
  }
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop()
{
  uint16_t timestamp = millis();

  //
  // TASK 1: Read the buttons and set their corresponding LEDs.
  //

  for (const auto& button_led : BUTTONS_LEDS)
  {
    button_led.button.Update();
    if (button_led.button.Fall())
    {
      digitalWrite(button_led.led_pin, HIGH);
    }
    else if (button_led.button.RepeatCount() == 1)
    {
      digitalWrite(button_led.led_pin, LOW);
    }
  }

  //
  // TASK 2: Blink the inbuilt LED.
  //

  const uint16_t LED_BLINK_INTERVAL = 100;
  static uint16_t led_blink_previous_timestamp = timestamp;
  static bool led_state = false;
  if (timestamp - led_blink_previous_timestamp >= LED_BLINK_INTERVAL)
  {
    led_state = !led_state;
    digitalWrite(LED_BUILTIN, led_state);
    led_blink_previous_timestamp += LED_BLINK_INTERVAL;
  }
}
```

And here it is in action in the Wokwi simulator:

  [1]: https://github.com/TimMathias/Arduino-Debouncer/


message:
How to light up middle points in a display with 4 digits?

How to light up the two points that is in the middle? It only lights up when the `digB` is set to `LOW`, and it lights up all 3 points that is in the middle.

[![Item][1]][1]

Example code:

    const int displayPins[] = {2,3,4,5,6,7,8,9,10,11,12,13};
    const int digA = 7;
    const int digB = 4;
    const int digC = 3;
    const int digD = 8;
    const int decimalPoint = 10;

    void setup() {
     for (int i = 0; i < (sizeof(displayPins)/sizeof(displayPins[0])); i++) {
      pinMode(displayPins[i], OUTPUT);
     }

     digitalWrite(digA, 1);
     digitalWrite(digB, 0);
     digitalWrite(decimalPoint, 1);
     digitalWrite(digC, 1);
     digitalWrite(digD, 1);
    }

    void loop() {
    }

I want to display a clock in this format: 00:00. But did not found a way to light up the two points that is in the middle.

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

body:
It is not possible to separate the colon dots from the decimal point dot - they are all wired together in parallel internally:

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

As has been mentioned in the comments you need to use the "black tape" method of selecting the LEDs. That's not a joke, that's really what's done. Cover the LED that you don't want visible with black tape (or black paint, etc).

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


message:
DS3231 RTC not working with ESP32

I am using ESP-32-WROOM-32 with a RTC DS3231 module. I have connected SDA & SCL pins of RTC DS3231 with ESP32 D22 and D23 pins. Also, the VCC of RTC is connected to 3V3 of ESP32 and the GND of RTC is also connected to GND of ESP32  .RTC module is having attached battery also.

Following is the code:
```
#include <Wire.h> // for I2C with RTC module
#include "RTClib.h" //to show time

RTC_DS3231 rtc;

void Scanner ()
{
  Serial.println ();
  Serial.println ("I2C scanner. Scanning ...");
  byte count = 0;

  Wire.begin(22,23);
  for (byte i = 8; i < 120; i++)
  {
    Wire.beginTransmission (i);          // Begin I2C transmission Address (i)
    if (Wire.endTransmission () == 0)  // Receive 0 = success (ACK response)
    {
      Serial.print ("Found address: ");
      Serial.print (i, DEC);
      Serial.print (" (0x");
      Serial.print (i, HEX);     // PCF8574 7 bit address
      Serial.println (")");
      count++;
    }
  }
  Serial.print ("Found ");
  Serial.print (count, DEC);        // numbers of devices
  Serial.println (" device(s).");
}
void setup()
{
    // put your setup code here, to run once:
    Wire.begin(22,23);
    //Wire.begin();
    Serial.begin(115200);
         while(!Serial);

       ////////////////////////////////////

    ////////////////////////////////////////

    while (!rtc.begin())
    {
        Serial.println("Couldn't find RTC");
        Scanner();
        //Serial.println(DS3231_REG_STATUS);
        //        while (1)
        //        {
        //                  Serial.println("Couldn't find RTC");
        //
        //        }

        ;
    }
    Serial.println("Finally");
    // In setup function, we will call a function rtc.adjust(DateTime(__DATE__, __TIME__)) which will set the time according to our PC time.
    rtc.adjust(DateTime(__DATE__, __TIME__));
}
void loop()
{

    DateTime curr_time_obj = rtc.now();
    int day = curr_time_obj.day();
    int month = curr_time_obj.month();
    int year = curr_time_obj.year();
    int week_day = curr_time_obj.dayOfTheWeek();
    int sec = curr_time_obj.second();
    int hr = curr_time_obj.hour();
    int minute = curr_time_obj.minute();

    Serial.print("hour is ");
    Serial.println(hr);
    Serial.print("min is ");
    Serial.println(minute);
    Serial.print("secs is ");
    Serial.println(sec);
    Serial.println("############################");
    delay(5000);
}

```
Following is the output:
[![enter image description here][1]][1]

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

Some of the images of the circuit can be found here: https://drive.google.com/drive/folders/1fhM7o_aZCGh88OBDcypVLqhKhizhXnNd?usp=sharing

I would appreciate any help to resolve this issue.
Thanks

body:
Warning

These modules normally come with a 200Ω resistor soldered next to the IN4148 Zener diode, as you can see in the image below.

ds3231 module problem fix
The resistor and diode form a simple charging circuit designed for use with LIR2032 rechargeable batteries.

Be aware that some DS3231 modules come with a non-rechargeable CR2032 battery. If this is the case, you must remove the resistor because attempting to charge a non-rechargeable battery can cause serious damage.

> Blockquote

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

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


message:
Powering Atmega328p from 4.5V

I want to use Atmega328p controller to handle some very simple signals. I'm using the chip and not the whole arduino board because it is a lot cheaper. The problem is that chip itself doesn't have voltage regulator so I need to think of a rechargeable power source. My idea is to use 3 rechargeable AA batteries (~4.5V). I read that it can handle somewhere from 1.5V to 5.5V but I also read that clock speed is then reduced and a lot other complications. So, finally, the question, If I were to use described power source, what challenges should I be ready to face and how will it impact the performance and is it even possible to pull it off.

body:
From the ATmega328P datasheet:

[![Maximum Frequency vs. Vcc][1]][1]

Within the range 2.7 V – 4.5 V, the maximum frequency is a
linear function of Vcc. From this graph, you can compute the minimum
value of Vcc required to run the microcontroller at 16 MHz: it's
3.78 V.

If you do want to run at 16 MHz, in order to emulate an Arduino
Uno, it may become unreliable once the supply voltage drops below
3.78 V, i.e. 1.26 V per cell. Whether this is a serious issue or
not depends on the cell chemistry. For reference, alkalines reach about
1 V at the end of their useful life, and NiCd has about 1.2 V
when fully charged. You will have to find the relevant voltage for the
chemistry you plan to use.

If you can afford running the microcontroller at 8 MHz, then you
will most certainly be safe.

**Edit**: If you want to run the microcontroller at 8 MHz, and you
are programming it with the Arduino IDE, you have to select a
board/processor combination that runs at 8 MHz. For example,
“Arduino Pro or Pro Mini” / “ATmega328P (3.3V 8MHz)”. This will ensure
that the time-related functions (`millis()`, `delay()`, etc.) and the
baudrates of `Serial.begin()` provide the correct timings. Other than
that, the drawback of running at a lower clock speed is that the
CPU-bound functions (computations) take twice as long.

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


body: They make SEPIC converters that will hold the voltage at 5V for you. The reason for the SEPIC is during charge what happens to the battery voltage and especially if the battery open circuits. If there is no chance for the battery voltage to go to high a boost converter will work just fine. This solution will allow it to run at full speed without degrading performance etc. The new converters are not very expensive and are generally greater than 95% efficient depending on the unit. If you can up the battery voltage things will get a lot more efficient but you would then need to change the boost to a buck, the SEPIC would be fine. I tend to use the China Nanos, they are inexpensive, probably less then your parts and readily available. I have not had problems with them. I like to supply them with about 8 volts via Vin, that gives me the additional filtering of the onboard power supply.


message:
ATtiny85 plugin and removed it self

So I bought ATtiny85 recently, when I plug it to my PC it make sound like mouse has been plugin, but then it make sound like the device has been removed. It happen again and again until I remove the device. Is it the device problem or am I missing something? Can I fix it?

body:
I'm assuming you've bought a [Digispark (or compatible) ATTiny85 USB board](http://digistump.com/products/1).

The sound of a USB device inserting and removing is normal. When the digiSpark boots it listens to the USB bus for a short period so you can upload your sketches. Then it proceeds to boot your sketch.

If no sketch has been uploaded, it might just reboot until you upload one. The Digisparks I have, have all had a "blink" sketch preloaded but yours may not.

The "problem" will go away when you start running your own sketches. It will then only announce itself once and then remove itself from the USB bus, unless your sketch also communicates via the USB bus.


message:
ESP8266: error: 'getLocalTime' was not declared in this scope

I am getting

> error: 'getLocalTime' was not declared in this scope

when I am compiling this code for ESP8266, however works for ESP32:
```
#include "time.h"

void gettime()
{
  static int16_t delaycount = 0 ;                         // To reduce number of NTP requests
  static int16_t retrycount = 100 ;

  if ( timeinfo.tm_year )                                 // Legal time found?
  {
    sprintf ( timetxt, "d:d:d",                  // Yes, format to a string
              timeinfo.tm_hour,
              timeinfo.tm_min,
              timeinfo.tm_sec ) ;
  }
  if ( --delaycount <= 0 )                                // Sync every few hours
  {
    delaycount = 7200 ;                                   // Reset counter
    if ( timeinfo.tm_year )                               // Legal time found?
    {
      dbgprint ( "Sync TOD, old value is %s", timetxt ) ;
    }
    dbgprint ( "Sync TOD" ) ;
    if ( !getLocalTime ( &timeinfo ) )                    // Read from NTP server
    {
      dbgprint ( "Failed to obtain time!" ) ;             // Error
      timeinfo.tm_year = 0 ;                              // Set current time to illegal
      if ( retrycount )                                   // Give up syncing?
      {
        retrycount-- ;                                    // No try again
        delaycount = 5 ;                                  // Retry after 5 seconds
      }
    }
    else
    {
      sprintf ( timetxt, "d:d:d",                // Format new time to a string
                timeinfo.tm_hour,
                timeinfo.tm_min,
                timeinfo.tm_sec ) ;
      dbgprint ( "Sync TOD, new value is %s", timetxt ) ;
    }
  }
}
```

What shall I replace getLocalTime with?

body:
It looks like the esp8266 Arduino core don't have a similar function.

The getLocalTime in esp32 arduino core is a simple function implemented in esp32-hal-time.c.

```
bool getLocalTime(struct tm * info, uint32_t ms)
{
    uint32_t start = millis();
    time_t now;
    while((millis()-start) <= ms) {
        time(&now);
        localtime_r(&now, info);
        if(info->tm_year > (2016 - 1900)){
            return true;
        }
        delay(10);
    }
    return false;
}
```

The function compiles on esp8266 arduino as it is so you can copy it to your sketch.


message:
Problem in upload bootloader into esp32

I have problem with my esp32 Device and asked one question as you can see below:

[How to understand the ESP32 is working (Error: Arduino unknown board ...)][1]

As it is not fixed, so I am thinking to upload the bootloader codes on the ESp32.
SO I have tried the ArduinoISP example codes and tried to  use the bootloader icon on Arduino, but it doesn't work,
and I get below error:
```
java.lang.NullPointerException
 at cc.arduino.packages.uploaders.SerialUploader.burnBootloader(SerialUploader.java:329)
 at processing.app.Editor.lambda$handleBurnBootloader$61(Editor.java:2379)
 at java.base/java.lang.Thread.run(Thread.java:829)
Error while burning bootloader.
```
Also, the whole process is show below:

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

So I have asked here for some comments or answers.

Thanks.

  [1]: https://arduino.stackexchange.com/questions/85880/how-to-understand-the-esp32-is-working-error-arduino-unknown-board
  [2]: https://i.stack.imgur.com/61tol.jpg

body:
1) esp32 has a fixed bootloader in read only memory. it is not replaceable

2) ArduinoISP sketch is a programmer only for classic ATmega MCU boards

3) in valid case you would have to select the programmer in Tools menu before using Burn Bootloader. (There are no options in your Programmer menu, because no programmers are defined for esp32 boards package)


message:
ESP32 programing error (A fatal error occurred: Timed out waiting for packet content )

I am trying to find the proper model of my esp32 MCU and find out the reason for below errors:

```
esptool.py v3.1-dev
Serial port /dev/ttyUSB0
Connecting........__
Chip is ESP32-D0WDQ6 (revision 1)
Features: WiFi, BT, Dual Core, Coding Scheme None
Crystal is 40MHz
MAC: 30:ae:a4:26:6f:44
Uploading stub...
Running stub...
Stub running...
Changing baud rate to 921600
Changed.
Configuring flash size...

A fatal error occurred: Timed out waiting for packet content
A fatal error occurred: Timed out waiting for packet content

```
My ESP32 type and the board setting are shown below ([link][1]) :

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

Thanks.

  [1]: https://www.aliexpress.com/item/32656775273.html
  [2]: https://i.stack.imgur.com/lUBwv.jpg

body: In case where the upload procedure with esptool.py starts successfully but fails as soon as the baud rate is set to the high baud rate selected in Tools menu, select a lower baud rate in Tools menu.


body: This can also be caused by how certain pins are wired, if pin 12 is high at boot, programming will also fail with this message.


message:
ATtiny85 won't wake from sleep

My ATtiny 85 won't wake up!

The purpose of the device is to monitor a reed switch and give a 20 ms output pulse on every alternate positive-going transition of the reed switch input. The device should go to sleep after 30 s of inactivity. It should wake up on reed switch activity (rising or falling edge).

```
/*
          ATMEL ATTINY 85
              +-\/-+
        PB5  1|    |8  Vcc
        PB3  2|    |7  PB2 (INT0) reed switch input (1 MΩ ext. pull-up)
        PB4  3|    |6  PB1        output
        GND  4|    |5  PB0
              +----+
*/
#include <avr/sleep.h>
#include <avr/power.h>
#include <elapsedMillis.h>

const int hallPin = 2;            // Reed switch in this case.
const int magnetPin =  1;         // Output.
const long debouncing_time = 15;  // Debouncing time in milliseconds.

volatile int hallState = 0;       // variable for storing the hall counter
volatile bool hallMem = 0;        // One-shot memory.
volatile unsigned long last_micros;

elapsedMillis timer;

void setup(){
  pinMode(magnetPin, OUTPUT);
  pinMode(hallPin, INPUT);
  // Attach an interrupt to the ISR vector. DO I NEED THIS?
//  attachInterrupt(0, pin_ISR, RISING); //default interupt pin is always 0 on ATtiny85 (physical pin 7).
  timer = 0;                             //Reset the timer
}

void loop(){
  if(digitalRead(hallPin) && !hallMem){
    hallMem = true;               // One-shot memory.
    hallState++;
    delay(debouncing_time);       // Keep it simple.
    timer = 0;
  }
  if(!digitalRead(hallPin)){
    hallMem = false;              // Allow re-trigger.
  }
  if(hallState > 1) {
      digitalWrite(magnetPin, HIGH);        // Send 20 ms pulse to sensor activation coil.
      delay(20);
      digitalWrite(magnetPin, LOW);
      hallState = 0;                        // Reset the trigger.
  }
  if(timer >= 30000) {                      // No activity.
    system_sleep();
  }
}

// From http://interface.khm.de/index.php/lab/experiments/sleep_watchdog_battery/
void system_sleep() {
  GIMSK |= _BV(PCIE);                     // Enable Pin Change Interrupts
  PCMSK |= _BV(INT0);                     // Use INT0 (PB2) as interrupt pin
  ADCSRA &= ~_BV(ADEN);                   // ADC off
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);    // replaces above statement

  sleep_enable();                         // Sets the Sleep Enable bit in the MCUCR Register (SE BIT)
  sei();                                  // Enable interrupts
  sleep_cpu();                            // sleep

  cli();                                  // Disable interrupts
//  PCMSK &= ~_BV(INT0);                  // Turn off INT0 (PB2) as interrupt pin
  sleep_disable();                        // Clear SE bit
  ADCSRA |= _BV(ADEN);                    // ADC on

  sei();                                  // Enable interrupts

  timer = 0;          // Reset the sleep timer on wake-up.
}

ISR(PCINT0_vect) {
}
```
Can anyone spot my error that is preventing a wake-up?

What is the ADC enabling instruction doing? Do I need it?

Many thanks.

body:
I believe your problem lies here:

```c
PCMSK |= _BV(INT0);  // Use INT0 (PB2) as interrupt pin
```

You seem to have mixed up two sorts of interrupts:

1. INT0 (External Interrupt), which only works on pin INT0 (i.e. PB2)
   and can sense low-level, rising edge, falling edge, or any change.

2. PCINT0 (Pin Change Interrupt), which works on any IO pin, but can
   only sense “any change”.

Since you are sleeping in PWR\_DOWN mode, pin change interrupt is the
appropriate choice. All your program is consistent with this choice but
for the line above.

The `INT0` macro has the value 6. It represents bit 6 of `GIMSK`, which
is used to enable the INT0 interrupt. Not what you want. Bit 6 of
`PCMSK` is reserved, so you are not supposed to touch it. If you want
the pin change interrupt to sense changes in pin PB2 (aka PCINT2), you
instead have to:

```c
PCMSK |= _BV(PCINT2);  // sense changes in PCINT2 = PB2
```


message:
Expected signature for ATmega328P is 1E 95 0F; I can not burn bootloader on my arduino Uno

well...
the problem starts from the time that I accidentally touched the crystal on my arduino and all of a sudden everything messed up; the leds on arduino turned on and off while being touched, and after that I was unable to program it...
after a lot of searches, I decided t burn bootloader again...
so I got a USBasp and wired it to arduino and tried to program it using programmer or burning bootloader...
but...
It is not posible because of the following ERROR:

    **Arduino: 1.8.15 (Windows 10), Board: "Arduino Uno"

    avrdude: warning: cannot set sck period. please check for usbasp firmware update.

    avrdude: Expected signature for ATmega328P is 1E 95 0F

             Double check chip, or use -F to override this check.

    Error while burning bootloader.**

I tried changing that 0xF in config file to 0x14, because of the difference between ATmega328 and ATmega328p...
but still no progress...
I will be very glad if someone can help me run this UNO...

by the way, is it possible that the crystal which I touched with hand is ruined or interrupted and all of these stuff is because of that?

body:
Well a couple of options:

- Plug the Arduino with USB, do you see a Serial PORT? If you do there is a good chance the USB CHIP is ok.
- Try programming the Arduino with a 12v High Voltage Programmer and burn a 8Mhz Internal oscillator bootloader and see if it works, if it does, the the crystal is damaged.
- Another alternative, e to use a 16mhz crystal and put it in parallel with that one, see if you can flash it like that, or just desolder that one and replace with a new one, doesn't matter if it's the same freq, you still be able to burn a bootloader, hopefully choose a osc that is supported by the bootloaders (8, 12, 16, 20) for example


message:
Unable to find headers from installed platformio library

I wrote a library that I intend to use in several project and I published it via platform.io's library management system.

https://platformio.org/lib/show/12820/FastLED-SectionManager

This is the first time I've published via platform.io (first time I've published any c++ library). I read over [platform.io's docs on creating a library](https://docs.platformio.org/en/latest/librarymanager/creating.html) and structured my library accordingly with my headers in the `include` directory and the implementation files in the `src` directory:

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

And created the following library.json file:

```
{
  "name": "FastLED-SectionManager",
  "version": "1.0.2",
  "description": "A led strip index manager that allows for logical groupings of strip sections.",
  "repository": {
    "type": "git",
    "url": "git@github.com:chris-schmitz/FastLED-Section-Manager.git"
  },
  "authors": [
    {
      "name": "Christopher Schmitz",
      "email": "schmitz.chris@gmail.com",
      "url": "https://light-inspiration.com/"
    }
  ],
  "homepage": "https://github.com/chris-schmitz/FastLED-Section-Manager",
  "license": "MIT",
  "dependencies": {
    "fastled/FastLED": "^3.4.0"
  },
  "frameworks": "*",
  "platforms": "*"
}
```

The problem that I'm running into is that when I install the library in a different project via platform.io and try to include a header, the header can't be found:

[![can't find header][2]][2]

I double checked in the `pio` directory for the project and I can definitely see the header and implementation files:

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

So I'm not sure why platform.io can't find the headers.

I can't quite tell what I'm doing wrong. any ideas?

  [1]: https://i.stack.imgur.com/47j1W.png
  [2]: https://i.stack.imgur.com/C2m7k.png
  [3]: https://i.stack.imgur.com/Wp7xi.png

body:
I woke up this morning and looked back at the documentation.

A part I mis-read was this:

> We recommend to use src folder for your C/C++ source files and **include folder for your headers**. You can also have nested sub-folders in src or include.

I had my headers stored in the `lib` folder :facepalm:

I tried to search around in the platformio docs for the explanation of the lib vs include vs src folders (I knew I saw it at one point) but couldn't find it.

I then remembered that I read the purpose of each directory in the Readme files in the project structure itself generated when you create a new platformio project:

[![readmes][1]][1]

The gist being:

- `src`: your compiled files, i.e. your `cpp` files
    - It's worth noting that you could just shove all of the files in here and it would work
- `lib`: libraries private to your project/library itself
- `include`: declaration and macro definition files, i.e. your header files

This explains how the header files in the `lib` directory worked in the SectionManager project itself but didn't work when using the SectionManager as an installed library; the `lib` directory is only "visible" local to a project, so when I tried to include the header files from another project they couldn't be found.

So in my SectionManager project I moved the headers to the `include` directory, bumped the version number, and published:

[![update to lib directory][2]][2]

Then I switched to my main project that I'm pulling the SectionManager library into, adjusted the dependency version to include the minor bump, updated, and now it works!

[![works!][3]][3]

Makes sense, I'm just still getting used to c++ and platform.io.

  [1]: https://i.stack.imgur.com/5hBkX.png
  [2]: https://i.stack.imgur.com/yNldk.jpg
  [3]: https://i.stack.imgur.com/VNK2i.png


message:
My PN532 doesn't detect RFID card when connected with ESP32 in I2C mode while it works perectly with Arduino Uno

I have a Elechouse PN532 module (bought here - https://robu.in/product/pn532-nfc-rfid-read-write-module-v3-kit/). When I try to use to it with I2C and connect it to my ESP32 (DOIT ESP32 DEV KIT V1, 30 pin version), the PN532 gets detected but it doesn't detect when a card or token shown to it. When I try the exact same code with Arduino Uno with I2C, it works flawlessly. Below are the connections for both boards, the code, the output and actual connection picture (since some said wire position matters for PN532).

**Connections**
- ESP32

| ESP32| PN532|
| ----------- | ----------- |
| GPIO 22| SCL       |
| GPIO 21  | SDA      |
| 3.3V   | VCC      |
| GND   | GND      |
- Arduino Uno

| Uno| PN532|
| ----------- | ----------- |
| A5      | SCL       |
| A4   | SDA      |
| 3.3V   | VCC      |
| GND   | GND      |

**The code**

    #include <Wire.h>
    #include <PN532_I2C.h>
    #include <PN532.h>
    #include <NfcAdapter.h>

    PN532_I2C pn532i2c(Wire);
    PN532 nfc(pn532i2c);

    void setup(void) {
      Serial.begin(115200);
      //Wire.begin(21, 22);        //used this line only when connected with ESP32
      Serial.println("Hello!");

      pn532i2c.wakeup();    //delays 500ms
      nfc.begin();

      uint32_t versiondata = nfc.getFirmwareVersion();
      if (! versiondata) {
        Serial.print("Didn't find PN53x board");
        while (1); // halt
      }

      // Got ok data, print it out!
      Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX);
      Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC);
      Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC);

      // Set the max number of retry attempts to read from a card
      // This prevents us from waiting forever for a card, which is
      // the default behaviour of the PN532.
      nfc.setPassiveActivationRetries(0xFF);

      // configure board to read RFID tags
      nfc.SAMConfig();

      Serial.println("Waiting for an ISO14443A card");
    }

    void loop(void) {
      boolean success;
      uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 };  // Buffer to store the returned UID
      uint8_t uidLength;                        // Length of the UID (4 or 7 bytes depending on ISO14443A card type)

      // Wait for an ISO14443A type cards (Mifare, etc.).  When one is found
      // 'uid' will be populated with the UID, and uidLength will indicate
      // if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight)
      success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, &uid[0], &uidLength);

      if (success) {
        Serial.println("Found a card!");
        Serial.print("UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes");
        Serial.print("UID Value: ");
        for (uint8_t i=0; i < uidLength; i++)
        {
          Serial.print(" 0x");Serial.print(uid[i], HEX);
        }
        Serial.println("");
        // Wait 1 second before continuing
        delay(1000);
      }
      else
      {
        // PN532 probably timed out waiting for a card
        Serial.println("Timed out waiting for a card");
      }
    }

**Output**

 - For Arduino Uno
[![enter image description here][1]][1]
 - For ESP32
[![enter image description here][2]][2]

**Connection Placements**

 - For Arduino Uno
[![enter image description here][3]][3]

 - For ESP32
[![enter image description here][4]][4]

Also, the configuration of ESP32 in Arduino IDE

[![enter image description here][5]][5]

  [1]: https://i.stack.imgur.com/ZKuZo.png
  [2]: https://i.stack.imgur.com/n5sB5.png
  [3]: https://i.stack.imgur.com/Nys3L.jpg
  [4]: https://i.stack.imgur.com/F6mzm.jpg
  [5]: https://i.stack.imgur.com/C263H.png

body:
To use PN532, UART or SPI seems to be a good choice. Also, the little red board needs a strong power supply, and the power supply capacity from the ESP32 DEV KIT will be insufficient; I recommend adding a capacitor of about 47uF on the PN532.
[![enter image description here][1]][1]

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


message:
Changing single bit in byte array

So I have a `byte`-array representing the display attached to my Arduino:
```c
byte theDisplay[8] = {
    B00000000,
    B00000000,
    B00000000,
    B00000000,
    B00000000,
    B00000000,
    B00000000,
    B00000000
};
```
Now I want to flip a single bit at an arbitrary position:
```lang-c
theDisplay[3][6] = 1;
```
This (probably) faulty method produces these errors:
```
In function 'void setup()':
sketch_sep14c:13:18: error: invalid types 'byte {aka unsigned char}[int]' for array subscript
   theDisplay[3][6] = 1;
                  ^
exit status 1
invalid types 'byte {aka unsigned char}[int]' for array subscript
```
Is there an easy way to flip a single bit working with indexes like shown above?

body:
The error occurs, because you try to use the syntax for a 2 dimensional array with a 1 dimensional array (since you have an array of bytes, not bits, and a microcontroller always works with at least one byte). For accessing the individual bits you need to use bitwise operators. For example this:

    theDisplay[3] |= (1 << bitnumber); // for setting the bit
    theDisplay[3] &= ~(1 << bitnumber); // for clearing the bit

with `bitnumber` being the number of the bit to change counted from least significant bit (in the binary representation in your code the rightmost digit) to most significant bit (the leftmost digit).

If you want to know, what exactly this does, you can google for bitwise operators in C++.


message:
First I2C project - Unable to get any servo movement with PCA9685

I'm working on a project where I need to run multiple servos. For now though, I'm trying to get a single MG90S servo running with a PCA9685 servo driver but I'm unable to get any movement from the servo.

What I have setup is as follows;
 - Servo power is 5v 2A in the form of a standalone power supply.
 - Arduino UNO GND to shield GND
 - Arduino 5v to shield VCC
 - Arduino A4 to shield SDA
 - Arduino A5 to shield SCL (Ive also tried SDA and SCL on the uno)

The code I'm running is just the standard adafruit library example (see below) with the only change being the I2C address is set to 0x41 as I have soldiered across the first pair of pads (I have verified the new address with an I2C scanner program).

Ive tried multiple servos, two PCA9685s and two different arduinos. The servos work without the PCA9685 and I can see println info when viewing the Serial Monitor. Any ideas?

[![setup photo][1]][1]

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

    /***************************************************
      This is an example for our Adafruit 16-channel PWM & Servo driver
      Servo test - this will drive 8 servos, one after the other on the
      first 8 pins of the PCA9685

      Pick one up today in the adafruit shop!
      ------> http://www.adafruit.com/products/815

      These drivers use I2C to communicate, 2 pins are required to
      interface.

      Adafruit invests time and resources providing this open source code,
      please support Adafruit and open-source hardware by purchasing
      products from Adafruit!

      Written by Limor Fried/Ladyada for Adafruit Industries.
      BSD license, all text above must be included in any redistribution
     ****************************************************/

    #include <Wire.h>
    #include <Adafruit_PWMServoDriver.h>

    // called this way, it uses the default address 0x40
    //Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
    // you can also call it with a different address you want
    Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x41);
    // you can also call it with a different address and I2C interface
    //Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x41, Wire);

    // Depending on your servo make, the pulse width min and max may vary, you
    // want these to be as small/large as possible without hitting the hard stop
    // for max range. You'll have to tweak them as necessary to match the servos you
    // have!
    #define SERVOMIN  400 // this is the 'minimum' pulse length count (out of 4096)
    #define SERVOMAX  600 // this is the 'maximum' pulse length count (out of 4096)

    // our servo # counter
    uint8_t servonum = 0;

    void setup() {
      Serial.begin(9600);
      Serial.println("8 channel Servo test!");

      pwm.begin();

      pwm.setPWMFreq(60);  // Analog servos run at ~60 Hz updates

      delay(10);
    }

    // you can use this function if you'd like to set the pulse length in seconds
    // e.g. setServoPulse(0, 0.001) is a ~1 millisecond pulse width. its not precise!
    void setServoPulse(uint8_t n, double pulse) {
      double pulselength;

      pulselength = 1000000;   // 1,000,000 us per second
      pulselength /= 60;   // 60 Hz
      Serial.print(pulselength); Serial.println(" us per period");
      pulselength /= 4096;  // 12 bits of resolution
      Serial.print(pulselength); Serial.println(" us per bit");
      pulse *= 1000000;  // convert to us
      pulse /= pulselength;
      Serial.println(pulse);
      pwm.setPWM(n, 0, pulse);
    }

    void loop() {
      // Drive each servo one at a time
      Serial.println(servonum);
      for (uint16_t pulselen = SERVOMIN; pulselen < SERVOMAX; pulselen++) {
        pwm.setPWM(servonum, 0, pulselen);
      }

      delay(500);
      for (uint16_t pulselen = SERVOMAX; pulselen > SERVOMIN; pulselen--) {
        pwm.setPWM(servonum, 0, pulselen);
      }

      delay(500);

      servonum ++;
      if (servonum > 7) servonum = 0;
    }

body:
Thanks for the reply Rowan.
Current draw from the power supply with a blank arduino sketch and the pwm example sketch are 0A which is clearly the issue. I've had a look back at the website I bought these PCA9685 boards from and there is a comment from another buyer with the exact same issue in the last week. They had no voltage to the servo connectors. I've checked and mine is the same. I get a pwm signal and I can see that changing as the script runs, but no 5v. I'm going to return the boards and buy from somewhere else. Many thanks.


message:
Circuit to get highest reading value from multiple thermistors?

I need to measure temperature of 6 battery cells. I don't care much about individual cell readings, I just want to sound a buzzer as soon as at least one of the temperatures is above a certain threshold.

I can see the most straightforward way to do it using 6 thermistors, but that's a lot of wires going between Arduino and all these sensors. Is there any other approach that would be more lightweight? Trying to save both space and weight.

If I understand correctly, best I can do with 6 thermistors is share the GND wire and resistor between them, but then I'm still stuck with 6 * 2 + 1 = 13 wires.

body:
DS18b20 digital thermometers use the 1-Wire protocol which requires only a single data line for a network of devices - so +V (3.3 - 5 Volts), Gnd, and Data, shared among all of them. You can even wire them in "Parasitic mode", skipping the +V, and they will get their power from the data line, so only 2 wires and 1 pin required.<br>From the DS18b20 Datasheet:

[![From the DS18b20 Datasheet:][1]][1]

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


message:
ESP32-CAM, Failed to connect to ESP32

I am trying my ESP32-CAM for project but I am having problems with uploading script/code to the ESP. I am using CP2102 to connect ESP and my laptop. I tried connecting it to 3.3V and even 5V but none seem to be working as I always get the same error:
"A fatal error occurred: Failed to connect to ESP32: Timed out waiting for packet header"

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

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

body:
For future references.

So after some time I was finally able to upload my code into ESP32-CAM. I don't know if I had just bad luck with "faulty" ESP but here is what helped me.

 1. Don't use CP2102, it just doesn't work for me, use other programmer or Arduino as I did.

 2. If you have been using scheme like this [scheme][1] and wasn't able to fix your problem try to connect all other things that need GND on some breadboard and use just one GND pin from ESP. I noticed that GNDs on ESP has (or atleast mine have ) 0.5V difference between them. Right now I am using the GND pin that was connected to IO0 as "main" GND and its works.

Hope this helps someone and thanks for all replies.

  [1]: https://i1.wp.com/randomnerdtutorials.com/wp-content/uploads/2019/12/ESP32-CAM-FTDI-programmer-5V-supply.png?w=750&quality=100&strip=all&ssl=1


message:
Problem Using pins A4 and A5 for input and output I2C

Hardare used:
Arduino nano ( old Bootloader )
Oled Monochrome Display ( 4 pins, 128 x 32 )
MPU 6050

Both display and MPU use A4 and A5 as I2C communication protocol, They interfere, as the MPU is used 2-way and the Display 1-way.

1. How can I change those 2 pins( does not matter witch Display/Sensor )
2. Can this method ( the one you propose ) be used for more cases like this? ( ex 3 sensors )

There is what I tried so far:
```#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // 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);

#include "I2Cdev.h"
#include "MPU6050_6Axis_MotionApps20.h"
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
    #include "Wire.h"
#endif
MPU6050 mpu;

#define OUTPUT_READABLE_YAWPITCHROLL
#define OUTPUT_READABLE_REALACCEL

// MPU control/status vars
bool dmpReady = false;  // set true if DMP init was successful
uint8_t mpuIntStatus;   // holds actual interrupt status byte from MPU
uint8_t devStatus;      // return status after each device operation (0 = success, !0 = error)
uint16_t packetSize;    // expected DMP packet size (default is 42 bytes)
uint16_t fifoCount;     // count of all bytes currently in FIFO
uint8_t fifoBuffer[64]; // FIFO storage buffer

// orientation/motion vars
Quaternion q;           // [w, x, y, z]         quaternion container
VectorInt16 aa;         // [x, y, z]            accel sensor measurements
VectorInt16 aaReal;     // [x, y, z]            gravity-free accel sensor measurements
VectorInt16 aaWorld;    // [x, y, z]            world-frame accel sensor measurements
VectorFloat gravity;    // [x, y, z]            gravity vector
float euler[3];         // [psi, theta, phi]    Euler angle container
float ypr[3];           // [yaw, pitch, roll]   yaw/pitch/roll container and gravity vector

#define INTERRUPT_PIN 2  // use pin 2 on Arduino Uno & most boards
volatile bool mpuInterrupt = false;
void dmpDataReady() {
  mpuInterrupt = true;
}

void setup() {
  volatile bool mpuInterrupt = false;     // indicates whether MPU interrupt pin has gone high

  if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("SSD1306 allocation failed"));
   for(;;); // Don't proceed, loop forever
  }

  // Clear the buffer
  display.clearDisplay();

  delay(150);

  #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
        Wire.begin();
        Wire.setClock(400000); // 400kHz I2C clock. Comment this line if having compilation difficulties
    #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
        Fastwire::setup(400, true);
    #endif

    Serial.println(F("Initializing I2C devices..."));
    mpu.initialize();
    pinMode(INTERRUPT_PIN, INPUT);

    // verify connection
    Serial.println(F("Testing device connections..."));
    Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));

    delay(50);

    // load and configure the DMP
    Serial.println(F("Initializing DMP..."));
    devStatus = mpu.dmpInitialize();

  if (devStatus == 0) {
        // Calibration Time: generate offsets and calibrate our MPU6050
        mpu.CalibrateAccel(6);
        mpu.CalibrateGyro(6);
        mpu.PrintActiveOffsets();
        // turn on the DMP, now that it's ready
        Serial.println(F("Enabling DMP..."));
        mpu.setDMPEnabled(true);

        // enable Arduino interrupt detection
        Serial.print(F("Enabling interrupt detection (Arduino external interrupt "));
        Serial.print(digitalPinToInterrupt(INTERRUPT_PIN));
        Serial.println(F(")..."));
        attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), dmpDataReady, RISING);
        mpuIntStatus = mpu.getIntStatus();

        // set our DMP Ready flag so the main loop() function knows it's okay to use it
        Serial.println(F("DMP ready! Waiting for first interrupt..."));
        dmpReady = true;

        // get expected DMP packet size for later comparison
        packetSize = mpu.dmpGetFIFOPacketSize();
    } else {
        // ERROR!
        // 1 = initial memory load failed
        // 2 = DMP configuration updates failed
        // (if it's going to break, usually the code will be 1)
        Serial.print(F("DMP Initialization failed (code "));
        Serial.print(devStatus);
        Serial.println(F(")"));
    }

  Serial.begin(9600);
}

void loop() {
  if (!dmpReady) return;
    // read a packet from FIFO
    if (mpu.dmpGetCurrentFIFOPacket(fifoBuffer)) { // Get the Latest packet

        #ifdef OUTPUT_READABLE_YAWPITCHROLL
            // display Euler angles in degrees
            mpu.dmpGetQuaternion(&q, fifoBuffer);
            mpu.dmpGetGravity(&gravity, &q);
            mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
            /*
            data.gyro_data[0] = ypr[0] * 180/M_PI;
            data.gyro_data[1] = ypr[1] * 180/M_PI;
            data.gyro_data[2] = ypr[2] * 180/M_PI;
            */
        #endif

        #ifdef OUTPUT_READABLE_REALACCEL
            // display real acceleration, adjusted to remove gravity
            mpu.dmpGetQuaternion(&q, fifoBuffer);
            mpu.dmpGetAccel(&aa, fifoBuffer);
            mpu.dmpGetGravity(&gravity, &q);
            mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity);
            /*
            data.acc_data[0] = aaReal.x;
            data.acc_data[1] = aaReal.y;
            data.acc_data[2] = aaReal.z;
            */
        #endif
    }

    display.print(String(ypr[0] * 180/M_PI));
    display.print('/');
    display.print(String(ypr[1] * 180/M_PI));
    display.print('/');
    display.print(String(ypr[2] * 180/M_PI));
    display.print("\n\n");
    display.print(String(aaReal.x));
    display.print('/');
    display.print(String(aaReal.y));
    display.print('/');
    display.print(String(aaReal.z));

    //display.print(String(data.id));
    display.display();

    delay(500);
}
```

Now I know this looks like a bunch of code thrown together with the hope to work, But it is composed from 2 other of my codes separately for MPU and Display, those work fine.

body:
So after repeated tests I found several problems, software and hardware.
1) The cables I used on the breadboard where facing each other. The metal parts where touching ( from a defect of the cables ). Turned them 90*.

2) The Oled display was NOT Initialized properly. When using ``` display.write() ``` or ``` display.print() ``` you must first put the cursor at (0;0) by ``` display.setCursor(0,0) ```. Furthermore for more compatibility in `Setup(){}` you have to add `display.setTextSize(1)` and `display.setTextColor(WHITE)`.

3) Power control. I found the best, either adding a capacitor on the VCC and GND lines when using them to power 2 Sensors at the same time, or ad a 5 mls delay in the first function. `delay(5)`


message:
Where are these junk characters (from serial) coming from?

I currently have 2 Arduinos both hooked up to HC-12s and have successfully got them communicating. But I am now trying to be able to process the data sent across and store it as a variable so as to make comparisons. But I'm getting junk data that comes over with the code, which prevents me from being able to do these comparisons.

For example, from one arduino when I sent "stop" I received

    stop<⸮=l⸮⸮⸮

I cant figure out what this junk is from, also, I've limited the receivedChars to a size of 4, why am I getting more than 4 characters?

The code from the sender

    #include <SoftwareSerial.h>

    SoftwareSerial HC12(3, 2); // HC-12 TX Pin, HC-12 RX Pin

    void setup() {
      Serial.begin(9600);             // Serial port to computer
      HC12.begin(9600);               // Serial port to HC12
      Serial.print("Checking HC-12 module: ");
      HC12.write("AT");               //Check for response(this is sending data to the HC, the SET pin must be low for this to work)
      delay(1000);
      HC12.write("AT+RX");            //Gets configs of HC-12
    }

    void loop() {
      while (HC12.available()) {        // If HC-12 has data
        Serial.write(HC12.read());      // Send the data to Serial monitor
      }
      while (Serial.available()) {      // If Serial monitor has data
        HC12.write(Serial.read());      // Send that data to HC-12
      }
    }

The simplified receiving code

        #define BYTELENGTH 4 //Limited to 4 chars
           #define ENDMARKER '\n'  //To know when stop stop reading serial

           SoftwareSerial HC12(3, 2); // HC-12 TX Pin, HC-12 RX Pin

      Serial.begin(9600); //Fastest it can be on the nano
      HC12.begin(9600); // Serial port to HC12s

          char receivedChars[BYTELENGTH - 1];
          int byteIndex;
          char curChar;

          while (HC12.available()) {        // If HC-12 has data
            curChar = HC12.read();
            if(curChar != ENDMARKER){
              receivedChars[byteIndex] = curChar;
              byteIndex++;
            }
          }
          if(strcmp(receivedChars,"") != 0){
            Serial.println(receivedChars);
            receivedChars[0] = 0;
          }

body:
It appears you have a baud rate problem. I am surprised you are getting anything. You need software to start the serial port such as SoftwareSerial mySerial(rxPin, txPin) then in setup  mySerial.begin(9600); You need that in each application and the baud rates need to be the same.

I have used SC16IS750 I2C/SPI-to-UART devices as an external UART, they work great and have many nice features such as a 64 bytes of transmit and receive FIFOs. Some versions of this have been obsoleted but they are still available and work fine. You get 8 additional I/Os as well.


body:
I would say you are printing data outside of your `char` array, because you didn't terminate the C-string in it and the size of your array is too small.

You have

    #define BYTELENGTH 4 //Limited to 4 chars
    char receivedChars[BYTELENGTH - 1];

so your `char` array is only 3 elements big. When you want to save a string in that array, you always need to terminate it with a null character `\0` (which is also zero in decimal representation). So in that `char` array you only have space for 2 characters. But your message "stop" is 4 characters long, so you need a `char` array with at least 5 elements. If you are not in an extreme tight memory situation I would suggest using a buffer with a bit headroom above your biggest message (to be sure, that nothing breaks, if you later use messages that are a bit longer). So more like this:

    #define BYTELENGTH 10 //Limited to 4 chars
    char receivedChars[BYTELENGTH + 1]; // message length + null character termination

And then you need to change your receiving code to add a null character at the end of the message. Also you might want to actually use the newline character `\n` as message delimiting (which you are currently not doing):

    bool full_message_received = false;

    void loop(){
        while (HC12.available()) {        // If HC-12 has data
            curChar = HC12.read();
            if(curChar != ENDMARKER){
              receivedChars[byteIndex] = curChar;
              byteIndex++;
            } else {
              receivedChars[byteIndex] = '\0'; // terminating the c-string
              full_message_received = true; // marking the message as fully received
            }
        }
        if(full_message_received){
            Serial.println(receivedChars);
            receivedChars[0] = 0;
            full_message_received = false;
        }
    }

**What happens, if I don't terminate the string with a null character?** All the functions, that handle C-strings (like `strcmp()` or also `Serial.print()`) use the null character to determine, at which point the string is at its end. They don't know the size of your array, so they just read byte after byte, until they reach the null character. They even read more data than is in your array. The junk characters are most likely exactly, what currently is placed in the memory directly after your array. `Serial.print()` doesn't know, that they don't belong to the C-string, since you didn't use the null character to tell it that. It just keeps printing characters, until it reaches a byte, that is zero.

You even wrote data to memory outside of the array. Depending on what comes directly after your array in the memory this can be without any problems, but you might also overwrite some other data, without knowing, what that data is. That can lead to very weird and hard to debug problems. Be sure to never write outside of your array. You might break things in weird ways.


message:
Why are the pin numbers of the diagrams and of the code different?

If I search Google for "arduino nano pin numbers", all results show that the pin number of D2 is 5. But that did not work. I searched for some sample codes, and they were 3 for D3 and 5 for D5, etc. So, in codes, the pin number for D`n` is `n`. Then what are the numbers in these diagrams?

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

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

body:
Every chip datasheet (and also the Arduino boards) uses 2 different ways to refer to the pins:

- Counting the physical pins in the order as they appear on the chosen package of the chip
- Referring to the pins by their function

The first way is only for referring to specific pin positions from the outside, for example when you are building the actual circuit. This also includes special pins like Vcc, GND and Reset. Those pins cannot be referenced by the code (wouldn't make much sense). Also the microcontroller on the inside of its package doesn't know in which package it got stuck by the manufacturer. Each package has a different pin order and form factor. So this counting only makes sense in the context of placing this specific package of the chip into a circuit (like where is Vcc, where ground and where do I need to connect to that specific digital pin), but makes no sense to use for the code inside the controller.

For referring to pins from inside the controller (aka in the code) we use the function of the pins. On an Arduino you have mainly digital and analog pins, which can be controlled. So for the convenience of beginners (which are targeted by the Arduino framework) the digital and analog pins are just numbered. Those are the numbers, that are normally written only the Arduino board. So D2 means the third digital pin inside the Arduino framework. A0 is the first analog pin. Where that pin is physically located on the board isn't interesting for the code, nore does the code know the actual location. For the code its just the third digital output hardware and so on.

**TL;DR:** For building the circuit we must refer to pin positions (like where is Vcc, where is ground) to connect the chip/microcontroller correctly. But the internal code doesn't know, where the physical pins are located and the actual location can also depend on the packaging. So internally we use a different counting system based on the pin function. The Arduino way of counting the digital and analog pins just hides away complexity for the beginner. As reference the numbers are also printed on the Arduino board itself.

---

In case you want to go deeper into the rabbit hole:

Actually the microcontroller has different hardware for different functions incorporated. For example: The analog pins can be used by the ADC (Analog to Digital Converter) to measure an analog voltage. But they also each have digital input and output hardware, just like any other digital pin. Most pins of a microcontroller are multi purpose. The code has to decide, what hardware gets to be connected to the respective pins. When I use `pinMode(2, OUTPUT)` I tell the microcontroller to connect the third digital output hardware to its respective physical pin. When I use `analogRead(A1)` I tell it to connect the second analog channel of the ADC to its respective pin and read an analog voltage through the ADC.

That means, that the code only knows of the function hardware and that it can be connected to their respective pins (whichever these pins are on the outside world). **The numbering in digital and analog pins is only an additional abstraction layer to hide the complexity from beginners.** Actually the code controls the hardware functions via Special Function Registers (SFR). These are special pieces of memory, which are physically hardwired to the respective hardware in the microcontroller. For the digital output hardware the pins are sorted into groups of up to 8 pins. These groups are called Ports, and are numbered with characters. When you look at [this pinout of the Arduino Nano][1], you see, that the Arduino pin D2 is also named PD2, which means PortD third pin (counting from zero up). Arduino pin D8 is also named PB0, so PortB first pin. Functions like `pinMode()`, `digitalWrite()` and `digitalRead()` all just manipulate the SFRs for the wanted port to set the respective pin. Refer to the [Documentation on Port Manipulation][2] for learning how to do it yourself. For beginners it is just easier to use the markings on the board - the Arduino pin number - instead of bearing with the ports and their SFRs directly.

  [1]: https://www.teachmemicro.com/arduino-nano-pinout-diagram/
  [2]: https://www.arduino.cc/en/Reference/PortManipulation


body:
> Why are the pin numbers of the diagrams and of the code different?

Because the Arduino designers chose to re-use the name "pin" for the chip's programmable signal lines, despite it's more common and already existing use to mean any of the protruding external connections to the device.


body:
There are at least four ways of referring to pins on any Arduino board:

1. **Board-order**: Simple numeric order (1,2,3 ...) of physical location of pins on printed circuit board anticlockwise from the USB end (or some arbitrary end)
2. **Arduino-name**: Names used in Arduino source code and/or PCB silk-screen annotation (D1,D2 ... A0,A1 ...).
3. **IC-order**: Simple numeric order of corresponding pin on IC according to numbering used on manufacturers data sheet.
3. **IC Function name**: Names for functions available on pin (RESET, VCC, INT0, PB0,PB1,PB2 ...) as described in data sheet for IC.

For example:

|Nano PCB Pin#|Arduino Name|ATMega328 TQFP Pin#|ATMega328 DIP Pin#|ATMega328 function|
|----------|------------|---|--------------|------------------|
|     1    | D13        |17 |      19      | PB5, SCK, PCINT5 |
|     2    | 3V3        |N/A|      N/A     | N/A              |
|     3    | REF        |20 |      21      | AREF             |
|     4    | A0         |23 |      23      | PC0, ADC0, PCINT8|
|     5    | A1         |24 |      24      | PC1, ADC1, PCINT9|
|etc

There are lots of different Arduino and Arduino-like boards that use the ATMega328, some use different ATMega328 packages (DIP, TQFP, etc) with different pin arrangements. Many arrange the physical PCB pins differently. This is why there isn't a fixed one to one relationship and it is partly why the Arduino IDE provides for it's own simplified naming that it attempts to apply consistently and portably across a variety of different microcontrollers.

---

[![Nano Pinout by PigHixx][1]][1]
[![Key by PigHixx][2]][2]

<sup>(c) PigHixx w/o permission.</sup>

  [1]: https://i.stack.imgur.com/nf4SW.png
  [2]: https://i.stack.imgur.com/cgHjP.png