text:
Arduino Freezes (probably because of I2C) - Need help to write robust script
Arduino Pro mini 3.3V stucks few hours after startup. After repowered, it begins to stuck within a few seconds. If I wait long enough before turning it on it stucks little later for example now it lasted 45 seconds before stuck. Whenever it is stuck SCL pin is high and SDA pin is low so I suspect somethin about I2C is wrong. There is an 60 seconds countdown at start and the stuck usually happens there, you will see it is an extremely simple for loop. There are SHT31 sensor, 128x64 SH1106 driven OLED screen, DS3231 clock module, hc-sr501PIR sensor, LDR, Encoder and a button on the project. Only first three works with I2C and the code for those devices are very short, they are in "start(), updatescreen(), getTime(), getDew()" functions in the long script below so I hope it is not hard to diagnose the problem. I have done some experiments. I isolated SHT31 and OLED, both caused freeze even though all other devices were disconnected (I added blink code to their example test sketch and the blinking stopped after few seconds which means stuck). OLED screen works when it is connected with jumpers outside the PCB so I even suspected the PCB but it is so simple that it shouldn't cause problems. The weird thing is that this device worked perfectly for 2 days before it crushed for the first time.
Schematic:

PCB (some mistakes were fixed later):

Real images:

Test script (the same freezing problem occurs but easier to read):
#include <U8g2lib.h>
#include <Wire.h>

U8G2_SH1106_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0, /* reset=*/U8X8_PIN_NONE);
void setup() {
  u8g2.begin();
  u8g2.setFont(u8g2_font_ncenB14_tr);
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
  u8g2.firstPage();
  do {
    u8g2.setCursor(0, 20);
    u8g2.print(F("Hello World!"));
  } while (u8g2.nextPage());
  delay(1000);
  digitalWrite(LED_BUILTIN, HIGH);  // turn the LED on (HIGH is the voltage level)
  delay(1000);                      // wait for a second
  digitalWrite(LED_BUILTIN, LOW);
}

Test script 2 (this time for sht31, the same freezing problem occurs but easier to read):
#include <Wire.h>
#include "ClosedCube_SHT31D.h"

ClosedCube_SHT31D sht3xd;
void setup() {
  Wire.begin();
  sht3xd.begin(0x44);
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
  digitalWrite(LED_BUILTIN, HIGH);
  SHT31D result = sht3xd.readTempAndHumidity(SHT3XD_REPEATABILITY_LOW, SHT3XD_MODE_CLOCK_STRETCH, 50);
  delay(1000);
  digitalWrite(LED_BUILTIN, LOW);
  delay(1000);
}

Full Script:
#include "Wire.h"
#include "ClosedCube_SHT31D.h"
#include <DS3231.h>
#include "LowPower.h"
#include <EEPROM.h>
#include <U8g2lib.h>

#define PIR 2
#define ENCODER_BUTTON 3
#define ENC_A 4
#define ENC_B 5
#define FAN_MAIN_REL 8
#define FAN_SECOND_REL 9
#define BUZZER 10
#define LIGHT_REL 11
#define LDR_PWR 12
#define LDR_READ A0
#define FREE_RUN_BUTTON A2
#define CLOCK_INT A3

volatile bool PIR_flag, TIM1_flag, But_flag, FreeRun_flag, Settings_flag;
uint8_t Weather_flag;  // Weather_flag is special, it is set/reset by a regular function, 0: Dew is under threshold, 1: Dew is over DewThres but less than DewThresExtreme, 2: Dew is over DewThresExtreme
volatile int16_t encVal;

// Variables:
float Temp, Hum, Dew;
bool DewTrigEnabled;
uint8_t FanMotTrigEnabled;  // for fan relay
bool LightRelEnabled;       // for light relay
uint16_t waitDur;           // Setting 1
uint16_t Runtime;           // Setting 2
float DewThres;             // Setting 3
float DewThresExtreme;
uint16_t FreeRunDur;  // Setting 5
bool FreeRunStatus;
bool DNDenabled;
uint8_t DND_SH;  // DND start Hour
uint8_t DND_SM;  // DND start Minute
uint8_t DND_FH;  // DND finish Hour
uint8_t DND_FM;  // DND finish Minute
uint16_t counter;
uint8_t hour, minute;
bool LDRenabled;
uint16_t LDRThres;
bool screen_awake = true;  // screen starts "on"
uint8_t FanRelayStatus;
const uint8_t screenTime = 60;  // Screen On time without motion (seconds)
const float DewUSratio = 0.98;  // Determines the dew point which the FAN turns off if it was triggered by the Dew in the first place
const uint8_t phaseLim = 120;   // Determines LDR check rate if light is off but LDR is enabled, each phase corresponds to 5 seconds.

ClosedCube_SHT31D sht3xd;
RTClib myRTC_1;
DS3231 myRTC_2;
U8G2_SH1106_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0, /* reset=*/U8X8_PIN_NONE);

void swCounter(bool turn_on, uint32_t cnt = 0) {
  if (turn_on) {
    counter = cnt;
    TCNT1 = 0;                            // TIM1 counter value
    TCCR1B |= (1 << CS12) | (1 << CS10);  // Start timer by setting prescaler to 1024
  } else
    TCCR1B &= ~(1 << CS12) | ~(1 << CS10);  // Stop TIM1
}

void setup() {
  LoadPinsAndEEPROM();

  Wire.begin();

  // Temp&Hum Sensor:
  sht3xd.begin(0x44);

  // Clock Module:
  myRTC_2.setA2Time(
    0, 0, 0,
    0b01110000, false, false, false);
  myRTC_2.turnOnAlarm(2);

  myRTC_2.setA1Time(
    0, 0, 0xFF, 0,
    0b00001110, false, false, false);
  myRTC_2.turnOffAlarm(1);
  myRTC_2.checkIfAlarm(1);  // clear Alarm 1 flag

  sht3xd.heaterEnable();
  // OLED Screen:
  u8g2.begin();
  u8g2.setFont(u8g2_font_lubB12_tr);
  for (int i = 60; i > 0; i--) {
    u8g2.firstPage();
    do {
      u8g2.drawStr(6, 25, "by Prince");
      u8g2.setCursor(58, 55);
      u8g2.print(i);
      if (i == 30) sht3xd.heaterDisable();
    } while (u8g2.nextPage());
    delay(1000);
  }
  u8g2.setDrawColor(2);

  //TIM1 Configuration:
  TCCR1A = 0;
  TCCR1B = 0;
  TIMSK1 |= (1 << OCIE1A);  // Output Compare A Match Interrupt Enable
  OCR1A = 39061;            // Output Compare A
  TCCR1B |= (1 << WGM12);   // CRC (auto reset timer when it reaches OCR1A)
  TCNT1 = 0;                // TIM1 counter value

  // Attach interrupts (PinChanges and INTpin)
  attachInterrupt(digitalPinToInterrupt(PIR), ISR_PIR, RISING);
  attachInterrupt(digitalPinToInterrupt(ENCODER_BUTTON), ISR_ENCODER_BUTTON, FALLING);
  PCICR |= (1 << PCIE1);                      // A0-A6 group can create interrupt
  PCMSK1 |= (1 << PCINT10) | (1 << PCINT11);  // A2 and A3 pins can create interrupt
  PCMSK2 |= (1 << PCINT20) | (1 << PCINT21);  // D4 and D5 pins can create interrupt

  Beep(1, 100, 0);
  PIR_flag = false;
  But_flag = false;
}

void loop() {
  checkButtons();  // After execution it will return.
  if (!getDNDstatus()) {
    getDew();  // sets flag accordingly

    if (PIR_flag) {
      if (FanMotTrigEnabled == 1) {
        TIM1_flag = true;  // Update screen initially
        screenPwr(1);

        unsigned long lastMotion;
        uint8_t step = 1;
        if (waitDur <= 5) step = 2;  // PIR_flag is already true at this point
        else swCounter(1, waitDur);

        for (step = step; step <= 2; step++) {  // 1: waiting, 2: armed, 3: Running
          if (step == 2) {
            (waitDur >= 90) ? counter = 60 : counter = 30;  // Deciding how long ahead it will check for motion
            swCounter(1, counter);
            PIR_flag = false;
            updateScreen(step);
          }
          while (counter > 0) {  // Counter Loop
            if (checkButtons()) return;
            if (PIR_flag) {
              PIR_flag = false;
              lastMotion = millis();
              if (step >= 2) {    // if it's armed or Running and Motion is detected
                if (step == 2) {  // if it's armed and Motion is detected
                  if (FanRelayStatus != 2) swFanRelays(1);
                  step = 3;  // Motion..
                  updateScreen(step);
                }
                swCounter(1, Runtime);  // Restart interval
              }
            }
            if (TIM1_flag) {
              TIM1_flag = false;
              if (getDNDstatus()) return;
              if (step == 1 && (millis() - lastMotion) / 1000 >= screenTime) return;
              getDew();
              DewControl(step != 3);  // in case Dew increases while on wait
              updateScreen(step);
            }
          }
        }
      } else if (FanMotTrigEnabled != 1) {  // Mot trig is disabled but there is motion
        PIR_flag = false;
        if (FanMotTrigEnabled == 2) swFanRelays(0);
        RunScreen(false);
      }
    }

    DewControl(true);
    Sleep(true);

  } else {  // if it's DND times:
    if (PIR_flag) {
      PIR_flag = false;
      RunScreen(true);
    }
    if (getDNDstatus()) Sleep(false);  // DnD status is rechecked because it might have been stuck in RunScreen by the user when DND is over.
  }
}

void DewControl(bool cmd1) {  // 0: cannot turn the fan "off" but only "on" 1: can both turn "on" and "off"
  if (Weather_flag == 0 && cmd1) swFanRelays(0);
  else if (Weather_flag == 1) swFanRelays(1);
  else if (Weather_flag == 2) swFanRelays(2);
}

void RunScreen(bool cmd1) {  // 0: dont return based on DND, 1: return if not in DND times anymore (prevents being stuck in DND if screen is on)
  TIM1_flag = true;          // Update screen initially
  screenPwr(1);
  swCounter(1, screenTime);  // Fixed Run screen time
  while (counter > 0) {
    if (checkButtons()) return;
    if (TIM1_flag) {
      if (getDNDstatus()) {
        if (FanRelayStatus) return;
      } else {
        if (cmd1) return;
        DewControl(true);
      }
      getDew();
      updateScreen(0);  // Idle or Dew

      if (PIR_flag) {
        counter = screenTime;
        PIR_flag = false;
      }
      TIM1_flag = false;
    }
  }
  LightRel_IfNeeded(0);
}

void getDew() {
  SHT31D result = sht3xd.readTempAndHumidity(SHT3XD_REPEATABILITY_LOW, SHT3XD_MODE_CLOCK_STRETCH, 50);  // used to be a static var
  Temp = result.t;
  Hum = result.rh;

  float a_func = log(Hum / 100) + 17.625 * Temp / (243.04 + Temp);
  Dew = (243.04 * a_func) / (17.625 - a_func);

  if (!DewTrigEnabled || (Dew <= DewThres * DewUSratio) || (Dew < DewThres && FanRelayStatus == 0)) Weather_flag = 0;
  else if (Dew < DewThresExtreme) Weather_flag = 1;
  else Weather_flag = 2;
}

bool getDNDstatus() {  // check if hours and minutes are in the interval
  if (!DNDenabled) return false;

  updateTime();
  uint16_t currentmin = hour * 60 + minute;

  uint16_t localDNDstart = DND_SH * 60 + DND_SM;
  uint16_t localDNDfinish = DND_FH * 60 + DND_FM;

  if (localDNDstart < localDNDfinish) return (currentmin >= localDNDstart && currentmin < localDNDfinish);
  else return (currentmin >= localDNDstart || currentmin < localDNDfinish);
}

void updateTime() {
  if (myRTC_2.checkIfAlarm(2)) {
    DateTime now;  // used to be a static var
    now = myRTC_1.now();
    hour = now.hour();
    minute = now.minute();
  }
}

void swFanRelays(uint8_t cmd1) {  // 0: turn off, 1: turn on
  if (FanRelayStatus == cmd1) return;
  bool PIR_flag_original = PIR_flag;
  if (cmd1 == 0) {
    digitalWrite(FAN_MAIN_REL, LOW);
    digitalWrite(FAN_SECOND_REL, LOW);
    FanRelayStatus = 0;
  } else if (cmd1 == 1) {
    digitalWrite(FAN_MAIN_REL, HIGH);
    if (FanRelayStatus != 2) {
      digitalWrite(FAN_SECOND_REL, HIGH);
      delay(500);
    }
    digitalWrite(FAN_SECOND_REL, LOW);
    FanRelayStatus = 1;
  } else if (cmd1 == 2) {
    digitalWrite(FAN_MAIN_REL, HIGH);
    digitalWrite(FAN_SECOND_REL, HIGH);
    FanRelayStatus = 2;
  }
  delay(100);
  if (!PIR_flag_original) PIR_flag = false;
  But_flag = false;
  FreeRun_flag = false;
}

void LightRel_IfNeeded(bool cmd1) {  // 0: turn OFF Light Relay, 1: turn ON Light Relay
  static bool LightRelStatus;
  bool LDRresult;
  static uint8_t phase;  // regularly check light level in case brightness changes in the room over time.

  switch (cmd1) {
    case 0:
      if (!LightRelStatus) return;
      LightRelStatus = false;
      phase = 0;
      digitalWrite(LIGHT_REL, LOW);
      delay(100);
      PIR_flag = false;
      But_flag = false;
      FreeRun_flag = false;
      break;

    case 1:
      if (!LightRelStatus && phase == 0) {
        if (LDRenabled) {
          digitalWrite(LDR_PWR, HIGH);
          delay(10);
          LDRresult = (analogRead(LDR_READ) > LDRThres);  // Darkness --> High resistance --> High voltage on LDR --> TRUE              Lit --> Low resistance --> Low voltage on LDR --> FALSE
          digitalWrite(LDR_PWR, LOW);
        } else LDRresult = true;

        if (LDRresult) {
          LightRelStatus = true;
          digitalWrite(LIGHT_REL, HIGH);
          delay(100);
          PIR_flag = false;
          But_flag = false;
          FreeRun_flag = false;
        }
      }
      phase++;
      if (phase > phaseLim) phase = 0;  // default value is 120 which means 10 minutes
      break;
  }
}

void Sleep(bool cmd1) {  // 0: Sleep normal 1: Sleep without turning off the Fan
  if (cmd1 == 0) swFanRelays(0);
  LightRel_IfNeeded(0);
  screenPwr(0);
  updateTime();
  PIR_flag = false;
  But_flag = false;
  FreeRun_flag = false;

  LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);
}

void updateScreen(uint8_t cmd1) {  // 0: idle or Dew Trig, 1: Detected, 2: Waiting, 3: Armed, 4: Mot Trig, 5: Free run dur
  String info;
  LightRel_IfNeeded(1);  // Regularly called because brigthness of the room info is updated every phase*5/60 minutes
  updateTime();

  switch (cmd1) {
    case 0:
      if (FanRelayStatus == 0) info = "Idle";
      else if (FanRelayStatus == 1) info = "Dew";
      else info = "OverDew";
      break;
    case 1:
      info = "Waiting";
      if (FanRelayStatus == 1) info += "&Dew";
      else if (FanRelayStatus == 2) info += "&OverDew";
      break;
    case 2:
      info = "Armed";
      if (FanRelayStatus == 1) info += "&Dew";
      else if (FanRelayStatus == 2) info += "&OverDew";
      break;
    case 3:
      info = "Motion";
      if (Weather_flag == 1) info += "&Dew";
      else if (Weather_flag == 2) info += "&OverDew";
      break;
    case 4:
      info = "<";
      info += String(counter / 60 + 1);
      info.remove(info.indexOf('.'));
      info += " mins";
      break;
  }

  u8g2.firstPage();
  do {
    u8g2.setFont(u8g2_font_6x10_mr);  // u8g2_font_haxrcorp4089_tn
    u8g2.setCursor(0, 7);
    u8g2.print(info);

    u8g2.setCursor(99, 7);
    if (hour < 10) u8g2.print("0");
    u8g2.print(hour);
    u8g2.print(":");
    if (minute < 10) u8g2.print("0");
    u8g2.print(minute);

    u8g2.drawLine(0, 10, 128, 10);

    u8g2.setFont(u8g2_font_fub20_tn);
    u8g2.setCursor(0, 38);
    if (Temp < 10 && Temp >= 0) u8g2.print("0");
    u8g2.print(Temp, 1);
    u8g2.setCursor(0, 64);
    u8g2.print(Hum, 1);
    u8g2.setCursor(71, 61);
    if (Dew < 10) u8g2.print("0");
    u8g2.print(Dew, 1);
    if (Dew < DewThres) u8g2.drawFrame(70, 38, 58, 26);
    else u8g2.drawBox(71, 39, 56, 24);

    u8g2.setFont(u8g2_font_lubB12_tr);
    u8g2.drawStr(55, 30, "*C");
    u8g2.drawStr(55, 64, "%");

    if (FreeRunStatus == true) u8g2.drawStr(81, 30, "FREE");
    else if (getDNDstatus()) u8g2.drawStr(82, 30, "DND");

  } while (u8g2.nextPage());
}

void screenPwr(bool cmd1) {
  if (cmd1 == screen_awake) return;

  switch (cmd1) {
    case 0:
      u8g2.setPowerSave(1);
      u8g2.clear();
      screen_awake = false;
      break;

    case 1:
      u8g2.setPowerSave(0);
      swCounter(0);
      screen_awake = true;
      break;
  }
}

void FreeRun() {
  Beep(1, 500, 0);
  FreeRun_flag = false;
  FreeRunStatus = true;
  getDew();
  swFanRelays(1);
  swCounter(1, FreeRunDur);
  updateScreen(4);
  screenPwr(1);
  while (counter > 0) {
    if (But_flag) {
      FreeRunStatus = false;
      Settings();
      return;
    }
    if (FreeRun_flag) {
      Beep(1, 100, 0);
      delay(1000);
      if (!digitalRead(FREE_RUN_BUTTON)) {  // if the user holds the button down
        swFanRelays(0);
        Beep(2, 100, 100);
        while (!digitalRead(FREE_RUN_BUTTON)) delay(100);  // For the user to remove hand
        delay(500);                                        // prevent debouncing
        FreeRun_flag = false;
        break;
      } else {
        FreeRun_flag = false;
        if (FanRelayStatus == 1) swFanRelays(2);
        else if (FanRelayStatus == 2) swFanRelays(1);
      }
    }
    if (TIM1_flag) {
      TIM1_flag = false;
      if (getDNDstatus()) break;
      getDew();
      updateScreen(4);
    }
  }
  DewControl(true);
  FreeRunStatus = false;
  PIR_flag = false;  // Ignore the motion while in "Free Run" mode
}

bool checkButtons() {
  if (FreeRun_flag) {
    if (!getDNDstatus()) {
      FreeRun();
      return 1;
    } else {  // if Free Run is pressed during DND, deny Free Run
      Beep(3, 50, 50);
      FreeRun_flag = false;
    }
  } else if (But_flag) {
    Beep(1, 100, 0);
    delay(1000);  // If button is held down
    if (!digitalRead(ENCODER_BUTTON)) {
      Settings();
      return 1;
    }
    But_flag = false;
  }
  return 0;
}

void Beep(uint8_t rep, uint8_t dur_act, uint8_t dur_pass) {  // repetition, duration of beeping, duration of pauses
  for (int i = 0; i < rep; i++) {
    digitalWrite(BUZZER, HIGH);
    delay(dur_act);
    digitalWrite(BUZZER, LOW);
    if (i < (rep - 1)) delay(dur_pass);
  }
}

void LoadPinsAndEEPROM() {

#define FanMotTrigEnabled_Address 0
#define waitDur_Address 1
#define Runtime_Address 3
#define DewTrigEnabled_Address 5
#define DewThres_Address 6
#define DewThresExtreme_Address 10
#define LightRelEnabled_Address 14
#define LDRenabled_Address 15
#define LDRThres_Address 16
#define DND_Enabled_Address 18  // DND enabled
#define DND_SH_Address 19       // DND start Hour
#define DND_SM_Address 20       // DND start Minute
#define DND_FH_Address 21       // DND finish Hour
#define DND_FM_Address 22       // DND finish Minute
#define FreeRunDur_Address 23

  EEPROM.get(FanMotTrigEnabled_Address, FanMotTrigEnabled);
  EEPROM.get(waitDur_Address, waitDur);
  EEPROM.get(Runtime_Address, Runtime);
  EEPROM.get(DewTrigEnabled_Address, DewTrigEnabled);
  EEPROM.get(DewThres_Address, DewThres);
  EEPROM.get(DewThresExtreme_Address, DewThresExtreme);
  EEPROM.get(LightRelEnabled_Address, LightRelEnabled);
  EEPROM.get(LDRenabled_Address, LDRenabled);
  EEPROM.get(LDRThres_Address, LDRThres);
  EEPROM.get(DND_Enabled_Address, DNDenabled);
  EEPROM.get(DND_SH_Address, DND_SH);
  EEPROM.get(DND_SM_Address, DND_SM);
  EEPROM.get(DND_FH_Address, DND_FH);
  EEPROM.get(DND_FM_Address, DND_FM);
  EEPROM.get(FreeRunDur_Address, FreeRunDur);

  // DEBUG:
  /*
  FanMotTrigEnabled = 1;
  waitDur = 10;
  Runtime = 10;
  DewTrigEnabled = true;
  DewThres = 18.0;
  DewThresExtreme = 19.0;
  LightRelEnabled = true;
  LDRenabled = true;
  LDRThres = 512;
  DNDenabled = false;
  DND_SH = 23;
  DND_SM = 45;
  DND_FH = 0;
  DND_FM = 2;
  FreeRunDur = 30;
*/
  pinMode(PIR, INPUT);
  pinMode(LDR_READ, INPUT);
  pinMode(ENC_A, INPUT);
  pinMode(ENC_B, INPUT);

  pinMode(CLOCK_INT, INPUT_PULLUP);  // Datasheet states pullup resistor is necessary
  pinMode(FREE_RUN_BUTTON, INPUT_PULLUP);
  pinMode(ENCODER_BUTTON, INPUT_PULLUP);

  pinMode(FAN_MAIN_REL, OUTPUT);
  pinMode(FAN_SECOND_REL, OUTPUT);
  pinMode(LIGHT_REL, OUTPUT);
  pinMode(BUZZER, OUTPUT);
  pinMode(LDR_PWR, OUTPUT);
}

void ISR_PIR() {
  PIR_flag = true;
}

void ISR_ENCODER_BUTTON() {
  But_flag = true;
}

ISR(PCINT1_vect) {
  if (!digitalRead(FREE_RUN_BUTTON)) FreeRun_flag = true;  // Button has pullup resistor thus "!" is used.
}

ISR(TIMER1_COMPA_vect) {
  TIM1_flag = true;
  counter -= 5;
  if (counter <= 0) swCounter(0);
}

// Horrible Settings Codes xd:
ISR(PCINT2_vect) {  // Rotary Encoder Interrupt
  static bool aLastState;
  bool aState = digitalRead(ENC_A);
  bool bState = digitalRead(ENC_B);

  if (aState != aLastState) {
    if (bState != aState) {
      encVal++;
    } else {
      encVal--;
    }
    aLastState = aState;
  }
}

void ButDebounce(bool cmd1) {  // 0: Encoder But, 1: Free Run
  if (cmd1) {
    while (!digitalRead(FREE_RUN_BUTTON)) delay(100);  // Wait until button is released
    delay(200);
    FreeRun_flag = false;
  } else {
    while (!digitalRead(ENCODER_BUTTON)) delay(100);  // Wait until button is released
    delay(200);
    But_flag = false;
  }
}

String formatTime(int input, bool type = true) {  // type = true means input is seconds, if false it means input is minutes
  int hours = input / 3600;                       // Get the number of hours
  int minutes = (input % 3600) / 60;              // Get the number of minutes
  int remainingSeconds = input % 60;              // Get the number of seconds

  if (!type) {
    hours = minutes;
    minutes = remainingSeconds;
    remainingSeconds = 0;
  }

  // Create a formatted string in the format "hour:minute:second"
  String formattedTime = "";

  if (hours < 10) {
    formattedTime += "0";  // Add leading zero for hours
  }
  formattedTime += String(hours) + ":";

  if (minutes < 10) {
    formattedTime += "0";  // Add leading zero for minutes
  }
  formattedTime += String(minutes) + ":";

  if (remainingSeconds < 10) {
    formattedTime += "0";  // Add leading zero for seconds
  }
  formattedTime += String(remainingSeconds);

  return formattedTime;
}

uint8_t setEncVal(uint16_t target, uint8_t inc1, uint8_t inc2, uint16_t inc3, uint8_t lim1, uint8_t lim2) {
  uint16_t a = 0;
  uint8_t b = 0;
  while (a < target) {
    if (b < lim1) a += inc1;
    else if (b < lim2) a += inc2;
    else a += inc3;
    b++;
  }
  return b;
}

void Settings() {} // removed because of character limit but I don't run this function before stuck anyway

Have you tried adding dedicated pullup resistors to SDA and SCL? Like 4.7kOhm. That might help in this case

No but the modules have pull-ups and it is 2.2k each when I measured

the first three sentences describe a possible overheating problem

Last time I had super weird I2C freezes it was caused by pin change ISR without it's handler.

I have a pin change interrupt which I use to wake the arduino up every minute from sleep by Ds3231 and it is connected to A3 and I have a button which is conected to A2. I didn't need handler for the clock module but since they are both analog pins I have "ISR(PCINT1_vect)" for the button so I guess I can say that I have no unhandled interrupts even though pinwise A3 does nothing except waking up.

jsotola, there is no heating on the regulator or the chip. Are you talking about I2C MOSFETs inside the Arduino? I guess I can't feel them with my fingers. I need to replace the Arduino for a reliable test I guess because the MOSFETs are already damaged. Is there any chance that temperature module or the screen or Ds3231 is also broken? Because they drive the SDA line with their MOSFETs as I guess.

OT: The missing separation between mains and low-level electronic looks dangerous to me. The gaps at K1 and K2 seem to be too small. Did you obey rules to protect humans?

I didn't follow any rules, this is a flaw in my design I admit.

You might want to change this before putting in operation to avoid hurting or killing someone, including yourself.

It sounds like over ambitious pull up resistors. They should total about 3K on each bus. I will take a SWAG and say the I2C driver fet is drawing to much current and heating up. When it does that its resistance increase thereby delivering less current. Get your resistors correct and I believe it will work just fine.
If you have freeze spray chill them and they will probably start working until they warm up.
If it was left on for any period of time it is possible you damaged one of the ICs which is no longer driving the bus properly. If you can check it with a scope. If not swat parts.

This is the first answer that sounded reasonable to me. On an other forum they told me I had cold solder or connectivity problem but they didn't sound realistic. This explains maybe why the device works longer when I wait for a long time before repowering, because FETs cool down. Also it explains why it managed to run 2 days at the first time, because the I2C FETs were healthy but now they are semi broken so it only lasts few hours. It lasts few seconds when I repower without waiting. I just can't believe kiloohms of resistance can still damage FETs. I will remove some resistors form modules.

I've removed the DS3231 because it had 4.7k pull-ups on board thus the total resistance became 5k (10k each on the SHT31 and OLED). Unfortunately the device was stuck few minutes after.

Are you sure you are using the latest I2C library?  Up until halfway through 2020, the 'official' I2C library had a known failure mode that would cause the I2C buss to hang.  See my 'Paynters Palace' post on this subject for additional info.
Frank

There is a comment saying: "Modified 2020 by Greyson Christoforo (grey@christoforo.net) to implement timeouts" I guess there is a default timeout already. Also I installed Arduino IDE 2 on April 2023. Anything I am missing? Thanks.


text:
Seting up registers in Samd based arduino board
I'm trying to setup the BOD33 for Samd51 MCU in th .ino file as a first thing, even before the #include lines in the .ino
// Define the base address for t_SUPC
#define T_SUPC_BASE 0x40001800UL

// Define the offsets for t_BOD33 and t_STATUS
#define T_BOD33_OFFSET 0x10
#define T_STATUS_OFFSET 0x0C

// Set the t_SUPC register
volatile uint32_t *t_SUPC = (volatile uint32_t *)T_SUPC_BASE;

// Set the t_BOD33 register
volatile uint32_t *t_BOD33 = (volatile uint32_t *)(T_SUPC_BASE + T_BOD33_OFFSET);

// Set the t_STATUS register
volatile uint32_t *t_STATUS = (volatile uint32_t *)(T_SUPC_BASE + T_STATUS_OFFSET);

// Clear bit 1 in t_BOD33 and then set it to 1
*t_BOD33 &= ~(1u << 1); // Clear bit 1

// Check bit 0 in t_STATUS and loop while it is 0
while ((*t_STATUS & 0x01) == 0)
{
}

*t_BOD33 &= (0x7D0300u << 1);

*t_BOD33 |= (1u << 1); // Set bit 1 to 1
while ((*t_STATUS & 0x01) == 0)
{
}

while ((*t_STATUS & 0x02) != 0)
{
}

// Clear bit 1 in t_BOD33 and then set it to 1
*t_BOD33 &= ~(1u << 1); // Clear bit 1
while ((*t_STATUS & 0x01) == 0)
{
}
*t_BOD33 |= (1u << 2);
*t_BOD33 &= ~(1u << 3);
*t_BOD33 |= (1u << 1); // Set bit 1 to 1

but I'm getting a compile problem and VScode is throwing those error, which I have no clue why since I never encountered it before
the errors are :
""
0_2.ino:28:10: error: expected constructor, destructor, or type conversion before '&=' token
   28 | *t_BOD33 &= ~(1u << 1); // Clear bit 1
      |          ^~
0_2.ino:31:1: error: expected unqualified-id before 'while'
   31 | while ((*t_STATUS & 0x01) == 0)
      | ^~~~~
0_2.ino:35:10: error: expected constructor, destructor, or type conversion before '&=' token
   35 | *t_BOD33 &= (0x7D0300u << 1);
      |          ^~
0_2.ino:37:10: error: expected constructor, destructor, or type conversion before '|=' token
   37 | *t_BOD33 |= (1u << 1); // Set bit 1 to 1
      |          ^~
0_2.ino:38:1: error: expected unqualified-id before 'while'
   38 | while ((*t_STATUS & 0x01) == 0)
      | ^~~~~
0_2.ino:42:1: error: expected unqualified-id before 'while'
   42 | while ((*t_STATUS & 0x02) != 0)
      | ^~~~~
0_2.ino:47:10: error: expected constructor, destructor, or type conversion before '&=' token
   47 | *t_BOD33 &= ~(1u << 1); // Clear bit 1
      |          ^~
0_2.ino:48:1: error: expected unqualified-id before 'while'
   48 | while ((*t_STATUS & 0x01) == 0)
      | ^~~~~
0_2.ino:51:10: error: expected constructor, destructor, or type conversion before '|=' token
   51 | *t_BOD33 |= (1u << 2);
      |          ^~
0_2.ino:52:10: error: expected constructor, destructor, or type conversion before '&=' token
   52 | *t_BOD33 &= ~(1u << 3);
      |          ^~
0_2.ino:53:10: error: expected constructor, destructor, or type conversion before '|=' token
   53 | *t_BOD33 |= (1u << 1); // Set bit 1 to 1
      |          ^~

thank you in advance.

The line where the error starts should go to a function e.g. setup(). You can compile the code below.
// Define the base address for t_SUPC
#define T_SUPC_BASE 0x40001800UL
// Define the offsets for t_BOD33 and t_STATUS
#define T_BOD33_OFFSET 0x10
#define T_STATUS_OFFSET 0x0C

// Set the t_SUPC register
volatile uint32_t *t_SUPC = (volatile uint32_t *)T_SUPC_BASE;
// Set the t_BOD33 register
volatile uint32_t *t_BOD33 = (volatile uint32_t *)(T_SUPC_BASE + T_BOD33_OFFSET);
// Set the t_STATUS register
volatile uint32_t *t_STATUS = (volatile uint32_t *)(T_SUPC_BASE + T_STATUS_OFFSET);

void setup()
{
    // Clear bit 1 in t_BOD33 and then set it to 1
    *t_BOD33 &= ~(1u << 1); // Clear bit 1

    // Check bit 0 in t_STATUS and loop while it is 0
    while ((*t_STATUS & 0x01) == 0)
    {
    }

    *t_BOD33 &= (0x7D0300u << 1);

    *t_BOD33 |= (1u << 1); // Set bit 1 to 1
    while ((*t_STATUS & 0x01) == 0)
    {
    }

    while ((*t_STATUS & 0x02) != 0)
    {
    }

    // Clear bit 1 in t_BOD33 and then set it to 1
    *t_BOD33 &= ~(1u << 1); // Clear bit 1
    while ((*t_STATUS & 0x01) == 0)
    {
    }
    *t_BOD33 |= (1u << 2);
    *t_BOD33 &= ~(1u << 3);
    *t_BOD33 |= (1u << 1); // Set bit 1 to 1
}

source: Stack Exchange

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/

sort: votes


text:
Pump running even if relay says "off"
I have a relay that should be switched off when the analog value is too high by the Arduino code:
int digitalPin = 4; // for the relay
int analogPin = A0; // for the soil moisture sensor
int digitalVal; // digital readings
int analogVal; // analog readings

void setup()
{
    pinMode(digitalPin, OUTPUT);
    digitalWrite(digitalPin, LOW);
    Serial.begin(9600);

}

void loop()
{
    analogVal = analogRead(analogPin); // read the value returned by the soil moisture sensor
    if (analogVal < 400) { // if the soil moisture sensor returns a value < 400
        digitalWrite(digitalPin, HIGH); // The water pump waters the plant
    } else {
        digitalWrite(digitalPin, LOW); // The water pump stops watering
    }
    Serial.println(analogVal);
    delay(100);
}

But, as you can see on the video, despite going above the 400 threshold, having the relay pin switching off, it continues to pump.
Here is my architecture:

I just changed the relay to an Elegoo 4:

I am following this tutorial.

you have to connect the relay to the controlled pin

don't use the arduino as a power supply for the motor ... it could destroy the arduino

Oh, right @jsotola but isn't it what I did? (I just uploaded a photo of my attempt to implement the sketch)
Thanks for the tip for the power supply. I will look for one when I will be sure my thing is working properly :)

isn't it what I did? ... no, the wiring diagram shows otherwise

Oh, you mean that the green and the light blue wires should be the same? So the relay would be connected to the control pin ?

"I will look for one when I will be sure my thing is working properly :) " Sounds like the chicken and egg thing. Expensive if the arduino fails. Note: "A Power Supply the Arduino is NOT!" A mistook could also take out your computer.

you mean that the green and the light blue wires should be the same? ... no ... your code shows the control pin to be pin 4 ... your wiring diagram show a connection at pin 2

yes, I think that's a mistake from the tutorial @jsotola as the video accompanying it says to connect the (S) pin of the relay to pin4 of the Arduino

why are you posting inaccurate material? ... there is no reason why anyone should have to watch a video to learn what you are doing ... questions should be self contained  without need for external links

hmm, I think I've posted the inaccurate material because it is the context of the question @jsotola    My question is about the pump working continuously while the relays should stop it at some point

Do you hear the relais switch? Its PCB has an LED, does it reflect the expected state? Only if that is correct, you should think about adding the pump.

Can you post your connection diagram? A hand-drawn document is better than the wrong diagram in the question.

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/


text:
ATMEGA2560 died inside a arcade game circuit
I am building arcade game with 10 player buttons (5 for each player) and one start button. All buttons have build in LED inside. Player buttons has LED for 12V and start button has led for 5V. I am using ATMEGA2560 pro boar. I have also 4 TM1637 displays (two for each player) showing time and score. I am using 12V adapter. This is my schematic:

This is test code which I had:
#include <Arduino.h>
#include <TM1637Display.h>

#define BTN_A1_PIN 16
#define BTN_A2_PIN 18
#define BTN_A3_PIN 28
#define BTN_A4_PIN 26
#define BTN_A5_PIN 47

#define BTN_B1_PIN 44
#define BTN_B2_PIN 36
#define BTN_B3_PIN 39
#define BTN_B4_PIN 46
#define BTN_B5_PIN 37

#define LED_A1_PIN 13
#define LED_A2_PIN 17
#define LED_A3_PIN 11
#define LED_A4_PIN 15
#define LED_A5_PIN 19

#define LED_B1_PIN 25
#define LED_B2_PIN 27
#define LED_B3_PIN 23
#define LED_B4_PIN 21
#define LED_B5_PIN 29

#define BTN_START_PIN 32
#define LED_START_PIN 35

#define DISPLAY_A_SCORE_CLK 20
#define DISPLAY_A_SCORE_DIO 10

#define DISPLAY_A_TIME_CLK 40
#define DISPLAY_A_TIME_DIO 43

#define DISPLAY_B_SCORE_CLK 42
#define DISPLAY_B_SCORE_DIO 33

#define DISPLAY_B_TIME_CLK 34
#define DISPLAY_B_TIME_DIO 38

typedef struct
{
  uint8_t btnIn;
  uint8_t ledOut;
} btn_t;

btn_t btn[] = {
    {
        .btnIn = BTN_A1_PIN,
        .ledOut = LED_A1_PIN,
    },
    {
        .btnIn = BTN_A2_PIN,
        .ledOut = LED_A2_PIN,
    },
    {
        .btnIn = BTN_A3_PIN,
        .ledOut = LED_A3_PIN,
    },
    {
        .btnIn = BTN_A4_PIN,
        .ledOut = LED_A4_PIN,
    },
    {
        .btnIn = BTN_A5_PIN,
        .ledOut = LED_A5_PIN,
    },
    {
        .btnIn = BTN_B1_PIN,
        .ledOut = LED_B1_PIN,
    },
    {
        .btnIn = BTN_B2_PIN,
        .ledOut = LED_B2_PIN,
    },
    {
        .btnIn = BTN_B3_PIN,
        .ledOut = LED_B3_PIN,
    },
    {
        .btnIn = BTN_B4_PIN,
        .ledOut = LED_B4_PIN,
    },
    {
        .btnIn = BTN_B5_PIN,
        .ledOut = LED_B5_PIN,
    },
    {
        .btnIn = BTN_START_PIN,
        .ledOut = LED_START_PIN,
    },
};

TM1637Display displayAScore(DISPLAY_A_SCORE_CLK, DISPLAY_A_SCORE_DIO);
TM1637Display displayATime(DISPLAY_A_TIME_CLK, DISPLAY_A_TIME_DIO);
TM1637Display displayBScore(DISPLAY_B_SCORE_CLK, DISPLAY_B_SCORE_DIO);
TM1637Display displayBTime(DISPLAY_B_TIME_CLK, DISPLAY_B_TIME_DIO);

void setup()
{
  for (int i = 0; i < 11; i++)
  {
    pinMode(btn[i].btnIn, INPUT_PULLUP);
    pinMode(btn[i].ledOut, OUTPUT);
  }
  displayAScore.setBrightness(0x0f);
  displayATime.setBrightness(0x0f);
  displayBScore.setBrightness(0x0f);
  displayBTime.setBrightness(0x0f);

  displayAScore.showNumberDec(1111, false);
  displayATime.showNumberDec(2222, false);
  displayBScore.showNumberDec(3333, false);
  displayBTime.showNumberDec(4444, false);
}

void loop()
{
  for (size_t i = 0; i < 11; i++)
  {
    if(0 == digitalRead(btn[i].btnIn))
    {
      digitalWrite(btn[i].ledOut, HIGH);
    }
    else
    {
      digitalWrite(btn[i].ledOut, LOW);
    }
  }
}

And this is what it looks like inside:

The problem is ATMEGA2560 just burned. I was testing it firstly without TM1637 (they were connected to power but I did not use lib for them at that time) and it was working okay (buttons were lighting up upon pressing).
Then I added lib for TM1637 to code and for 2 seconds I saw "1111" "2222" ... so on as it is in code, so there is no bad connection. But after 2 seconds it started buzzing (probably linear regulator temp protection was kicking in) and ATMEGA just burned.
Now when I plug 12V in it MCU gets hot pretty fast. I can measure 5V on the linear regulator so it is not shorted. I had always connected only 12V and no power from USB. I know my wires are not the shortest but I would not expect that MCU dies. Could you help please? I don't want to plug the next 20€ chip just to see another expensive smoke.

either something is miswired, or a component is not what you think it is ... maybe the buttons have an internal connection between the switch and the indicator LED

@jsotola thanks for answer. I double checked every connection and it was correct. No, buttons are not connected with LEDs

The 5V pin on the board probably isn't a good place to pull power for the displays.  I'm sure that's more than it can supply.  Ideally they should have their own power supply.

You fried it because you broke rule #1: "A Power Supply the Arduino is NOT!". Your displays can pull 320 Ma in themselves. That is over 2 watts of power before anything else. When you get a new one purchase a buck converter and power the LEDs with the 5V output of that, use the 12V to feed it. As I understand it The suggested maximum power dissipation for the Mega regulator is 1 Watt. So with 12V into the regulator the max current is about 140 mA (1W / (12V - 5V)), This does not count your LEDs.

I was counting on the protection circuit of the regulator, these linear ones use to have it. But is it strange why ATMEGA burned, but regulator is outputting 5V. I used separate supply for ATMEGA and displays and now it is working. Thanks for answer.


text:
How can I get the Arduino IDE v0021 running on Windows XP to communicate with the latest Nano v3.0
After reading another post
CH340 Nano avrdude: stk500_getsync() not in sync resp=0xa4
I have discovered that the bootloader on current Nano v3.0 has been upgraded. However, the advice given to overcome this problem is based around a more modern version of the Arduino IDE communicating with an old bootloader. I have the reverse problem. I damaged my Arduino Nano that was working with a laptop running Windows XP and bought a replacement. It obviously has the latest bootloader installed so my version of the Arduino IDE v0021 (recommended to run on Windows XP) can no longer upload sketches to the board.
I have uploaded GRBL v1.1h to the Nano board from an Arduino IDE v1.8.19 installation on a Windows 7 computer but the older version of GRBL Control v0.8.1 running on Windows XP has compatibility issues with GRBL 1.1h. I need to upload an earlier version of GRBL that is compatible with GRBL Control v0.8.1 but the bootloader on the new Arduino Nano v3.0 runs at 115200 and the Arduino IDE v0021 expects a baud rate of 57600 so I get these errors

stk500_getsync():not in sync: resp=0x09
stk500_disable(): protocol error, expect=0x14, resp=0x51

Can I upload an older bootloader to a newer Arduino Nano so I can then flash an older version of GRBL that is compatible with GRBL Control v0.8.1 to run on Windows XP?

replace the bootloader. the new Nano has the same ATmega328p MCU as the old

So it is possible to burn an old bootloader to a new Arduino Nano?

in what sense is your Nano "new"? how can the bootloader knew if it is old or new Nano? where would be a difference for the bootloader?

OK point taken. I will make the attempt and report the outcome.

Since at the end of the day it is Avrdude, which talks with the Nano, you can always read its documentation and use an appropriate command line to flash anything you want.

I guess a better advice would be to select Uno as board for the Nano with 'new' bootloader

I agree with Juraj that any bootloader can be uploaded to the newer version of the Nano. However, the process of doing so is not simple. With Windows XP SP3 installed on my laptop I was running Arduino IDE v0021. The process involves connecting an Arduino UNO R3 to the Arduino Nano v3.0 but first you have to communicate with both boards through the Arduino IDE v0021. This requires two different USB drivers. For Device Manager to recognise the UNO R3 I had to copy the "Drivers" folder from my Arduino IDE v1.8.19 installation on my Windows 7 computer to my Arduino IDE v0021 installation folder on my laptop. Inside that drivers folder is a file called "Old_Arduino_Drivers.zip". You need to expand that into the "Drivers" folder.
In Device Manager with the Arduino UNO R3 plugged in you can now update the driver for the "Unknown USB" device by searching in the "Drivers" folder. On my computer it installed it as Arduino UNO R3 on COM7. It may be a different COM port on your computer. NOTE: FTDI and CH340 drivers will NOT work on Windows XP with the Arduino UNO R3.
Now disconnect the Arduino UNO R3 and connect the Arduino Nano v3.0. Once again Device Manager should not recognise it. Search the "Drivers" folder once again and it should find a driver. However, this time it will use an FTDI driver to install the Nano. It showed up in Device Manager as USB Serial Port on COM5.
After both these drivers were successfully installed my Arduino IDE v0021 could communicate with both Arduino boards and it could upload sketches to the Arduino UNO R3 but not the Nano...yet. I connected the Arduino UNO R3 and uploaded, "ArduinoISP" from the menu File >> Examples.
I then unplugged the USB cable from the Arduino UNO R3 and physically connected wires between the UNO and the Nano (see the connection diagram here).
With both boards wired correctly, plug the USB cable back into the Arduino UNO R3. You should see LEDs light up on both boards. Open the Arduino IDE v0021 and from the Tools menu select "Arduino Duemilanove or Nano w/ ATmega328" as the board. NOTE: Do NOT select "Arduino Uno" even though it is the board connected to your computer. You are about to burn a new bootloader to the Nano not the Uno. Next select whatever serial port has been allocated to the device. In my case COM7 was allocated to the UNO.
Now from the "Tools" menu select "Burn Bootloader >> w/ Arduino as ISP". This worked for me and I was finally able to upload sketches to the Arduino Nano v3.0 using the old version 0021 of the Arduino IDE on Windows XP.

btw it is better to use the Nano as Uno. you have then the smaller ('new') Optiboot bootloader and a right fuse setting for the bootloader size leaves more flash memory for the sketch


text:
avrdude: ser_open(): can't open device "\\.\COM5": Access is denied
I'm getting the error as follows

Sketch uses 2952 bytes (9%) of program storage space. Maximum is 32256 bytes.
Global variables use 196 bytes (9%) of dynamic memory, leaving 1852 bytes for local variables. Maximum is 2048 bytes.
avrdude: ser_open(): can't open device "\.\COM5": Access is denied.
Failed uploading: uploading error: exit status 1

The board I am using is Arduino Uno and checked the ports too. Also restarted and installed IDE again. But still not being able to deal with it.
I will be happy with the help!

Are you sure that COM5 is your Arduino Uno? On the device manager check if you unplug Arduino Uno, COM5 goes away.

In Windows (if you are using windows), There are two things may caused the problem:

go to device manager >> ports >> and Uninstall all ports related to Arduino (including the COM5). Then connect the arduino again and it install it again automatically.
Make sure that you close all "serial monitor", before uploading the sketch.

I did that too. I even tried with Arduino cloud web editor. But no results.

I am sure about it. I am aware of the above mentioned method. And even tried with other ports. Still the error message is same.


text:
Connecting nRF24L01 to ATmega328PU with external 8 MHz crystal problem
I am trying to fix the problem of communicating between two nRF24L01+ together, one connected to an Arduino Uno and another connected to an ATmega328PU with an 8 MHz external crystal.
The bootloader on the ATmega328PU is “Arduino Pro or Pro Mini” 3.3 V, 8 MHz.
The problem is that the nRF24L01+ on the ATmega328PU is not responding (working). I am using the RF24 library as shown in the code below.
There are several things that I have already tried:

To make sure that both nRF24L01+ modules work, I connected one to an Arduino Uno and another to an Arduino Mega and they work perfectly. So, the problem is not with the nRF modules.
I changed the external crystal of the ATmega328PU to 16 MHz and changed the bootloader to Arduino Uno; didn’t work again.

The circuit diagram is shown below:

Transmitter code:
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

RF24 radio(7, 8); // CE, CSN

const byte address[6] = "00001";
const int btn = 4;
int buttonState = 0;
int programState = 0;

void setup() {
  radio.begin();
  radio.openWritingPipe(address);
  radio.setPALevel(RF24_PA_MIN);
  radio.stopListening();
  pinMode(btn, INPUT);
}

void loop() {
  buttonState = digitalRead(btn);
    // check if the pushbutton is pressed. If it is, the buttonState is HIGH:
    if ((buttonState == LOW) && (programState == 0)) {
      programState = 1;
    }

    else if ((buttonState == HIGH)&& (programState == 1)) {
      const char text[] ="Hello World"; // you can customize this text to your wish
      radio.write(&text, sizeof(text));
      programState = 0;
      Serial.println("BUTTON");

      delay(1000);
  }
}

Receiver code:
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
RF24 radio(7, 8); // CE, CSN
const byte address[6] = "00001";
const int output = 2;

void setup() {
  Serial.begin(9600);
  radio.begin();
  radio.openReadingPipe(0, address);
  radio.setPALevel(RF24_PA_MIN);
  radio.startListening();
  pinMode(output,OUTPUT);
  digitalWrite(output, LOW);
  delay(1000);
}

void loop() {
  if (radio.available()) {
    char text[32] = "";
    radio.read(&text, sizeof(text));
    Serial.println(text);
    if (strcmp(text,"Hello World")==0) {
      Serial.println("CORRECT");
      digitalWrite(output, HIGH);
      delay(2000);
      digitalWrite(output, LOW);
      delay(2000);
    }
  }
}

Crystal is an electronics component where you need to have certain knowledge about electronic design, you can't just plug in a crystal and hoping it will work. Different crystals have different load capacitances (this will involving reading the datasheet of the crystal) and need some calculation to get the right load capacitors in order for it to work properly.

I am not sure how did you find that I put crystal resonator (oscillator) in the circuit without knowing what I am doing! Each electronic component has datasheet that everyone read it before using them. I used crystal with 22pF capacitor as stated in its datasheet and as suggested in Atmega328PU datasheet.

Well, if you search for 8MHz crystal, you will noticed that different crystal has different load capacitance. You need to read the datasheet of your crystal, not the datasheet of the MCU, then you need to do some calculation based on load capacitance datasheet told you to come out the correct capacitors for the particular crystal. BTW, If I remember correctly ATmega328 datasheet give a range of 12-22pF, depend on the crystal you are using.

The bare ATmeaga328P Fritzing diagram has an error in that only one leg of the right  hand crystal load capacitor is connected to anything.

I am assuming that your barebone Atmega328PU can run simple sketches e.g. LED blink?

@Fahad Yes it can run LED blink

Here are a couple of things you can try. Because it sounds like the hardware setup is giving you issues. Because the same code worked on a mega as you mentioned.
I am assuming you will be using arduino uno bootloader and 16mhz crystal oscillator. Add a pull-up on the reset pin. Use a 5V supply for the mcu (better if you can use a regulator). Connect 5V to pin 7 and 20 and GND to pin 8 and 22 (your image doesnt show that). Use a filtering capacitor between pin 7 and 8. Make sure crystal is connected properly with caps (image shows one pin is not connected). .....

.....Module needs 3.3V. So don't connect 5V. The pin of the modules is 5V tolerant. With that, first check if you can run the blink example, by actually blinking an LED. Then try your code.

A Power Supply the Arduino is Not! Generally but not always they fail when connecting radios to them, this is intermittent and will drive you bonkers trying to find it.

depend on how you flash bootloader you may want to set fuses corresponding to 8MHz external crystal.

Assuming a basic test of the MCU works, say the blink sketch works at normal speed (0.5 Hz), try this format of the constructor:
RF24 radio(7, 8, 4000000); // set SPI speed to 4MHz instead of default 10MHz
The default of 10MHz maybe too high for your MCU configuration.
From https://github.com/nRF24/RF24/blob/master/COMMON_ISSUES.md
Some more things to try:
EDIT
Most Nrf24L01 problems are related to an inadequate power supply. Some 3.3 volt power supplies, say those of a Nano where the 3.3 volts is derived from the USB/UART adaptor, don't work well here. You could try adding two capacitors across the power rails at the point on the breadboard where the power for the nrf24L01 is taken. Use a 100nF ceramic and a 10 to 100uF electrolytic. You barebones atmega328p should anyway have its own decoupling capacitor as close as possible to the chip's power pins. Use a 100nF ceramic.
The link above has other trouble shooting measures.

Tried didn't work.

@Jondepoy I've added some more suggestions in the answer.


text:
NodeMCU code that both display OLED and control WS2812 LED Ring
I'm trying to make a project using NodeMCU that show pictures in small OLED screen and also controlling WS2812 LED Ring.
I manage to do each of them separately but I'm not sure how to mix them together. The problem lies in the fact that most code examples for both the screen and the LED use sleep and that will of course only work for one of the other but not both.
This is the first project I've looked at to display bitmaps with SSD1306  screen and nodemcu.
This is the second project I've looked at to control NeoPixel WS2812 ring.
The main project was that both of them use delay as a way to wait for some amount of time to "progress". But, I couldn't just wait because then it will mess up both the screen and the NeoPixel.
One more thing is I have to also take reading input into account. I still not 100% sure about the input but it will probably be potentiometer and maybe a button.
I think I have found the solution which is to break the large "tasks" of reading input, controlling screen and controlling leds into smaller parts and do the waiting in a cooperative way.
I've found this instructable which both explain how to do it and also provide code example.
I'll be glad to know if people how other ways to implement this.

I'm not sure how to mix them together ... how do you drink some water while eating dinner?

Why don't you post your code? We can take a look at it and probably suggest something to get you started.

There is an example called BlinkWithoutDelay (you can find that in the Arduino IDE by going to Files->Examples->02.Digital). That gives you an idea of how you can do your things without using delay(). The third link you added uses that concept.

You need to stop using delay and instead keep track of elapsed time. One of the comments under your question suggests looking at the BlinkWithoutDelay example, which is part of the Arduino IDE.
The jocular comment "how do you drink some water while eating dinner" suggests the solution. You do one thing for a moment, and then do another thing. When eating dinner you don't wait for the entire meal to be consumed before you can drink a glass of water.
Here's some example code that blinks two LEDs at different rates:
// Which pins are connected to which LED
const byte greenLED = 12;
const byte redLED = 13;

// Time periods of blinks in milliseconds (1000 to a second).
const unsigned long greenLEDinterval = 500;
const unsigned long redLEDinterval = 1000;

// Variable holding the timer value so far. One for each "Timer"
unsigned long greenLEDtimer;
unsigned long redLEDtimer;

void setup ()
  {
  pinMode (greenLED, OUTPUT);
  pinMode (redLED, OUTPUT);
  greenLEDtimer = millis ();
  redLEDtimer = millis ();
  }  // end of setup

void toggleGreenLED ()
  {
   if (digitalRead (greenLED) == LOW)
      digitalWrite (greenLED, HIGH);
   else
      digitalWrite (greenLED, LOW);

  // remember when we toggled it
  greenLEDtimer = millis ();
  }  // end of toggleGreenLED

void toggleRedLED ()
  {
   if (digitalRead (redLED) == LOW)
      digitalWrite (redLED, HIGH);
   else
      digitalWrite (redLED, LOW);

  // remember when we toggled it
  redLEDtimer = millis ();
  }  // end of toggleRedLED

void loop ()
  {

  // Handling the blink of one LED.
  if ( (millis () - greenLEDtimer) >= greenLEDinterval)
     toggleGreenLED ();

  // The other LED is controlled the same way. Repeat for more LEDs
  if ( (millis () - redLEDtimer) >= redLEDinterval)
    toggleRedLED ();

/* Other code that needs to execute goes here.
   It will be called many thousand times per second because the above code
   does not wait for the LED blink interval to finish. */

}  // end of loop


text:
Arduino AVR Program with default ATMEGA32U4 bootloader instead
I’m working an Arduino program that uses the FastLED library and is all coded in the Arduino IDE (not my choice, just a result of this OOS library).
However, I don’t want to run this on an “Arduino” board. Instead, I want to flash this to a factory fresh ATMEGA32U4 as an MCU for the project. However, the ATMEGA32U4 doesn’t come with the Arduino boot loader, but instead, DFU. I have flashing procedures designed for the DFU boot loader already and I don’t want to go swapping bootloaders.
Would the Arduino program work fine without swapping to the Arduino bootloader? My understanding is yes since the bootloader only controls the boot sequence, and has nothing to do with runtime.

You are using an Arduino Library (in C++), and even an Arduino IDE, so whether you like it or not, you are running the code under the Arduino framework as an "Arduino" board. So what is the issue of trying to avoid the boot loader? Even you set you your programming using {DFU programmer](https://support.arduino.cc/hc/en-us/articles/4408887452434-Flash-USB-to-serial-firmware-in-DFU-mode), you are still running as an Arduino board under the Arduino framework!

Please try this: Export the compiled sketch as hex file and flash it with DFU.

Would the Arduino program work fine without swapping to the Arduino bootloader?

Yes, the bootloader is only there for conveniently changing program memory via serial instructions.
Whatever method you use to put the "main" code there, it will be the same code and will operate the same.


text:
Changing SPI ports on an Arduino
My end goal is to read information from an nRF24l01 module connected to my Arduino UNO R3, and generate an interrupt whenever a message is sent to the Arduino.
Now, I have read that for Hardware interrupts, only pins D2 and D3 can be used to generate interrupts. However, while connecting the MISO line, I saw that here it was mentioned that

On some Arduino boards (see table above), pins MOSI, MISO and SCK are the same pins as digital pin 11, 12 and 13, respectively. That is why many tutorials instruct you to hook up the target to these pins.

On every website I have searched, MISO is always connected to 12. Is there any way to change the MISO line from 12 to 3, or will I have to resort to using Pin change interrupts? Another way I can think of to bypass this is to connect D12 to D3, but I'm afraid this may cause complications in the circuit.

SPI (and all the none-GPIO peripherals) has its own interrupt that you can enable it by setting the SPE bit of the SPI Control Register, and when a data is received an interrupt would be triggered. Search for SPI Slave example or read my blog for the section of SPI Slave .

If you are using Arduino Uno (based on ATMega328 chip), it does not support alternative pin for SPI port. On your assumption that " MISO is always connected to 12", this is only true for Arduino board based on ATMega328. For other Arduino Core (e.g. ESP or STM32), or even different MCU(e.g. Arduino Leonardo which is based on ATMega32U4) using the same Arduino AVR Core, this will not be the case.

Thanks!That works for me

The NRF24L01 itself can optionally generate an interrupt on receiving a message. The pin on the NRF24L01 is marked IRQ where it is broken out on most modules. You can connect this to an external interrupt pin on a Uno or use any pin which configured for a pin change interrupt. I am not sure how far you will get attempting to use MISO for the same purpose.  See here for an example: https://howtomechatronics.com/tutorials/arduino/arduino-wireless-communication-nrf24l01-tutorial/

@6v6gt the IRQ line, in idle state, is HIGH or LOW? I am asking because I want to fill in the last parameter of attachInterrupt(digitalPintoInterrupt(3), func_name, ________) correctly.

The IRQ pin is active LOW according to this: https://www.sparkfun.com/datasheets/Components/SMD/nRF24L01Pluss_Preliminary_Product_Specification_v1_0.pdf . I'd use the input pin pullup resistor and look for a falling edge. The pins should be 5v tolerant. You may have to explicitly enable the IRQ pin using the NRF24L01 library: https://nrf24.github.io/RF24/classRF24.html#abf68b9b0c9cd17179e9e144c3e7f9c45

Thanks @6v6gt for the help

If it works as you want, then add an additional answer in the thread saying what you did, It may help someone else.

@6v6gt Look, this is why answers are supposed to go in answer boxes. Grrr. I scanned the answers to see if anyone had answered the question about the IRQ pin and saw no such answer. So I typed my own. Then I see your comment above answering the question and mentioning the IRQ pin. And now we have, forum-style, more comments querying how your "answer" works. Please, please use the answer "feature" to answer questions. Then comments under the answer make sense. This isn't a forum.

@nickgammon Yes. Sorry. It was a special case. As you have seen, the OP's question had nothing to do with what he wanted to achieve so an answer would not have matched the question. I had tried to get him to sort it out by adding his own answer based on his own experience of the suggested IRQ method but, alas, that never happened.

I have read that for Hardware interrupts, only pins D2 and D3 can be used to generate interrupts

The pin-change interrupts, available on all pins of the Arduino Uno, are almost as good. I say "almost" because the only thing you have to do is work out which pin caused the interrupt, which can be trivial if you only set up one pin to generate interrupts.

Is there any way to change the MISO line from 12 to 3,

Not if you used the hardware SPI on the chip. If you use bit-banged SPI you can use any pins.
I did a project for a temperature and humidity sensor, which logs to a SD card (using SPI), and also displays on a 8-digit display (using SPI). For the latter case I used bit-banged SPI, as described there.
I have a page about SPI and also a similar one on Stack Exchange.
My bit-banged SPI code is available here.

I'm not clear about why you don't just use the hardware SPI pins. Is that you want an interrupt when a SPI message arrives? There is a hardware interrupt for just that. See my posts about SPI for more details about that.

"Is that you want an interrupt when a SPI message arrives?" :My end goal is to read information from an nRF24l01 module connected to my Arduino UNO R3, and generate an interrupt whenever a message is sent to the Arduino. So yeah, that's exactly what I'm looking for.

Actually I've never used bit-banging before, so I will just dive a bit more into the topic. Thanks for the resources.

An SPI interrupt would seem to meet your requirements, no need to muck around trying to generate a different sort of interrupt.

Thanks, Nick, for the help.

Nick, a SPI slave can only send data if requested by the master. so if polling SPI in master is not good enough, there must be some other way for the slave to signal to master that it should do a request.

@Juraj OK, but in that case the slave won't be doing an unsolicited send. So therefore the slave would be sending a signal using some other pin (eg. "data ready"?) which could be connected to pin 2 or pin 3 for an interrupt.

In the example on the linked page the receiver just polls for a message to appear.

@Juraj Ach, I see we have an XY problem here. I made another answer. This answer is still "good" in the sense that it answers the question in bold asked by the OP. My other answer deals with the Y part of the problem.

My second answer ...
Your question, in bold, is a good example of an XY Problem. You asked:

Is there any way to change the MISO line from 12 to 3, or will I have to resort to using Pin change interrupts?

This is the X question. However the Y question is your goal:

My end goal is to read information from an nRF24l01 module connected to my Arduino UNO ...

I answered, in another answer, first about changing the MISO line from pin 12, and also pointed out that SPI transactions can generate interrupts.
However, as Juraj pointed out in a comment, the Arduino in this case is the master and the nRF24l01 is the slave (from the SPI point of view).
There is no way that a slave can burst into life and generate a message, and hence cause an interrupt. That is the master's job.
As I read on this page about the module it has an IRQ pin described thus:

IRQ is an interrupt pin that can notify the master when there is new data to process.

So, your job is simplified, really. You don't need to detect when an SPI transaction starts (the Arduino will start the transaction), you need to connect the IRQ pin to an Arduino pin and detect that data is ready. Simple! Then you can easily use pin 2 or pin 3 if you want to use the "hardware" interrupts rather than the pin-change interrupts. (The pin-change interrupts are hardware interrupts too, though).

I would say Y is the pseudo-problem which doesn't need a solution (move MISO to interrupt pin). the real problem X is the right use of the IRQ pin


text:
ESP8266 Wifi connection problem
I have a Feather Huzzah, aka ESP8266, that I am trying to connect to the Wifi.
One major thing is, that my landlord decided to use the worst Wifi SSID and PW.
The SSID contains an ä and a whitespace, and the PW an @.
I scanned successfully the Wifi with the board and the prewritten code and the Wifi shows up.
Now I am using the Wifi client basic, just to check if any connection can established.
I tried to write all special characters in Unicode, but still no change.
Here is my code:
/*
This sketch sends a string to a TCP server, and prints a one-line response.
You must run a TCP server in your local network.
For example, on Linux you can use this command: nc -v -l 3000
*/

#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>

#ifndef STASSID
#define STASSID "XXX XXäXX"      //original SSID
#define STASSID "XXX XX\u00e4XX" //Unicode SSID
#define STAPSK "XXX@XXX"        //Orginal PW
#define STAPSK "XXX@XXX"        //Unicode PW
#endif

const char* ssid = STASSID;
const char* password = STAPSK;

const char* host = "192.168.1.1";
const uint16_t port = 3000;

ESP8266WiFiMulti WiFiMulti;

void setup() {
  Serial.begin(115200);

  // We start by connecting to a WiFi network
  WiFi.mode(WIFI_STA);
  WiFiMulti.addAP(ssid, password);

  Serial.println();
  Serial.println();
  Serial.print("Wait for WiFi... ");

  while (WiFiMulti.run() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  delay(500);
}

void loop() {
  Serial.print("connecting to ");
  Serial.print(host);
  Serial.print(':');
  Serial.println(port);

  // Use WiFiClient class to create TCP connections
  WiFiClient client;

  if (!client.connect(host, port)) {
    Serial.println("connection failed");
    Serial.println("wait 5 sec...");
    delay(5000);
    return;
  }

  // This will send the request to the server
  client.println("hello from ESP8266");

  // read back one line from server
  Serial.println("receiving from remote server");
  String line = client.readStringUntil('\r');
  Serial.println(line);

  Serial.println("closing connection");
  client.stop();

  Serial.println("wait 5 sec...");
  delay(5000);
}

Thank you for any help, and greetings from Sweden.

I copied ä into notepad++ and viewed the character using the hex editor plugin ... it consists of two bytes c3 a4

Don't get me wrong, but what am I supposed to do with that answer? I am not deep into Arduino programming unfortunatly. Can I convert bytes into chars?

it is just information, not an answer ... an answer would be in the "answer" section ... this site is not a forum

convert the bytes to char and insert them into the SSID   ... I have no idea if the result will work ... I would start with a known SSID that does not include problem characters ... connect the usual way to confirm connectivity ... then replace one of the characters with same character and confirm that connectivity is still good ... that will ensure that the character insertion code is valid

I don't have enough reputation to comment, otherwise this would be a comment, but you could ask your landlord to change the password. If he says no, you could say one of your devices can't type that character.

Yeah, I start to belief that this is the only solution :D

Start with a known simple SSID, and try this:
#define STASSID "mywifi" // For example this is the known SSID that connects
... ... ...
const char ssid[] = "mywifi";

If that works, then you can replace the char with hex.
const char ssid[] = {0x6D, 0x79, 0x77, 0x69, 0x66, 0x69};

If that works then you can replace the hex bytes with your actual SSID. And in the place of ä use those two hex bytes as jsotola mentioned, 0xC3 and 0xA4.

Edit 1:
From the comment, it looks like the receiver never connects to the WiFi. In the receiver hardware, try something simple and see if it gets connected at all or not.
#include <ESP8266WiFi.h>

void setup()
{
  Serial.begin(115200);
  Serial.println();

  WiFi.begin("network-name", "pass-to-network");

  Serial.print("Connecting");
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }
  Serial.println();

  Serial.print("Connected, IP address: ");
  Serial.println(WiFi.localIP());
}

void loop() {}

Check what output you get.

Good hint. I connected the board to the Hotspot of my phone and it worked. So good so far. But when I try my local wifi again, I does not like it.  I replaced the const char ssid[] and password with raw hexadezimals and ran it trough several converters. When I print it out it looks fine.  But when i print out the password it is the correct password + the ssid again?! Like it is one variable, added together? Is that only due to the serial printout?

That doesn't sound right. Can you post the code that you mentioned in the comment where the password prints both password and SSID?

#ifndef STASSID
#define STASSID {0x6D, 0x79, 0x77, 0x69, 0x66, 0x69}
#define STAPSK {0x6D, 0x79, 0x70, 0x61, 0x73, 0x73, 0x77}
#endif
const char ssid[] = STASSID;
const char password[] = STAPSK;
... ... ...
Serial.print("Connecting to ");
Serial.print(ssid);
Serial.print(" ");
Serial.print(password);

Connecting to mywifi mypasswmywifi

Sorry, I cant edit it for better readability. I don't get it how to do that

No worries. Let me check.

Ok, that is happening because you are printing the array. Before when you defined your ssid and password, you used a string like this "mypassword". In that case, after the letter, there is a null-terminated character 0x00. So when tried to print that the print() knew when to stop, whenever it saw 0x00. But in the comment code, you are defining ssid and password as an array. So there is no "extra" null character. So print() doesn't know when to stop. when you printed the password it probably had the SSID in the print buffer from the previous print. You can't print an array like that.

Ok, well, it was just a test anyway. It should not make any difference in the internal handling. So, where else could be the problem? Security of the router?

@DaMusikant I updated the answer.

Finally I had some time again. I have some interesting things discovered. When I tried to connect to my hotspot it worked. But when I translated this name and pw it didin't connect. Instead, I saw my phone toggeling that someones connected and then not, in a half second intervall. It seems the controller itself has issues with hexadecimals. What is going on there?


text:
Problem when coding 4x4 keypad's key detection (without library)
Part of my current assignment involves reading the input from a 4x4 keypad connected to an Arduino UNO. While this may be done easily using <Keypad.h>, the project is being done with Tinkercad's online simulator, meaning I don't have access to that library. I have to do it the manual way.
This is the code I've got so far:
#include <Wire.h>
#define DIMENSIONS 4
const unsigned long period = 50;
unsigned long prevMillis = 0;
byte modo = 0;
const byte rowsPins[DIMENSIONS] = {11, 10, 9, 8};
const byte columnsPins[DIMENSIONS] = {7, 6, 5, 4};
char keys[DIMENSIONS][DIMENSIONS] = {
    {'1', '2', '3', 'A'},
    {'4', '5', '6', 'B'},
    {'7', '8', '9', 'C'},
    {'*', '0', '#', 'D'}
};

void setup()
{
    Serial.begin(9600);// debug
    for(byte i = 0; i < DIMENSIONS; i++){
        pinMode(columnsPins[i], INPUT);
        digitalWrite(columnsPins[i], HIGH);
        pinMode(rowsPins[i], INPUT_PULLUP);
    }
    Wire.begin();
}

void loop()
{
    switch(modo){
        case 0:
            Serial.print("Master (2) boot up\n");
            modo++;
            break;
        case 1:
            if(millis() >= 1000){
                modo++;
            }
            break;
        case 2:
            if (millis() - prevMillis > period){
                prevMillis = millis();
                for(byte c = 0; c < DIMENSIONS; c++){
                    pinMode(columnsPins[c], OUTPUT);
                    digitalWrite(columnsPins[c], LOW);
                    for(byte r = 0; r < DIMENSIONS; r++){
                        if(digitalRead(columnsPins[r]) == LOW){
                            Serial.println(keys[r][c]);
                        }
                    }
                    digitalWrite(columnsPins[c], HIGH);
                    pinMode(columnsPins[c], INPUT);
                }
            }
            break;
        default:
            break;
    }
}

(the "modes" and Wire.h are a different part of the assignment and not related to my issue)
This code should, in theory, read the input from the connected 4x4 keypad and then print on the serial monitor which key was pressed. I've done a fair bit of searching, and other solutions for detecting key presses without the Keypad library aren't super different from what I've done here. However, for some reason, what I wrote is not working properly for me.
On starting the simulation, the serial monitor prints 1, 5, 9, D continuously and repeatedly on a loop. Pressing the keys does sometimes print the appropriate character, but it does not stop the flood of 1s, 5s, 9s and Ds.
I know for a fact that it's not a matter of the pins being misconnected, I've checked for that at least a dozen times by now. It's most certainly a matter of code... but I can't figure out where the problem lies.

you could add a 4x4 array to store button state ... then do a 50 ms debounce delay whenever the button state changes

In case 2:
digitalWrite(columnsPins[c], LOW);
for(byte r = 0; r < DIMENSIONS; r++){
   if(digitalRead(columnsPins[r]) == LOW){
   Serial.println(keys[r][c]);
   }
}

Since you just wrote one of the column pins low, you can guarantee that one is going to read low.  Did you mean to read the row pins?

I can't believe I did not notice such an obvious mistake. Thanks for the save, Delta_G.

Post a annotated schematic as to how you have actually wired the keyboard, be sure to show all resistors and diodes.

@Gil not a keyboard, just a humble 4x4 keypad. Here you go. It's extremely simple, the pins on the Arduino are connected directly to the keypad, so I didn't feel it was necessary to include it in the OP.

@Maf95 "When a programmer has a hard time finding a bug, it's because he's looking in the wrong place."


text:
Instructables "Omnibot" -- using the "real" Uno R3 board
Step 4 of this instructable uses what seems to be a "knock-off" development version of the Uno R3 board, where an RF receiver is soldered to pads that don't exist on the R3 or R3 SMD boards:
https://www.instructables.com/OmniBot-Easy-Arduino-RC-Robots/

...

Locate available Gnd, Vcc, and Rx holes on your Arduino. (if using the recommended Arduino they can be found all near each other just below the ICSP pins.)
Insert the tinned wires through their respective holes and solder on the back side. White to RX, red to 5V, black to GND.

...

I am completely new to Arduino, so I'm a little puzzled by the lack of VCC. Sounds like this is just power. Is there any reason I can't hook the RF receiver to the D0 (RX) pin, 5v out, and GND headers?

Vcc is positive voltage supply ... 5 V

your question becomes useless when the instructables link dies ... please add the necessary diagrams to your question

Yes, the holes they are showing it connected to are physically connected to the pins you mention.  Connecting directly to those pins would be equivalent.


text:
Expose two HID Joystick devices with single RP2040 board (Waveshare Pi Pico Zero)
I want to use a Waveshare Pi Pico Zero to connect two standard NES controllers to a computer over a single USB port.
I'm using the Waveshare RP2040 Zero board definition from https://github.com/earlephilhower/arduino-pico which seems to provide a Joystick HID library that was compatible with this Teensy targeted NES_to_USB sketch. However, that only works for a single NES controller.
I found Arduino-USB-HID-RetroJoystickAdapter that supports two joysticks or NES controllers using a single board using the MHeironimus ArduinoJoystickLibrary. Unfortunately it seems that particular Joystick library only supports ATmega32u4 based Arduino boards (e.g. Leonardo, Pro Micro).
Ask
A solution for exposing two USB HID Joystick devices on a single Pi Pico Zero board. First prize is a drop-in library like MHeironimus ArduinoJoystickLibrary that is compatible with https://github.com/earlephilhower/arduino-pico's RP2040 core. Happy to hear of more DIY solutions too, not sure if I'll be able to follow though :)

First prize is a drop-in library ... what does that mean?

First prize is a drop-in library -- Being able to simply install an existing library into Arduino that makes a second Joystick HID device available for Pi Pico like MHeironimus's ArduinoJoystickLibrary does for ATMega32u4 based boards.

this may help... https://eleccelerator.com/tutorial-about-usb-hid-report-descriptors/

I got some useful advice about how to use TinyUSB directly from the arduino-pico maintainer. If I manage to get something working I'll write it up as an answer.

OK, I got it working, in short, select "Adafruit TinyUSB" as the USB stack and then modify the Adafruit hid_gamepad.ino  example to have two different GP reports similar to the hid_composite example. The hard bit then is dealing with the Linux kernel's stupidity and having to enable HID_QUIRK_MULTI_INPUT mode to enable multiple HID reports of the same type on a single device to work. Bit late now, will write it up properly tomorrow.

By selecting the Adafruit TinyUSB USB stack option (Tools->USB Stack->Adafruit TinyUSB) of the arduino-pico core instead of the default (Pico SDK) the USB HID descriptors can be configured directly to expose two HID gamepads.
The disadvantage of this approach is that the easy to use preconfigured devices (e.g. Joystick, Mouse and Keyboard) are not configured, but this gives you the option to use the full flexibility of TinyUSB to configure USB devices. While I've used it with my Waveshare Pi Pico Zero board it should work with any Arduino board that Adafruit TinyUSB supports.
Here is a test sketch that sets up a HID device with two gamepads similar to the "Hey how about two players?" example in https://eleccelerator.com/tutorial-about-usb-hid-report-descriptors/. I modified the Adafruit TinyUSB hid_gamepad.ino example by adding a second Gamepad report and shortening the "demo" loop to save space:
/*********************************************************************
 Adafruit invests time and resources providing this open source code,
 please support Adafruit and open-source hardware by purchasing
 products from Adafruit!

 MIT license, check LICENSE for more information
 Copyright (c) 2021 NeKuNeKo for Adafruit Industries
 All text above, and the splash screen below must be included in
 any redistribution
*********************************************************************/

#include "Adafruit_TinyUSB.h"

// NB NB!!! Select "Adafruit TinyUSB" for USB stack

// HID report descriptor using TinyUSB's template
uint8_t const desc_hid_report[] =
{
  TUD_HID_REPORT_DESC_GAMEPAD(HID_REPORT_ID(1)), // First gamepad report-id 1
  TUD_HID_REPORT_DESC_GAMEPAD(HID_REPORT_ID(2))  // Second gamepad report-id 2
};

// USB HID object. For ESP32 these values cannot be changed after this declaration
// desc report, desc len, protocol, interval, use out endpoint
Adafruit_USBD_HID usb_hid(desc_hid_report, sizeof(desc_hid_report), HID_ITF_PROTOCOL_NONE, 2, false);

// Report payload defined in src/class/hid/hid.h
// - For Gamepad Button Bit Mask see  hid_gamepad_button_bm_t
// - For Gamepad Hat    Bit Mask see  hid_gamepad_hat_t
hid_gamepad_report_t   gp[2]; // Two gamepad descriptors

void setup()
{
#if defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_RP2040)
  // Manual begin() is required on core without built-in support for TinyUSB such as mbed rp2040
  TinyUSB_Device_Init(0);
#endif

  Serial.begin(115200);
  usb_hid.begin();

  // wait until device mounted
  while( !TinyUSBDevice.mounted() ) delay(1);
  Serial.println("Adafruit TinyUSB HID multi-gamepad example");
}

uint8_t gp_i = 0;

void loop()
{
  if ( !usb_hid.ready() ) return;

  Serial.print("Testing gamepad nr: ");
  Serial.println(gp_i);

  // Reset buttons
  Serial.println("No pressing buttons");
  gp[gp_i].x       = 0;
  gp[gp_i].y       = 0;
  gp[gp_i].z       = 0;
  gp[gp_i].rz      = 0;
  gp[gp_i].rx      = 0;
  gp[gp_i].ry      = 0;
  gp[gp_i].hat     = 0;
  gp[gp_i].buttons = 0;
  // gp_i + 1 is the HID report-id, i.e. 1 for first gamepad and 2 for the
  // second, as defined in desc_hid_report[] above.
  usb_hid.sendReport(gp_i + 1, &gp[gp_i], sizeof(gp[gp_i]));
  delay(2000);

  // Random touch
  Serial.println("Random touch");
  gp[gp_i].x       = random(-127, 128);
  gp[gp_i].y       = random(-127, 128);
  gp[gp_i].z       = random(-127, 128);
  gp[gp_i].rz      = random(-127, 128);
  gp[gp_i].rx      = random(-127, 128);
  gp[gp_i].ry      = random(-127, 128);
  gp[gp_i].hat     = random(0,      9);
  gp[gp_i].buttons = random(0, 0xffff);
  usb_hid.sendReport(gp_i + 1, &gp[gp_i], sizeof(gp[gp_i]));
  delay(2000);

  // select the other gamepad
  gp_i = (gp_i + 1) % 2;
}

Linux HID Malarkey
For some reason the Linux kernel by default ignores multiple reports of the same type of HID device. I.e. a device with a mouse, keyboard and joystick device reports are no problem, but if a device has multiple of the same HID reports, say, two gamepads, Linux will only see the first instance. To enable multiple instances the HID_QUIRK_MULTI_INPUT setting must be enabled for the specific USB device.
These instructions worked on Ubuntu 22.04, you may need to adjust them for your distro.
After programming the example sketch I could see the ID of my Pi Pico USB device with `lsusb:
$ lsusb
...
Bus 001 Device 011: ID 239a:cafe Adafruit RP2040 Zero
...

Note down the USB device identifier (239a:cafe) and create a file in /etc/modprobe.d to configure the usbhid module:
$ echo "options usbhid quirks=0x239a:0xcafe:0x040" | sudo tee /etc/modprobe.d/adafruit_hid_quirk.conf

$ sudo update-initramfs -u

# Requires a reboot to take effect, e.g.:

$ sudo shutdown -r now

The 0x239a:0xcafe is from the lsusb output and 0x040 is the magic number to enable HID_QUIRK_MULTI_INPUT mode. We need update-initramfs since usbhid is usually loaded too early in the boot process for the settings from /etc/modprobe.d to take effect without it being in the initrd.
Once you have rebooted you can check if the usbhid setting took effect:
$ cat /sys/module/usbhid/parameters/quirks
0x239a:0xcafe:0x040,(null),(null),(null)

and you should see two joystick devices after programming the sketch:
ls /dev/input/js*
/dev/input/js0  /dev/input/js1

Testing
An easy way to test is to navigate to https://gamepad-tester.com/. After a short period you should see something like:

You should see Player1's values toggle and then Player2's values until you unplug your pico.


text:
Arduino code intermittent
Have an alarm for "tea time", "lunch time" and "tea time". Works well at times but occasionally it gets stuck on the alarm not resetting, other times it does not trigger the alarm.
please help I am new to Arduino and all of this.
here is the code:
#include <LiquidCrystal_I2C.h>
#include <ThreeWire.h>
#include <RtcDS1302.h>

ThreeWire myWire(4,5,2); // IO, SCLK, CE
RtcDS1302<ThreeWire> Rtc(myWire);
LiquidCrystal_I2C lcd(0x3f,16,2);
int Relay = 7;

void setup ()
{
    //RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);
    //Rtc.SetDateTime(compiled);
    Serial.begin(9600);
    lcd.init();
    lcd.backlight();
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("  ClearChoice");
    lcd.setCursor(0,1);
    lcd.print(" Installations");
    delay(5000);
    lcd.clear();
    pinMode(7, OUTPUT);
    pinMode(8, INPUT);
    digitalWrite(Relay, LOW);
}
void Alarm()
{
    digitalWrite(Relay, HIGH);

    delay(3000);

    digitalWrite(Relay, LOW);
}

void AlarmActive()
{
    RtcDateTime now = Rtc.GetDateTime();
    int MySec = now.Second();
    int MyMin=now.Minute();
    int MyHour=now.Hour();
    int MyDay=now.DayOfWeek();

    if(MyHour==10 && MyMin==00 && MySec==00 && MyDay<=5)
    {
        Alarm();
    }
    if(MyHour==10 && MyMin==15 && MySec==00 && MyDay<=5)
    {
        Alarm();
    }
    if(MyHour==12 && MyMin==00 && MySec==00 && MyDay<=5)
    {
        Alarm();
    }
    if(MyHour==12 && MyMin==30 && MySec==00 && MyDay<=5)
    {
        Alarm();
    }
    if(MyHour==15 && MyMin==00 && MySec==00 && MyDay<=5)
    {
        Alarm();
    }
    if(MyHour==15 && MyMin==15 && MySec==00 && MyDay<=5)
    {
        Alarm();
    }
}

void Clock()
{
    RtcDateTime now = Rtc.GetDateTime();
    int dayOfWeek = now.DayOfWeek();
    String days[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

    lcd.setCursor(0,0);
    char buffer[3];
    lcd.print("Date: ");
    lcd.print(now.Day());
    lcd.print("/");
    lcd.print(now.Month());
    lcd.print("/");
    lcd.print(now.Year());
    lcd.setCursor(0,1);
    lcd.print("Time: ");
    sprintf(buffer, "%02d", now.Hour());
    lcd.print(buffer);
    lcd.print(":");
    sprintf(buffer, "%02d", now.Minute());
    lcd.print(buffer);
    lcd.print(":");
    sprintf(buffer, "%02d", now.Second());
    lcd.print(buffer);
    lcd.setCursor(0,1);

    Serial.print("Time: ");
    Serial.print(now.Hour());
    Serial.print(":");
    Serial.print(now.Minute());
    Serial.print(":");
    Serial.print(now.Second());
    Serial.println();
    Serial.print("Date: ");
    Serial.print(now.Day());
    Serial.print("/");
    Serial.print(now.Month());
    Serial.print("/");
    Serial.print(now.Year());
    Serial.println();
    lcd.print("Time: ");
    Serial.println(days[dayOfWeek]);
    Serial.println();
    AlarmActive();

    delay(1000);
}

void loop ()
{
   Clock();
}

Please try delaying only for like half a second instead of a full second in Clock(). Currently you are probably occasionally missing the relevant second of an alarm.

Thank you. Will give it a try.

Also, Alarm() has a 3-second delay. This can contribute to the issue you are seeing, as @chrisl mentioned. Check out an example called "blink without delay". That should give me some idea about how NOT to use delay.

Thank you.
Fahad

What do you see on the serial monitor when the program fails to work as expected?

@Fahad: You changed the code while reformatting it. Maybe you should explain to the OP that the empty else statements have no effect at all and can be removed.

forget the seconds ... trigger the alarm on day, hour, minute ... insert a 60 second delay at end of alarm() so that it triggers only once every alarm time


text:
Can't install to arduino mega 2560 using arduino-cli, but can using IDE
I have a MKS GEN L v1.0 3dprinter board that works fine uploading using the IDE. But I need to install to it using the arduino-cli.
For some reason, the command arduino-cli board list says that the board has an unknown FQBN. Which is fine, I guess. I guess I don't know how to compile & upload without the FQBN.
The options I need selected (which work in the IDE) are:

Board: Arduino/Genuino Mega or Mega 2560
Processor: ATmega2560
Programmer: AVRISP mkII

I don't understand why these options aren't clearly available in the arduino-cli.
I ran these commands: arduino-cli core install arduino:avr and arduino-cli core install arduino:megaavr
I ran  arduino-cli board list. It says /dev/ttyUSB0, serial, Serial Port (USB), "Unknown" for FQBN....
I run arduino-cli compile Marlin. It says "unknown FQBN".
So how do I install using the same parameters in the IDE?

did you install the AVR boards package in CLI? IDE has the AVR boards package bundled in the installation folder, but the CLI doesn't use it from there

I did run : arduino-cli core install arduino:avr and arduino-cli core install arduino:megaavr... Is there something else I should do?

and what CLI command do you run at what is the output exactly? (add it to the question)

Ok I added it...

I would guess, that the arduino-cli doesn't recognize your boards FQBN, since it is not a genuine Arduino board. My Arduino Nano clones (with the CH340 USB-Serial-chip) aren't recognized as Arduino Nanos either. For me that's the same with the Arduino IDE.
Though, since you already know what board you have, you can find the FQBN yourself by looking through the list in the output of
arduino-cli board listall

or if you want to narrow the list down a bit:
arduino-cli board listall avr

There you will find the line with the Megas FQBN:
Arduino Mega or Mega 2560        arduino:avr:mega

Then you need to know, which Serial interface/COM port your Arduino has. This is done analog to the Arduino IDE: Check the list of connected boards via
arduino-cli board list

If you cannot identify it directly from the list, you might want to disconnect and connect it again, to see, what entry in this list reappears again.
Then compile and upload can be done like this (be sure to input your own COM port/Serial interface, if it differs from this):
arduino-cli compile --fqbn arduino:avr:mega
arduino-cli upload --fqbn arduino:avr:mega --port /dev/ttyUSB0

while being in the sketch folder.

Thank you... I have been searching for an answer to this for years... It is not clear the "FQBN" would be the same as that sub menu in the IDE


text:
Communicating via Serial Monitor but not able to get comms via Terminal outside of Arduino IDE
I am using Arduino Nano 33 BLE. I am able to communicate via Serial Monitor within Arduino IDE, but not able to communicate via Terminal, outside of Arduino IDE. I am using Teraterm, do I need to do any additional setting?
No error messages. It does work on the Serial Monitor of Arduino IDE at 115200 baud rate with the default settings ("SERIAL_8N1"). The serial port Setup on Teraterm is the following:
Speed: 115200 Data: 8 bit Parity: none. Stop bits: 1 bit. Flow control: none
The thing is that it does what it has to do writing one command that is one letter, I mean, in my Arduino sketch if you write "$" on Serial Monitor it does a reset, and through Teraterm if you write "$" It does a reset as well,.. but on Teraterm if I type a command longer than one letter It doesn't even show what I type on Teraterm and doesn't recognize.

do you get some error message? (add it to the question)

What are the serial port settings on the Arduino sketch? On the serial monitor? On Teraterm?

not able to communicate is a similar description to not feeling well ... it provides no useful information about the problem

Are you saying that you don't see what you type? That would be the default for many terminal programs. You need to turn on "local echo" to see what you are typing.

Got a sketch you can show us?

In TeraTerm the local echo is off by default. So you won't see anything while you type something. Here are the settings:

First connect to the serial port.

Then go to Setup->Terminal.

Based on your code select what you are expecting to receive at the end of a transmission from Arduino and what you need to send at the end of your command to Arduino to tell it is the end of the command. Usually, it can be Carriage Return (CR: 0x0D) or Line Feed (LF: 0x13), or both.

Also, check Local echo. That will print whatever you are typing on the terminal.

Then Setup->Serial port....

And configure your serial port accordingly.

What you call a “terminal” is actually a terminal emulator, i.e. a
computer program intended to emulate an old school computer
terminal. CRT-based terminals were in turn designed to emulate still
older “hard-copy terminals”, like the venerable ASR-33. A hard-copy
terminal (also called “teletypewriter”) is basically a typewriter fitted
with a serial port. Whatever you type is sent along the wire. Keystrokes
are sent immediately: these devices did not have memory (which was
hugely expensive at the time) and could not buffer your input. The
Teraterm program you are using inherits from this history: like a
teletypewriter, it sends your keystrokes immediately.
The Arduino serial monitor, in contrast, does not transmit as you type.
Instead, you type a line of text and, when you hit “Send”, the whole
line is sent at once, at the full speed of the serial port.
This makes a significant difference in terms of transmission timing.
With Teraterm, the Arduino program sees long pauses (which depend on
your typing speed) between successive characters. With the serial
monitor, successive characters are spaced by roughly 87 µs. If your
Arduino code properly buffers its input until it receives an
end-of-line, then it will work equally well with Teraterm and with the
serial monitor. If, on the other hand, your code gets impatient and
times out while you are typing, then it will not get multi-character
commands you type on Teraterm.
Note that, if you want your Arduino program to be friendly to terminal
users, you may want to echo the characters you receive, as local echo on
the terminal is usually not on by default. More importantly, you may
want to handle the backspace key (which can send either ASCII BS or
ASCII DEL) to let the user fix their typos. See how this is done in this
very simple command-line interpreter.


text:
Send large file over BLE with ESP32 Wrover B
I have been able to get a large file to be sent in packages over BLE to a characteristic on my ESP32-Wrover-B module (yay!). However, these files can be large (+300kb) so I need to repackage them after all the file data has been sent (in chunks), to then be stored/written in LittleFS.
I have PSRAM with my module that will allow me to store in a larger space directly, however, from the tutorials I have read, you cannot create a global char* variable for PSRAM.
What would be my best approach here? My basic logic here is to repackage all the chunks that are received via BLE into a char* (or string). Once all data received,  save it as a file in LittleFS.

Use a buffer array to receive the chunk then write to the file once the chunk is received completely.
This is what I utilized for transferring the OTA update file (~1.2MB) over BLE ESP32_BLE_OTA_Arduino


text:
Errors when trying to connect esp8266 to firebase
hello guys i was trying to connect my project to firebase but got this erorrs:
d:\Kuliah\Mata Kuliah\Internet of Things\Arduino\libraries\FirebaseArduino\src\Firebase.cpp: In member function 'int FirebaseRequest::sendRequest(const string&, const string&, char*, const string&, const string&)':
d:\Kuliah\Mata Kuliah\Internet of Things\Arduino\libraries\FirebaseArduino\src\Firebase.cpp:78:1: error: no return statement in function returning non-void [-Werror=return-type]
   78 | }
      | ^
d:\Kuliah\Mata Kuliah\Internet of Things\Arduino\libraries\FirebaseArduino\src\Firebase.cpp: In member function 'void FirebaseStream::startStreaming(const string&, const string&, const string&)':
d:\Kuliah\Mata Kuliah\Internet of Things\Arduino\libraries\FirebaseArduino\src\Firebase.cpp:91:16: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
   91 |   analyzeError("STREAM", status, path_with_auth);
      |                ^~~~~~~~
d:\Kuliah\Mata Kuliah\Internet of Things\Arduino\libraries\FirebaseArduino\src\FirebaseHttpClient_Esp8266.cpp: In member function 'virtual void FirebaseHttpClientEsp8266::begin(const string&)':
d:\Kuliah\Mata Kuliah\Internet of Things\Arduino\libraries\FirebaseArduino\src\FirebaseHttpClient_Esp8266.cpp:47:50: error: no matching function for call to 'begin(const char*, const char [60])'
   47 |     http_.begin(url.c_str(), kFirebaseFingerprint);
      |                                                  ^
In file included from d:\Kuliah\Mata Kuliah\Internet of Things\Arduino\libraries\FirebaseArduino\src\FirebaseHttpClient_Esp8266.cpp:9:
C:\Users\NyK\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\libraries\ESP8266HTTPClient\src/ESP8266HTTPClient.h:166:10: note: candidate: 'bool HTTPClient::begin(String, uint16_t, String)' (near match)
  166 |     bool begin(String host, uint16_t port, String uri = "/")  __attribute__ ((error("obsolete API, use ::begin(WiFiClient, host, port, uri)")));
      |          ^~~~~
C:\Users\NyK\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\libraries\ESP8266HTTPClient\src/ESP8266HTTPClient.h:166:10: note:   conversion of argument 2 would be ill-formed:
d:\Kuliah\Mata Kuliah\Internet of Things\Arduino\libraries\FirebaseArduino\src\FirebaseHttpClient_Esp8266.cpp:47:30: error: invalid conversion from 'const char*' to 'uint16_t' {aka 'short unsigned int'} [-fpermissive]
   47 |     http_.begin(url.c_str(), kFirebaseFingerprint);
      |                              ^~~~~~~~~~~~~~~~~~~~
      |                              |
      |                              const char*
In file included from d:\Kuliah\Mata Kuliah\Internet of Things\Arduino\libraries\FirebaseArduino\src\FirebaseHttpClient_Esp8266.cpp:9:
C:\Users\NyK\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\libraries\ESP8266HTTPClient\src/ESP8266HTTPClient.h:167:10: note: candidate: 'bool HTTPClient::begin(String, const uint8_t*)' (near match)
  167 |     bool begin(String url, const uint8_t httpsFingerprint[20])  __attribute__ ((error("obsolete API, use ::begin(WiFiClientSecure, ...)")));
      |          ^~~~~
C:\Users\NyK\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\libraries\ESP8266HTTPClient\src/ESP8266HTTPClient.h:167:10: note:   conversion of argument 2 would be ill-formed:
d:\Kuliah\Mata Kuliah\Internet of Things\Arduino\libraries\FirebaseArduino\src\FirebaseHttpClient_Esp8266.cpp:47:30: error: invalid conversion from 'const char*' to 'const uint8_t*' {aka 'const unsigned char*'} [-fpermissive]
   47 |     http_.begin(url.c_str(), kFirebaseFingerprint);
      |                              ^~~~~~~~~~~~~~~~~~~~
      |                              |
      |                              const char*
d:\Kuliah\Mata Kuliah\Internet of Things\Arduino\libraries\FirebaseArduino\src\FirebaseHttpClient_Esp8266.cpp: In member function 'virtual void FirebaseHttpClientEsp8266::begin(const string&, const string&)':
d:\Kuliah\Mata Kuliah\Internet of Things\Arduino\libraries\FirebaseArduino\src\FirebaseHttpClient_Esp8266.cpp:51:60: error: invalid conversion from 'const char*' to 'const uint8_t*' {aka 'const unsigned char*'} [-fpermissive]
   51 |     http_.begin(host.c_str(), kFirebasePort, path.c_str(), kFirebaseFingerprint);
      |                                                            ^~~~~~~~~~~~~~~~~~~~
      |                                                            |
      |                                                            const char*
In file included from d:\Kuliah\Mata Kuliah\Internet of Things\Arduino\libraries\FirebaseArduino\src\FirebaseHttpClient_Esp8266.cpp:9:
C:\Users\NyK\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\libraries\ESP8266HTTPClient\src/ESP8266HTTPClient.h:168:70: note:   initializing argument 4 of 'bool HTTPClient::begin(String, uint16_t, String, const uint8_t*)'
  168 |     bool begin(String host, uint16_t port, String uri, const uint8_t httpsFingerprint[20])  __attribute__ ((error("obsolete API, use ::begin(WiFiClientSecure, ...)")));
      |                                                        ~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~
cc1plus.exe: some warnings being treated as errors

exit status 1

Compilation error: exit status 1

i've installed the latest version of esp8266 and "Firebase Arduino Client Library for ESP8266 By Mobitz" but the error still occured. please help
here's my full code:

#include <ESP8266WiFi.h>
#include <SoftwareSerial.h>
#include <FirebaseArduino.h>
#include <ArduinoJson.h>
#include <ESP8266HTTPClient.h>
#include<DHT.h>

#define FIREBASE_HOST "*****firebaseio.com"
#define FIREBASE_AUTH "*****UKBpSMo07nUT8ZWYS9"

#define WIFI_SSID "******"
#define WIFI_PASSWORD "******"

#define DHTPIN D5
#define DHTTYPE DHT11

DHT dht(DHTPIN, DHTTYPE);

bool light;
bool fan;

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

void setup() {
  pinMode(D1, OUTPUT);
  Serial.begin(115200);
  delay(500);
  WiFi.begin(WIFI_SSID,WIFI_PASSWORD);
  Serial.println("Connecting..");

  while (WiFi.status() != WL_CONNECTED){
    Serial.print(".");
    delay(500);
  }
  Serial.println();
  Serial.print("Connected");
  Serial.println(WiFi.localIP());

  Firebase.begin(FIREBASE_HOST,FIREBASE_AUTH);
  dht.begin();

  delay(2000);
  // put your setup code here, to run once:
}

void readDatas(){
  float h=dht.readHumidity();
  float t=dht.readTemperature();

  Firebase.setFloat("Data/Temperature:",t);
  Firebase.setFloat("Data/Humidity:",h);
}

void loop() {
  light = Firebase.getBool("LightStates/switch");
  Serial.println(light);
  if(light==true){
    digitalWrite(D6, HIGH);
  }
  if(light==false){
    digitalWrite(D6, LOW);
  }

  fan = Firebase.getBool("FanStates/switch");
  Serial.println(fan);
  if(fan==true){
    digitalWrite(D7, HIGH);
  }
  if(fan==false){
    digitalWrite(D7, LOW);
  }

  unsigned long currentMillis = millis();
  if(currentMillis-previousMillis>=interval){
    readDatas();
    previousMillis=currentMillis;
  }

}

The library "Firebase Arduino Client Library for ESP8266 By Mobitz"  doesn't have FirebaseArduino.h. You perhaps installed the wrong library?

I also installed the firebase master but still didn't work

I don't know which library is "firebase master". But I think you should select one library and stick to it. I believe "Firebase Arduino Client Library for ESP8266 By Mobitz" is pretty well documented. If you decide to use that, first check their examples and make them work. And then start injecting your code into their examples. Wherever you copied your code from I believe it is using an old library that is not maintained anymore and not available in the Arduino Library Manager.

fixed by downgrading my esp8266 version to 2.7