text:
Is std::string (and ephemeral memory allocation in general) safe to use for ESP32 Arduino?
I know that with 8-bit AVR Arduinos, std::string is widely regarded as fundamentally unsafe due to problems with heap-fragmentation (partly due to limited ram, and partly because the WAY the underlying Arduino/AVR library manages memory is more simplistic than something constantly allocating and releasing a lot of ephemeral allocations needs to be).
Does the same caution apply to ESP32 (when used with Arduino framework), or does its underlying memory-management scheme (presumably based upon esp-idf) on a module with ~468k of RAM do a sufficiently better job of minimizing fragmentation and memory leaks to make std::string (and other similar classes) safe to use without having to constantly obsess about the problem and bend over backwards to avoid ephemeral memory allocations?
I'm particularly worried that the various libraries for making http requests (potentially involving the creation and destruction of multiple String objects for every request and response) might be more indifferent to the problem than they really ought to be.
I know there are a few Arduino libraries floating around that basically allocate one single big chunk of memory for a reusable String-like object (and additional space to give it "working room" to do things like regular expressions, substring replacements, etc), but it looks like the popular ESP32 libraries for making http requests just create and destroy new String objects for every request and act like it's totally fine. Am I being paranoid, or is ephemeral memory allocation still a real problem, even on platforms like ESP32?
By the same token... is there some way (on an ESP32 Arduino program) to periodically ask the library to analyze the current memory situation, and deliberately initiate a software-reboot (and re-initialization) if the memory appears to be getting overly fragmented (vs waiting for a slow memory leak to just fester until a memory allocation fails and the whole program crashes uncontrollably)?

The problem with randomly allocating and deallocating memory in embedded systems (ES) is that most are meant to be able to run error free, essentially forever. Since memory space is finite, an ES that employs the technique don't meet that constraint.
To the question in your last paragraph, apparently you are considering a system that can tolerate occasional resets with the consequent loss of context. In that case, perhaps resetting anytime an allocation fails would be acceptable. You'd want to vet each request especially carefully to to ensure it could usually be expected to succeed (define "usually"!), to avoid the large overhead of too-frequent resets or worse, a continuous reset loop resulting from an impossible-to-fill request.
Consider the difference between a human-driven question-and-answer system on one hand, and an implanted cardiac pacemaker or an jet fighter auto-landing system for night carrier-landings. An occasional timing hiccup might be annoy me in the Q&A system (if I can even notice it), but in either of the other two, it might spoil someone's whole day. :-(

The system could definitely tolerate periodic reboots without incident, as long as they happen when I decide they're necessary (say, upon checking as the final act in loop(), and triggering a reboot if the largest chunk of free memory is smaller than 100k, or less than 200k remains available). The general assumption is that it wouldn't happen very often... but from what I've seen, Arduino-based stuff in general that uses wifi for almost anything tends to reliably crap out after a few weeks unless it gets periodically rebooted... so I'm just starting from that assumption and embracing it :)

For what it's worth, I have a fan controller on an ATmega328p -> ESP-01 (AT firmware) that runs continuously until a power glitch or some other event takes down my WiFi network. If it were more critical to keep the controller running, it could have been made to "don't care" if the WiFi is down and just keep going without it. The WiFi is only to allow me to view what the controller is doing and isn't a necessary function.

If this is any interest to you, I did a web server library that doesn't use String class at all.
It decodes incoming HTTP requests an item at a time, passing the results to a callback routine.
That way it doesn't even have to hold the whole HTTP request in memory, it decodes the individual parameters "on the fly" using a state machine.
Since there is no dynamic memory allocation you should, in theory, be able to run indefinitely.
My library is at https://github.com/nickgammon/HTTPserver
Having said that, and to answer your actual question ...

Dynamic memory allocation doesn't have to be bad. In particular, if the amounts of memory being allocated are always the same (for example, your input to your server is predictable) then it shouldn't run out of memory. The allocator will just keep serving up the same bit of memory you used last time.
What can be particularly bad is this sort of stuff:
String buf = "";
while (Serial.available ())
  {
  buf += Serial.read ();  // append one byte
  }

That sort of code is likely to cause heap fragmentation because it keeps allocating larger and larger chunks. Whether the library you mention does that, I don't know.

Note, it isn't totally clear from your question if you are writing an HTTP client or server. If you are writing a client then my library won't be any help, but my remarks above should still apply.

Thanks, but my program is purely a http client. The main thing I'm wringing my hands over is that the circuit's primary mission is, "monitor moisture sensors, and trigger the piezo buzzer if water is detected". I have it sending BLE advertisements for my debugging convenience, and making occasional http POST requests to log the data & make it available to me from outside the house... but my big concern is making sure that failure with Bluetooth or WiFi won't hang or crash the whole program and derail it from its primary mission (of watching the sensors & sounding the piezo if necessary).

(continued)... I think I might need to eventually implement something involving watchdog timers... but I'm not sure whether ESP32 even has AVR-like watchdog timers capable of automatically rebooting the chip if the software fails to "check in" within some specified time limit. In any case, that would be a topic for another question ;-)

According to a Google search, it has in fact got watchdog timers.


text:
State machine doesn't function
My goal is to make a logic controller for a cassette tape mechanism, right now I'm simply trying to get the mechanism to engage and disengage the pinchroller arm which is motorized, spin the reels/capstan to advance the tape for playback; and stop the process by stopping the capstan motor, and retracting the pinchroller arm.
Currently this code doesn't respond to any of the button inputs, and I'm unsure as to why that is. I have another program that allows manual control of the motors, and that works fine, this however does not.
Can someone point out/correct what is the mistake? Because I can't seem to find what is wrong. Thank you in advance!
Here is my current full code:
const int motor1Pin = 5; //If motor1 is HIGH and motor2 is LOW,  the motor will spin one way, if motor1 is LOW and motor2 HIGH then the motor will spin in the opposite direction.
const int motor2Pin = 4;
const int motor3Pin = 2;
const int motor4Pin = 1;
const int enablePin = 6; //turns pinch roller arm motor on or off
const int enablePin2 = 3; //turns capstan motor on or off
const int limitswitch1Pin = 7; // end of top travel limit switch
const int limitswitch2Pin = 9; // end of bottom travel limit switch
const int cyclePin = 8; //switch that cycles the pinch roller arm depending on limit switches
const int reversePin = 10;
const int forwardPin = 11;
const int stopPin = 12;

int state;
int buttonState;
int limit1State;
int lastlimit1State;
int limit2State;
int lastlimit2State;
int reverseState;
int forwardState;
int stopState;

enum State_enum {STOP,PLAY};

bool enableState = false;
bool enable2State = false;

void setup() {

  pinMode(motor1Pin, OUTPUT);
  pinMode(motor2Pin, OUTPUT);
  pinMode(motor3Pin, OUTPUT);
  pinMode(motor4Pin, OUTPUT);
  pinMode(enablePin, OUTPUT);
  pinMode(enablePin2, OUTPUT);
  pinMode(reversePin, INPUT_PULLUP);
  pinMode(forwardPin, INPUT_PULLUP);
  pinMode(stopPin, INPUT_PULLUP);
  pinMode(limitswitch1Pin, INPUT_PULLUP);
  pinMode(limitswitch2Pin, INPUT_PULLUP);
  pinMode(cyclePin, INPUT_PULLUP);
  pinMode(A0, INPUT);

  buttonState = digitalRead(cyclePin);
  limit1State = digitalRead(limitswitch1Pin);
  limit2State = digitalRead(limitswitch2Pin);
  reverseState = digitalRead(reversePin);
  forwardState = digitalRead(forwardPin);
  stopState = digitalRead(stopPin);

}

void loop() {

  if (buttonState == LOW) int state = PLAY;
  if (stopState == LOW) int state = STOP;

  switch (state) {
  case PLAY: //Plays the cassette
    if (stopState == LOW) {
      state = STOP;
    }
    if (limit1State == LOW) { //running the pinchroller arm clockwise from the top to bottom

      digitalWrite(motor1Pin, HIGH); // set leg 1 of the pinchroller motor H-bridge high
      digitalWrite(motor2Pin, LOW); // set leg 2 of the pinchrooler motor H-bridge low
      analogWrite(enablePin, 176); //set pinchroller motor speed

    } else if (limit2State == LOW) { //pinchroller arm is fully down (at bottom)
      digitalWrite(enablePin, LOW); //disable pinch roller motor
      digitalWrite(motor3Pin, LOW); // set leg 3 of the capstan motor H-bridge low
      digitalWrite(motor4Pin, HIGH); // set leg 4 of the capstan motor H-bridge high
      analogWrite(enablePin2, 200); // set capstan motor speed
      digitalWrite(enable2State, true);
    }
    break;

  case STOP: //Stops the cassette
    if (enable2State == true && limit2State == LOW) {
      digitalWrite(enablePin2, LOW);
      digitalWrite(enable2State, false);

    } else if (enable2State == false && limit2State == LOW) {
      //running the pinchroller arm counter-clockwise from the bottom to top

      digitalWrite(motor1Pin, LOW); // set leg 1 of the motor H-bridge high
      digitalWrite(motor2Pin, HIGH); // set leg 2 of the motor H-bridge low
      analogWrite(enablePin, 176); //set pincroller motor speed

      if (limit1State == LOW) {
        digitalWrite(enablePin, LOW);
      }
    }
    break;

  }
}

I don't know enough about how tapes work to comment on the sense of what you're doing, but some problems with the code:
You are reading the input and setting buttonstate once only in setup(). You need to read it repeatedly, by putting it in loop().
You also have three variables called state: one global which is never set, and two with very restricted scope which are set but never used - they go out of scope immediately. Remove the ints where you set state in your loop().
This part is useless because you've already done it just above, but probably not hurting anything:
if (stopState == LOW) {
    state = STOP;
}

That's as far as I got. If that doesn't fix it, consider adding trace: you'd have found these two problems pretty quickly if you'd printed out the variables to check your assumptions.

You are reading the input and setting buttonstate once only in setup() - the same applies to all the states.

The OP is testing if  enable2State is true, but nothing in the code changes enable2State.

source: Stack Exchange

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

sort: votes


text:
State machine sketch to drive a DC motor with limit switches
I have a DC motor that will need to use two limit switches to detect end of travel in two directions.
I've read that coding a state machine to do this task is the best method, however I have no idea where to even begin.
Below you'll find a fritzing sketch of my experimental configuration for the code once implemented, and a flow chart.

You have created a flow chart.  When discussing state machines it is better to use a state diagram.

In this state diagram of a turnstile (from the state machine wikipedia page linked to above) it is observed that the nodes (bubbles) contain the state of the turnstile and on the edges (arrows) is written the condition required to travel in the direction of the arrow to a new state.
For the question asked here, at least 2 nodes are needed to state the direction of the motor.  The edges likely will state which arrow is to be used to travel to a new state based on which switch is open or closed.  Later, consider adding a new state to stop the motor once an end switch is closed. (Hint: Likely, you will need 2 stop nodes.  One for each end-stop switch.  The reason being you will need to know which direction the motor is to turn when restarted.)
For certain cases, adding a momentary contact switch is complex due to the need to mitigate the contact bounce.  This is true when the meaning of activating the switch changes.  The end-stop switch meaning does not change so there is no need to mitigate the contact bounce or "debounce" the end-stop switches.  However, it is assumed the "Cycle Switch" can start the motor spinning in different directions depending on the history of the motor movement.  Therefor the "Cycle Switch" can benefit from a 4 node state machine where there is clearly nodes which output switch-closed and switch-open.  But to get to either of these 2 nodes there needs to be 2 other nodes where the switch "debouncing" is handled.

When handling multiple state machines in one program it is important not to block the flow.  All state machines need to be continuously checked for state chances (testing the edge conditions for traveling from the current node to a new node).
When writing for an Arduino (in C / C++), the code pattern most often used is a "case" statement (switch / case) where a variable is assigned numbers associated with different nodes.  In such a code pattern, each "case" is a node which contains the edge test(s) and can assign a new value to the variable to switch to a new node ("case") if any of the edge tests are true.
Simplifying the design:  If you do not plan on stopping the motor then you do not need to "debounce" the "Cycle Switch".
Here is why: The meaning of the "Cycle Switch" changes from push-to-start to push-to-stop should you want to stop the motor between the 2 stop-switches.  If all you need is to start the motor after either of the stop-switches are closed, then the number of times the "Cycle Switch" bounces is irrelevant as long as the bounces do not continue for longer then it takes for the motor to reach the opposite stop-switch.

Each state in the state machine should be a state in which the arduino will be for a time. Anywhere you would use a delay() or a blocking function or a busy loop will be a state.
You can also use multiple orthogonal statemachines and mix them. For example 1 to control whether the motor needs to be driven at all and one to control which direction it is driven in. That way the motor control part will look like:
if(motorDriven) {
    if(motorDirection = TOP) {
        driveMotorCW();
    } else {
        driveMotorCCW();
    }
} else {
    stopMotor();
}

Then the control of the state machine is straightforward. If limit switch is pressed change motorDirection to the opposite (and maybe stop the motor).
For timing you should keep a timestamp of the start of the interval and then test if millis() - timestamp > interval. For intervals less than a month this will work decently enough (barring drift). For intervals greater than that you should invest in a external clock.

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


text:
IR receiver receives only 0
I am trying to decode IR codes of my Samsung tv remote
But the receiver always receiving "0"
Schematics:

Code:
#include <IRremote.h>

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

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

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

Please help me to decode my IR codes

The most current version of IRremote doesn't have any arguments for the decode function. To get the result you'd use irrecv.results to get the results.

Next update with 3.1 of the library, you need to call irrecv.decodedIRData.decodedRawData to get the data. This code worked for me:
#include <IRremote.h>

int IRpin = 11;
IRrecv irrecv(IRpin);

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

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

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


text:
Arduino nano KiCad symbols
Can anyone explain me the difference between the symbols for Arduino nano in KiCad? Is there any important difference at all? All of them seem to have all basic pins.

Different boards with different footprints.

In short, there aren't any substantial differences.  But it makes sense to use the one that actually matches what you have.
My KICAD symbols are out of date, so I downloaded and unpacked the current archive for MCU Module symbols.  These things are defined in text files, so doing this allows you to employ the usual diff tools to them, if you break the parts of interest out into separate files, which is what I did to produce the below images.
Index Entries
Besides the name, they're different in what datasheet they refer to:

Definitions
In the below, on the left you'll see in dark blue background that both the Nano v2.x and v3.x are actually defined in the same file.  So, they are in fact sharing a definition; so, no differences there at all.  The original Nano boards varied in that some had ATMega168P and some had ATMega328P.  These are practically but not quite the same chip.  The significant difference is sizes of the various memories.  And they had different bootloaders.  Nothing that would make their symbols or footprints significantly different.
On the right is the Nano-Every, which is a fairly different beast from the older Nanos in that it's an ATMega4809, one of the new-series AVR parts, and different significant ways greater than just memory sizes.  But, it was designed to have the same layout as the prior Nano boards.  They even went so far as to make classes and objects to try to "emulate" the more traditional style GPIO ports of the Nano for Nano Every users.
As you can see there's really no differences besides the names of the pins and a few changes in drawn locations between the v2/v3 symbol on left and the "Every" symbol on the right.  Some of the pin names are different, but it's the pin numbers that matter when mating it to a footprint in Kicad, and those are the same between the two.
For whatever reason pin number 29 changed from W (in 2/3) to N (in "Every"), which according to their documentation is a change from power input to not connected.  I suppose this might make a difference between whether or not you need to add a PWR_FLAG symbol somewhere in your design to satisfy electrical rules check (ERC).  In the "Every", for whatever reason when they (slightly) rearranged the pins locations in the symbol, they stuck pin number 29 right on top of pin 4.  So, if you're having a hard time seeing pin 29, that (and the light gray text) are why.

Thank you for the excellent answer.

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


text:
Stable amplitude of amplified signal
Is there any circuit with opamp where can be (by arduino) set constant output amplitude which doesn't depend on input signals amplitude?

What signal? It sounds like you're asking for an AGC circuit with adjustable level.

NB: AGC = Automatic Gain Control

Yes. AGC will help me in this project. Thank you both.

Just for grins I googled "digital control AGC" and got about 5 million hits. A lot more information is needed to properly answer your question. Please define the input and output signals, level, frequency, etc. Note the rate of change will have a large effect on the AGC filters and Arduino response (partially controlled by your software) will make or break the whole design. Include a proposed schematic, not a frizzy drawing.

Just a word of advice about AGC in general.  There is almost always an issue of attack (how fast the AGC reacts to a sudden increase in signal) and release (how fast it reacts to a decrease).  In most AGC cases you will need to make compromises on these two settings to avoid poor behavior from the AGC... it's not a drop-in solution with pre-determined optimum settings for every purpose.  Depending on the program material, you can get obnoxious artifacts like breathing and pumping for speech and music.  ACG is much better at slow drifting things like signal fade.  I just want you know what you might be getting into...


text:
Controlling op amps amplification ratio by arduino
Is there any option how to control amplification ratio of operational amplifier by some logic signal which can be produced by arduino? I am talking about some clasic op amp like lm356 or ui741 in basic inverting or non-inverting circuit (i would like to use non-inverting circuit in my application). I know only about digital potentiometer like solution but i think that it isn't profesional and most eficient solution, so I want to know your opinion. Thanks for reply.

There's nothing wrong with digipots...  I made a whole mixer system using digipots and op-amps once.

not a question about Arduino

Could you provide more details on your requirements? Do you need gain adjustments in fine tuning or just large steps, like the scales of a multimeter? What are the characteristics of your input signal?

The basic principle is easy to implement.  A non-inverting configuration has a resistor Ri from the inverting input to ground, and a feedback resistor Rf from the same input to the output.  The signal is applied to the non-inverting input.  The gain is 1+Rf/Ri.  You can control the gain by changing Ri, which can be done via a CD4016 quad analog switch and 4 resistors.
HOWEVER, the Arduino is a 0-5V device.  The CD4016 can handle 15V, but to switch it the digital input must pass through half the supply.  The op-amps you mention will require bipolar supplies to handle AC signals (which I assume is what you want), so you could run them with +/-7.5V, with the CD4016 powered between them.  Then to get the Arduino 0-5V to toggle the CD4016 you'd need some level-shifting transistors to get it to +/-7.5.  The upshot is that this is surely going to be more trouble than it's worth.
However, if you are willing to drop the ancient op-amps and use a modern single-supply type (MCP6021, LT1013, etc) that runs on 0-5V, you can use input and output capacitors to convert the signal to AC, then just use the CD4016 as-is. Or JFET transistors, or even bipolars to switch the gain resistor under Arduino control if you don't need audiophile quality.


text:
Find MAC address of client connected to ESP32 Bluetooth SPP via esp32-Arduino Bluetooth serial library
Let's suppose I'm using Espressif's Arduino-esp32 Bluetooth Serial library with code similar to the following:
#include "BluetoothSerial.h"

// snip

BluetoothSerial bts;
bool firstTime = true;

void setup() {
  bts.begin("bts");
}

void loop() {
  if (firstTime && bts.hasClient()) {
    // somehow get the MAC address of the client that paired & opened a connection
    firstTime = false;
  }
}

First, I ran the above code and paired a MacBook Pro to the ESP32.
I then opened a terminal window & ran system_profiler SPBluetoothDataType.
Among other things, it gave me:

the 6-byte MAC address of the laptop's Bluetooth controller

the 6-byte MAC address of the connected ESP32

I originally thought the following (executed on the ESP32, in loop()) would fetch the MAC address of the client connected to the ESP32:
uint8_t[6] mac;
bts.getBtAddress(mac);

But when I printed it as hex, it matched the MAC address the MacBook said belonged to the ESP32.
Likewise, I was originally under the impression that ESP.getEfuseMac() would return the base MAC address from which the ESP32's Ethernet, WiFi, and Bluetooth MAC addresses are all derived, but it returned a value that looks nothing at all like either one of the MAC addresses printed by system_profiler.
What do I need to do to get the MAC address of the connected Bluetooth SPP client that's the reason the call to bts.hasClient() is returning true?


text:
Keypad library isn't working or I am wrong somewhere
I am using PICSimLab to simulate a keypad. The configuration of the keypad is as shown in the picture:

and the code is:
#include <LiquidCrystal.h>
#include <Key.h>
#include <Keypad.h>

const byte rows = 4; // 4 rows
const byte columns = 3; // 3 columns
char keys[rows][columns] = {
  {'1','2','3'},
  {'4','5','6'},
  {'7','8','9'},
  {'*','0','#'}
}; // keymap

byte rowPins[rows] = {3, 2, 1, 0};
byte columnPins[columns] = {6, 5, 4}; // set up connection pins

Keypad kp = Keypad(makeKeymap(keys), rowPins, columnPins, rows, columns); // set up keypad

const int d4 = 7, d5 = 8, d6 = 9, d7 = 10, en = 11, rs = 12; // set up LCD pins
LiquidCrystal myLcd(rs, en, d4, d5, d6, d7); // set up LCD

void setup() {
  myLcd.begin(16,2);
  myLcd.print("Last name:Smith");
  myLcd.clear();
  myLcd.print("AM:1396");
  myLcd.setCursor(0,1);
  myLcd.print("ENTER VOL:");
}

void insertVol() {
  int i = 0;
  while (i < 4) {
    char key = kp.getKey();
    while(key) {
      myLcd.setCursor(i+11,1);
      myLcd.print(key);
    }
    i++;
  }
}

void loop() {
}

The purpose is to display some lines on the LCD, then type in a 4-digit password and display each digit of the password on the LCD crystal.
I get this picture which is correct:

But when I am pressing any button of the keyboard it isn't shown on the screen. I want to comment something else the length of the string "ENTER VOL" is 10 characters so we start at the position 11,1 of the LCD screen when printing out the password.
I have tried connecting L1 -> 0 , L2 -> 1 , L3 -> 2 , L3 -> 3 and C1 -> 4 , C2 -> 5 , C3 -> 6 in case it mattered, but still nothing. Is the library broken or where am I wrong? I had tried using the Keypad before this project and I had run into the same issues. Help appreciated.

how did you solve the problem before?

I didnt in fact it is a obstacle i cant get past so im asking if someone here knows about this.

Your function loop() is empty. Add these two lines to it:
insertVol();
delay(500);

in order to invoke function insertVol()


text:
What is the purpose of putting a data type in brackets before a calculation?
sorry for the nooby question but I can't seem to find the answer to this anywhere, probably because I'm unsure what to search for with this problem!
I'm just wondering what the reason is for including a data type in brackets before a calculation takes place? In the code below, all the variables have already been declared at the top of the program, so I'm unsure what the reason / effect of including the (float) has. acc_y and angle_pitch_acc have been declared as floats and acc_total_vector has been declared as long
angle_pitch_acc = asin((float)acc_y/acc_total_vector)* 57.296;

Thanks!

It's called casting. It changes the data type temporarily. In this instance it's being used to change an integer type into a floating point type, which means that the whole calculation is done using floating point mathematics. However acc_y is supposedly already a float, but maybe it wasn't at the time the author wrote that line. Maybe things, as they often do in a program, evolved. Only the author knows.

The OP wrote, that acc_y is declared as float. So the calculation would already be a floating point one, I think

@chrisl I stopped reading at "I wonder..."

Ok thanks, that makes sense.


text:
Machine learning on Arduino Nano RP2040
I am trying to use the Arduino Nano RP2040 to recognize gestures using an IMU. This board has the possibility of machine learning core features provided by the LSM6DSOX.
I tested the example provided by the manufacturer and everything works fine. I now want to create a new ML model to recognize custom gestures.
I found this STM tutorial, which is very helpful, but I can't find the code presented at 5:48, to record the movements.
Does anyone know where I can find all the code or how I should do it?

I answer the question myself, for those who have the same problem as me.
Source code
#include "PluggableUSBMSD.h"
#include "FlashIAPBlockDevice.h"
#include "WiFiNINA.h"
#include "LSM6DSOXSensor.h"

#define INT_1 INT_IMU
#define SENSOR_ODR 104.0f // In Hertz
#define ACC_FS 2 // In g
#define GYR_FS 2000 // In dps
#define MEASUREMENT_TIME_INTERVAL (1000.0f/SENSOR_ODR) // In ms
#define FIFO_SAMPLE_THRESHOLD 199
#define FLASH_BUFF_LEN 8192

typedef enum {
  DATA_STORAGE_STATE,
  DATA_LOGGER_IDLE_STATE,
  DATA_LOGGER_RUNNING_STATE
} demo_state_e;

volatile demo_state_e demo_state = DATA_STORAGE_STATE;
volatile int mems_event = 0;
uint32_t file_count = 0;
unsigned long timestamp_count = 0;
bool acc_available = false;
bool gyr_available = false;
int32_t acc_value[3];
int32_t gyr_value[3];
char buff[FLASH_BUFF_LEN];
uint32_t pos = 0;

static FlashIAPBlockDevice bd(XIP_BASE + 0x100000, 0x100000);

LSM6DSOXSensor AccGyr(&Wire, LSM6DSOX_I2C_ADD_L);

USBMSD MassStorage(&bd);

rtos::Thread acquisition_th;

FILE *f = nullptr;

void INT1Event_cb()
{
  mems_event = 1;
}

void USBMSD::begin()
{
  int err = getFileSystem().mount(&bd);
  if (err) {
    err = getFileSystem().reformat(&bd);
  }
}

mbed::FATFileSystem &USBMSD::getFileSystem()
{
  static mbed::FATFileSystem fs("fs");
  return fs;
}

void led_green_thd()
{
  while (1) {
    if (demo_state == DATA_LOGGER_RUNNING_STATE) {
      digitalWrite(LEDG, HIGH);
      delay(100);
      digitalWrite(LEDG, LOW);
      delay(100);
    }
  }
}

void Read_FIFO_Data(uint16_t samples_to_read)
{
  uint16_t i;

  for (i = 0; i < samples_to_read; i++) {
    uint8_t tag;
    // Check the FIFO tag
    AccGyr.Get_FIFO_Tag(&tag);
    switch (tag) {
      // If we have a gyro tag, read the gyro data
      case LSM6DSOX_GYRO_NC_TAG: {
          AccGyr.Get_FIFO_G_Axes(gyr_value);
          gyr_available = true;
          break;
        }
      // If we have an acc tag, read the acc data
      case LSM6DSOX_XL_NC_TAG: {
          AccGyr.Get_FIFO_X_Axes(acc_value);
          acc_available = true;
          break;
        }
      // We can discard other tags
      default: {
          break;
        }
    }
    // If we have the measurements of both acc and gyro, we can store them with timestamp
    if (acc_available && gyr_available) {
      int num_bytes;
      num_bytes = snprintf(&buff[pos], (FLASH_BUFF_LEN - pos), "%lu %d %d %d %d %d %d\n", (unsigned long)((float)timestamp_count * MEASUREMENT_TIME_INTERVAL), (int)acc_value[0], (int)acc_value[1], (int)acc_value[2], (int)gyr_value[0], (int)gyr_value[1], (int)gyr_value[2]);
      pos += num_bytes;
      timestamp_count++;
      acc_available = false;
      gyr_available = false;
    }
  }
  // We can add the termination character to the string, so we are ready to save it in flash
  buff[pos] = '\0';
  pos = 0;
}

void setup()
{
  Serial.begin(115200);
  MassStorage.begin();
  pinMode(LEDB, OUTPUT);
  pinMode(LEDG, OUTPUT);
  digitalWrite(LEDB, LOW);
  digitalWrite(LEDG, LOW);

  // Initialize I2C bus.
  Wire.begin();
  Wire.setClock(400000);

  //Interrupts.
  attachInterrupt(INT_1, INT1Event_cb, RISING);

  // Initialize IMU.
  AccGyr.begin();
  AccGyr.Enable_X();
  AccGyr.Enable_G();
  // Configure ODR and FS of the acc and gyro
  AccGyr.Set_X_ODR(SENSOR_ODR);
  AccGyr.Set_X_FS(ACC_FS);
  AccGyr.Set_G_ODR(SENSOR_ODR);
  AccGyr.Set_G_FS(GYR_FS);
  // Enable the Double Tap event
  AccGyr.Enable_Double_Tap_Detection(LSM6DSOX_INT1_PIN);
  // Configure FIFO BDR for acc and gyro
  AccGyr.Set_FIFO_X_BDR(SENSOR_ODR);
  AccGyr.Set_FIFO_G_BDR(SENSOR_ODR);
  // Start Led blinking thread
  acquisition_th.start(led_green_thd);
}

void loop()
{
  if (mems_event) {
    mems_event = 0;
    LSM6DSOX_Event_Status_t status;
    AccGyr.Get_X_Event_Status(&status);
    if (status.DoubleTapStatus) {
      switch (demo_state) {
        case DATA_STORAGE_STATE: {
            // Go to DATA_LOGGER_IDLE_STATE state
            demo_state = DATA_LOGGER_IDLE_STATE;
            digitalWrite(LEDG, HIGH);
            Serial.println("From DATA_STORAGE_STATE To DATA_LOGGER_IDLE_STATE");
            break;
          }
        case DATA_LOGGER_IDLE_STATE: {
            char filename[32];
            // Go to DATA_LOGGER_RUNNING_STATE state
            snprintf(filename, 32, "/fs/data_%lu.txt", file_count);
            Serial.print("Start writing file ");
            Serial.println(filename);
            // open a file to write some data
            // w+ means overwrite, so every time the board is rebooted the file will be overwritten
            f = fopen(filename, "w+");
            if (f != nullptr) {
              // write header
              fprintf(f, "Timestamp[ms] A_X [mg] A_Y [mg] A_Z [mg] G_X [mdps] G_Y [mdps] G_Z [mdps]\n");
              fflush(f);
              Serial.println("From DATA_LOGGER_IDLE_STATE To DATA_LOGGER_RUNNING_STATE");
              demo_state = DATA_LOGGER_RUNNING_STATE;
              digitalWrite(LEDG, LOW);
              timestamp_count = 0;
              pos = 0;
              acc_available = false;
              gyr_available = false;
              // Set FIFO in Continuous mode
              AccGyr.Set_FIFO_Mode(LSM6DSOX_STREAM_MODE);
            }
            break;
          }
        case DATA_LOGGER_RUNNING_STATE: {
            // Empty the FIFO
            uint16_t fifo_samples;
            AccGyr.Get_FIFO_Num_Samples(&fifo_samples);
            Read_FIFO_Data(fifo_samples);
            // Store the string in flash
            fprintf(f, "%s", buff);
            fflush(f);

            // Close the log file and increase the counter
            fclose(f);
            file_count++;
            // Set FIFO in Bypass mode
            AccGyr.Set_FIFO_Mode(LSM6DSOX_BYPASS_MODE);
            // Go to DATA_LOGGER_IDLE_STATE state
            demo_state = DATA_LOGGER_IDLE_STATE;
            // Wait for the led thread ends the blinking
            delay(250);
            digitalWrite(LEDG, HIGH);
            Serial.println("From DATA_LOGGER_RUNNING_STATE To DATA_LOGGER_IDLE_STATE");
            break;
          }
        default:
          Serial.println("Error! Invalid state");
      }
    }
  }

  if (demo_state == DATA_LOGGER_RUNNING_STATE) {
    uint16_t fifo_samples;

    // Check the number of samples inside FIFO
    AccGyr.Get_FIFO_Num_Samples(&fifo_samples);

    // If we reach the threshold we can empty the FIFO
    if (fifo_samples > FIFO_SAMPLE_THRESHOLD) {
      // Empty the FIFO
      Read_FIFO_Data(fifo_samples);
      // Store the string in flash
      fprintf(f, "%s", buff);
      fflush(f);
    }
  }

  if (demo_state == DATA_STORAGE_STATE && millis() > 10000) {
    // Disable the sensor and go to Mass Storage mode
    AccGyr.Disable_Double_Tap_Detection();
    AccGyr.Disable_X();
    AccGyr.Disable_G();
    while (1) {
      digitalWrite(LEDB, HIGH);
      delay(100);
      digitalWrite(LEDB, LOW);
      delay(100);
    }
  }
}


text:
Char array filling with blanks
When I run this code, my pin and pinCheck arrays are not being filled with the results of keypad.getKey(). If I print the value at each index, the result is blank. As far as I can tell, I am either not writing a char to the array, I am misreading the array when it comes time to print to the serial monitor, or .getKey() only works in the main or loop functions.
#include <Key.h>
#include <Keypad.h>

void armDisarm(void);
boolean array_cmp(char, char, int, int);

bool isArmed = 0;
char pin[3];
char pinCheck[3];
const byte ROWS = 4; // number of rows
const byte COLS = 4; // number of columns
char keys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'#','0','*','D'}
};

byte rowPins[ROWS] = {9, 8, 7, 6}; // row pinouts of the keypad R1 = D8, R2 = D7, R3 = D6, R4 = D5
byte colPins[COLS] = {5, 4, 3, 2};    // column pinouts of the keypad C1 = D4, C2 = D3, C3 = D2
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);

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

void loop()
{
  if (isArmed == 1)
  {
    Serial.println("SYSTEM ARMED! ENTER PIN TO DISARM!");
  }
  else
  {
    Serial.println("SYSTEM DISARMED! ENTER PIN TO ARM!");
  }
  armDisarm();
}

void armDisarm(void)
{
  while(true)
 {
    if (isArmed == 0)
    {
      for (int i = 0; i < 4;)
      {
        if (keypad.getKey() == NO_KEY)
        {
          continue;
        }
        pin[i] = keypad.getKey();
        Serial.println(pin[i]);
        i++;
      }
      isArmed = 1;
      return;
    }
    else if (isArmed == 1)
    {
      for (int j = 0; j < 4;)
      {
        if (keypad.getKey() == NO_KEY)
        {
          continue;
        }
        pinCheck[j] = keypad.getKey();
        Serial.println(pin[j]);
        j++;
      }
      for (int k = 0; k < 4; k++)
      {
        if(pinCheck[k] != pin[k])
        {
          isSame = 0;
          break;
        }
        else
        {
          isSame = 1;
        }
      }

      if (array_cmp(pin, pinCheck, sizeof(pin), sizeof(pinCheck)) == 1)
      {
        Serial.println("same pin"); //used for bebugging
        isArmed = 0;
        return;
      }
      else
      {
        Serial.println("INCORRECT PIN! CLAYMORE ROOMBA DEPLOYED!");
      }
    }
  }
}

boolean array_cmp(char a[sizeof(pin)], char b[sizeof(pinCheck)], int len_a, int len_b)
{
  int n;

  // if their lengths are different, return false
  if (len_a != len_b)
  {
    return false;
  }

  // test each element to be the same. if not, return false
  for (n = 0 ;n < len_a; n++)
  {
    if (a[n]!= b[n])
    {
      return false;
    }
  }

  //ok, if we have not returned yet, they are equal :)
  return true;
}

First of all, there is one essential feature of the Keypad library you
have to understand: it is non-blocking. When you call keypad.getKey(),
it returns immediately, and almost always returns NO_KEY to signal
that no key was pressed since the last time you checked. If a key was
pressed, keypad.getKey() returns that key and then, on the next
call, it again returns NO_KEY because no key was pressed since the
last time you checked.
It is important to realize that, whenever a key is pressed, that key is
returned only once by keypad.getKey(). You should manage to not miss
it!
Now consider this loop:
for (int i = 0; i < 4;)
{
    if (keypad.getKey() == NO_KEY)
    {
        continue;
    }
    pin[i] = keypad.getKey();
    Serial.println(pin[i]);
    i++;
}

This will run very fast, and almost always looping through the
continue statement. When a key is pressed, keypad.getKey() returns a
value different from NO_KEY (and this value is lost), the test
within the if is false, and the statement that follows gets executed,
namely:
    pin[i] = keypad.getKey();

But this is another call to keypad.getKey(), which returns NO_KEY,
so this is what gets saved in the array.
This is how I would write that loop:
for (int i = 0; i < 3; i++)
{
    char key = NO_KEY;
    while (key == NO_KEY)
    {
        key = keypad.getKey();
    }
    pin[i] = key;
    Serial.println(pin[i]);
}

Please note that:

The value returned by keypad.getKey() is always saved into a
variable, you do not want to loose it! When we get something other
than NO_KEY, the value previously saved into the variable is stored
in the array.

I moved the i++ where it belongs, in order to avoid that very
confusing way of controlling the loop.

The if has become a while, because we do not want to move to the
next iteration until we have actually read a valid key.

The loop does only three iterations, because this is the length of the
array pin, which we would otherwise overflow.

As an addition ToEdgar Bonets answer. I should warn you that your code keeps adding position in as each time you check array you are increasing the value of i. As a result you are filling arrays with NO_KEY.
Also having have build a security alarm on arduino before (Or shouldnt we know thats what you are doing?) I should warn you that waiting for Keyboard inputs mean that you are not checking tamper or alarm even when its armed because you are stucked inside nonloop function waiting for imput.
I have personally made input a global struct
struct foo{
   char digits[4];
   byte digit=0;
} pinCode;

You can either take instance of the struct as a parameter to your function or because its global use it internaly.
bool addDigit(char button){
  /*here deal with many potential inputs*/

you can then inside your function assign the button pressed as
pinCode.digits[pinCode.digit]=button;
pinCode.digit++;

if you are passing the instance of the struct as a pointer then it will change to
pinCode->digits[pinCode->digit]=button;
pinCode->digit++;

you can then inside this funtion test if password is confirmed (OK is pressed) and return true.
While the end of the password isn't reached, just return false.
SO within the loop you would have something like:
key = keypad.getKey();
if(key!=NO_KEY){
   if(addDigit(key)) //Here take an action based on inputs
}
// Do all the other stuff alarm has to do


text:
GY-521 output and degrees
I am trying to make an observatory through 2 GY-521 gyroscopes and using the outputs I have to make a motor move, but I have a problem.
When I move one of the two gyroscopes the outputs change, but then as soon as I leave it it returns to the initial value, the data I see via an ESP8266 on an internet site, this is the code:
#include <Wire.h>
#include "WiFiEsp.h"
// Emulate Serial1 on pins 6/7 if not present
#ifndef HAVE_HWSERIAL1
#include "SoftwareSerial.h"
SoftwareSerial Serial1(18, 19); // RX, TX
#endif

char ssid[] = "Vodafone-A61356555";            // your network SSID (name)
char pass[] = "YgtHnkJHNpFAcPfH";        // your network password
int status = WL_IDLE_STATUS;     // the Wifi radio's status
int reqCount = 0;                // number of requests received

WiFiEspServer server(80);

int MPU = 0x69;
int MPU1 = 0x69;
int16_t AcX, AcY, AcZ, Tmp, GyX, GyY, GyZ;
int16_t AcX1, AcY1, AcZ1, Tmp1, GyX1, GyY1, GyZ1;
int gyro_state = 2;
int gyro_state_1 = 3;
int RED_LED = 8;
int GREEN_LED = 9;

void setup(){
  pinMode(gyro_state, OUTPUT);
  pinMode(gyro_state_1, OUTPUT);
  pinMode(RED_LED, OUTPUT);
  pinMode(GREEN_LED, OUTPUT);
  digitalWrite(gyro_state, HIGH);
  digitalWrite(gyro_state_1, HIGH);
  Wire.begin();
  Wire.beginTransmission(MPU);
  Wire.write(0x6B);  // PWR_MGMT_1 register
  Wire.write(0);     // set to zero (wakes up the MPU-6050)
  Wire.endTransmission(true);
  Serial.begin(115200);
  // initialize serial for ESP module
  Serial1.begin(9600);
  // initialize ESP module
  WiFi.init(&Serial1);

  // check for the presence of the shield
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("WiFi shield not present");
    // don't continue
    while (true);
  }

  // attempt to connect to WiFi network
  while ( status != WL_CONNECTED) {
    Serial.print("Attempting to connect to WPA SSID: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network
    status = WiFi.begin(ssid, pass);
  }

  Serial.println("You're connected to the network");
  printWifiStatus();

  // start the web server on port 80
  server.begin();
}

void loop() {
  // listen for incoming clients
  WiFiEspClient client = server.available();
  if (client) {
    Serial.println("New client");
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        Serial.write(c);
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {
          Serial.println("Sending response");

          // send a standard http response header
          // use \r\n instead of many println statements to speedup data send
          client.print(
            "HTTP/1.1 200 OK\r\n"
            //"Content-Type: text/html\r\n"
            "Connection: close\r\n"  // the connection will be closed after completion of the response
            "Refresh: 5\r\n"
            "\r\n");
          client.print("<!DOCTYPE HTML>\r\n");
          client.print("\r\n");
          client.print("
\r\n");
          client.print("Accelerometro Telescopio X: ");
          client.print(AcX);
          client.print("  Accelerometro Cupola X: ");
          client.print(AcX1);
          client.print("
\r\n");
          client.print("
\r\n");
          client.print("Accelerometro Telescopio Y: ");
          client.print(AcY);
          client.print("  Accelerometro Cupola Y: ");
          client.print(AcY1);
          client.print("
\r\n");
          client.print("
\r\n");
          client.print("Accelerometro Telescopio Z: ");
          client.print(AcZ);
          client.print("  Accelerometro Cupola Z: ");
          client.print(AcZ1);
          client.print("
\r\n");
          client.print("
\r\n");
          client.print("Giroscopio Telescopio X: ");
          client.print(GyX);
          client.print("  Giroscopio Cupola X: ");
          client.print(GyX1);
          client.print("
\r\n");
          client.print("
\r\n");
          client.print("Giroscopio Telescopio Y: ");
          client.print(GyY);
          client.print("  Giroscopio Cupola Y: ");
          client.print(GyY1);
          client.print("
\r\n");
          client.print("
\r\n");
          client.print("Giroscopio Telescopio Z: ");
          client.print(GyZ);
          client.print("  Giroscopio Cupola Z: ");
          client.print(GyZ1);
          client.print("
\r\n");
          client.print("
\r\n");
          client.print("Temperatura Telescopio: ");
          client.print(Tmp);
          client.print("  Temperatura Cupola: ");
          client.print(Tmp1);
          client.print("
\r\n");
          client.print("
\r\n");
          client.print("\r\n");
          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        }
        else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(100);

    // close the connection:
    client.stop();
    Serial.println("Client disconnected");
  }
  digitalWrite(gyro_state, HIGH);
  digitalWrite(gyro_state_1, LOW);

  do {
    Wire.beginTransmission(MPU);
    Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
    Wire.endTransmission(false);
    Wire.requestFrom(MPU, 14, true);       // request a total of 14 registers
    AcX = Wire.read() << 8 | Wire.read();  // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
    AcY = Wire.read() << 8 | Wire.read();  // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
    AcZ = Wire.read() << 8 | Wire.read();  // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
    Tmp = Wire.read() << 8 | Wire.read();  // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L)
    GyX = Wire.read() << 8 | Wire.read();  // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
    GyY = Wire.read() << 8 | Wire.read();  // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
    GyZ = Wire.read() << 8 | Wire.read();  // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)

    Tmp = Tmp / 340 + 36.53;

    Serial.println("First Gyro");
    Serial.println(GyZ);

    digitalWrite(gyro_state_1, HIGH);
    digitalWrite(gyro_state, LOW);
    delay(1000);

  } while(digitalRead(gyro_state)== HIGH);

  do {
    Wire.beginTransmission(MPU1);
    Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
    Wire.endTransmission(false);
    Wire.requestFrom(MPU1, 14, true);       // request a total of 14 registers
    AcX1 = Wire.read() << 8 | Wire.read();  // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
    AcY1 = Wire.read() << 8 | Wire.read();  // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
    AcZ1 = Wire.read() << 8 | Wire.read();  // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
    Tmp1 = Wire.read() << 8 | Wire.read();  // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L)
    GyX1 = Wire.read() << 8 | Wire.read();  // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
    GyY1 = Wire.read() << 8 | Wire.read();  // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
    GyZ1 = Wire.read() << 8 | Wire.read();  // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)

    Tmp1 = Tmp1 / 340 + 36.53;

    Serial.println("Second Gyro");
    Serial.println(Gy1);

    digitalWrite(gyro_state, HIGH);
    digitalWrite(gyro_state_1, LOW);
    delay(1000);

  } while(digitalRead(gyro_state_1) == HIGH);

  if (GyY > GyY1) {
    digitalWrite(9, HIGH);
    digitalWrite(8, LOW);
  }
  else if (GyY < GyY1) {
    digitalWrite(8, HIGH);
    digitalWrite(9, LOW);
  }
}

void printWifiStatus() {
  // print the SSID of the network you're attached to
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // print your WiFi shield's IP address
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);

  // print where to go in the browser
  Serial.println();
  Serial.print("To see this page in action, open a browser to http://");
  Serial.println(ip);
  Serial.println();
}

Output:
First Gyro
1503
Second Gyro
3730
First Gyro
1558
Second Gyro
-162
First Gyro
1498
Second Gyro
-164

Can anyone explain to me why once I stop moving the gyroscope, the value returns to the initial position? And if it is possible to convert to degrees?

You know, thats what gyroscopes do. They measure angular velocity, not the angle. When you stop turning the sensor the angular velocity drops to zero. Normally one would combine the accelerometer and the integrated gyroscope data to get a stable angle value

See this question on the Electrical Engineering Stackexchange: MPU6050 losing orientation

The GY-521 and the MPU6050 are the same functionally, and you need to use one of the several libraries to get what you want.  It appears you are retrieving angular rate values, but what you want is relative heading. The angular rate will return to zero (or whatever the initial value was) once it stops moving, but the heading will (with proper treatment) stay constant.
I have used the MPU6050 in several projects with success, using Jeff Rowberg’s I2CDevLib library, and although getting everything set up is complicated, I recommend it.  See this post for basic setup.
Also, I note that most of your program has nothing at all to do with the gyroscope.  I recommend you use the smallest and simplest possible program to work out the hardware issues before adding the more complex bits.


text:
Unable to replicate Arduino code into ATmega8 code
I am trying to replicate an LTC Audio Decoder code from Arduino Uno into AVR ATmega8 which I got from here.
My Arduino Uno code is working great. Here is my Arduino Uno code:
#define one_time_max          588 // these values are setup for NTSC video
#define one_time_min          422 // PAL would be around 1000 for 0 and 500 for 1
#define zero_time_max          1080 // 80bits times 29.97 frames per sec
#define zero_time_min          922 // equals 833 (divide by 8 clock pulses)

#define icpPin 8        // ICP input pin on arduino
#define end_data_position      63
#define end_sync_position      77
#define end_smpte_position     80

volatile unsigned int bit_time;
volatile boolean valid_tc_word;
volatile boolean ones_bit_count;
volatile boolean tc_sync;
volatile boolean write_tc_out;
volatile boolean drop_frame_flag;

volatile byte total_bits;
volatile byte current_bit;
volatile byte sync_count;

volatile byte tc[8];
volatile char timeCode[11];

/* ICR interrupt vector */
ISR(TIMER1_CAPT_vect)
{
 //toggleCaptureEdge
 TCCR1B ^= _BV(ICES1);
  //Serial.println("Inter");
 bit_time = ICR1;

 //resetTimer1
 TCNT1 = 0;

if ((bit_time < one_time_min) || (bit_time > zero_time_max)) // get rid of anything way outside the norm
 {
   //Serial.println(bit_time, DEC);
   total_bits = 0;
 }
 else
 {
   if (ones_bit_count == true) // only count the second ones pluse
     ones_bit_count = false;
   else
   {
     if (bit_time > zero_time_min)
     {
       current_bit = 0;
       sync_count = 0;
     }
     else //if (bit_time < one_time_max)
     {
       ones_bit_count = true;
       current_bit = 1;
       sync_count++;
       if (sync_count == 12) // part of the last two bytes of a timecode word
       {
         sync_count = 0;
         tc_sync = true;
         total_bits = end_sync_position;
       }
     }

     if (total_bits <= end_data_position) // timecode runs least to most so we need
     {                                    // to shift things around
       tc[0] = tc[0] >> 1;

       for(int n=1;n<8;n++)
       {
         if(tc[n] & 1)
           tc[n-1] |= 0x80;

         tc[n] = tc[n] >> 1;
       }

       if(current_bit == 1)
         tc[7] |= 0x80;
     }
     total_bits++;
   }

   if (total_bits == end_smpte_position) // we have the 80th bit
   {
     total_bits = 0;
     if (tc_sync)
     {
       tc_sync = false;
       valid_tc_word = true;
     }
   }

   if (valid_tc_word)
   {
     valid_tc_word = false;

     timeCode[11]= '\0';
     timeCode[10] = (tc[0]&0x0F)+0x30;      // frames
     timeCode[9] = (tc[1]&0x03)+0x30;      // 10's of frames
     timeCode[8] =  '-';
     timeCode[7] = (tc[2]&0x0F)+0x30;      // seconds
     timeCode[6] = (tc[3]&0x07)+0x30;      // 10's of seconds
     timeCode[5] =  '-';
     timeCode[4] = (tc[4]&0x0F)+0x30;      // minutes
     timeCode[3] = (tc[5]&0x07)+0x30;      // 10's of minutes
     timeCode[2] = '-';
     timeCode[1] = (tc[6]&0x0F)+0x30;      // hours
     timeCode[0] = (tc[7]&0x03)+0x30;      // 10's of hours

       drop_frame_flag = bit_is_set(tc[1], 2);

     write_tc_out = true;
   }
 }
}

void setup()
{
 Serial.begin(9600);
 pinMode(8, INPUT);                  // ICP pin (digital pin 8 on arduino) as input

 bit_time = 0;
 valid_tc_word = false;
 ones_bit_count = false;
 tc_sync = false;
 write_tc_out = false;
 drop_frame_flag = false;
 total_bits =  0;
 current_bit =  0;
 sync_count =  0;

 Serial.println("Finished setup ");
 delay (1000);

 TCCR1A = B00000000; // clear all
 TCCR1B = B11000010; // ICNC1 noise reduction + ICES1 start on rising edge + CS11 divide by 8
 TCCR1C = B00000000; // clear all
 TIMSK1 = B00100000; // ICIE1 enable the icp

 TCNT1 = 0; // clear timer1
}

void loop()
{
  if (write_tc_out)
   {
     write_tc_out = false;
     //if (drop_frame_flag)
       //Serial.print("TC-[df] ");
     //else
       //Serial.print("TC-[nd] ");
     Serial.println((char*)timeCode);
   //  Serial.print("  ");
     //Serial.print("\r");
   }
}

Now to replicate this code for AVR ATmega8, I just copy this code in AVR studio and make small changes like initializing UART, initializing Input Capture Mode etc. Here is my AVR ATmega8 code:
#define F_CPU 16000000UL

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/sfr_defs.h>

#define one_time_max          588 // these values are setup for NTSC video
#define one_time_min          422 // PAL would be around 1000 for 0 and 500 for 1
#define zero_time_max          1080 // 80bits times 29.97 frames per sec
#define zero_time_min          922 // equals 833 (divide by 8 clock pulses)

#define icpPin 8        // ICP input pin on arduino
#define end_data_position      63
#define end_sync_position      77
#define end_smpte_position     80

volatile unsigned int bit_time;
volatile char valid_tc_word;
volatile char ones_bit_count;
volatile char tc_sync;
volatile char write_tc_out;
volatile char drop_frame_flag;

volatile unsigned char total_bits;
volatile unsigned char current_bit;
volatile unsigned char sync_count;

volatile unsigned char tc[8];
volatile char timeCode[11];

void USARTInit(uint16_t ubrr_value)
{

    UBRRL = ubrr_value;
    UBRRH = (ubrr_value>>8);
    UCSRC|=(1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);
    UCSRB=(1<<RXCIE)|(1<<RXEN)|(1<<TXEN);

}

unsigned char USARTReadChar()
{

    while(!(UCSRA & (1<<RXC)));
    return UDR;
}

void USARTWriteChar(char data)
{

    while(!(UCSRA & (1<<UDRE)));
    UDR=data;
}

void send_string(char s[])
{
    int i =0;

    while (s[i] != 0x00)
    {
        USARTWriteChar(s[i]);
        i++;
    }
}

int main(void)
{

    USARTInit(103);
    DDRB=0;
     bit_time = 0;
     valid_tc_word = 0;
     ones_bit_count = 0;
     tc_sync = 0;
     write_tc_out = 0;
     drop_frame_flag = 0;
     total_bits =  0;
     current_bit =  0;
     sync_count =  0;

    send_string("FINISHED SETUP");
    _delay_ms(1000);

    TCCR1A = 0;
    TCCR1B = (1<<ICNC1)|(1<<ICES1)|(1<<CS11);
    TIMSK = (1<<TICIE1);
    TCNT1 = 0;
    sei();
    while(1)
    {

        if (write_tc_out==1)
        {
            write_tc_out = 0;
            send_string((char*)timeCode);
        }
}

}

ISR(TIMER1_CAPT_vect)
{

 //toggleCaptureEdge
 TCCR1B ^= _BV(ICES1);
  //Serial.println("Inter");
 bit_time = ICR1;

 //resetTimer1
 TCNT1 = 0;

if ((bit_time < one_time_min) || (bit_time > zero_time_max)) // get rid of anything way outside the norm
 {
   //Serial.println(bit_time, DEC);
   total_bits = 0;
 }
 else
 {
   if (ones_bit_count == 1) // only count the second ones pluse
     ones_bit_count = 0;
   else
   {
     if (bit_time > zero_time_min)
     {
       current_bit = 0;
       sync_count = 0;
     }
     else //if (bit_time < one_time_max)
     {
       ones_bit_count = 1;
       current_bit = 1;
       sync_count++;
       if (sync_count == 12) // part of the last two bytes of a timecode word
       {
         sync_count = 0;
         tc_sync = 1;
         total_bits = end_sync_position;
       }
     }

     if (total_bits <= end_data_position) // timecode runs least to most so we need
     {
               // to shift things around
       tc[0] = tc[0] >> 1;

       for(int n=1;n<8;n++)
       {
         if(tc[n] & 1)
           tc[n-1] |= 0x80;

         tc[n] = tc[n] >> 1;
       }

       if(current_bit == 1)
         tc[7] |= 0x80;
     }
     total_bits++;
   }

   if (total_bits == end_smpte_position) // we have the 80th bit
   {
     total_bits = 0;
     if (tc_sync)
     {
       tc_sync = 0;
       valid_tc_word = 1;
     }
   }

  if (valid_tc_word==1)
   {

     valid_tc_word = 0;

     timeCode[11]= '\0';
     timeCode[10] = (tc[0]&0x0F)+0x30;      // frames
     timeCode[9] = (tc[1]&0x03)+0x30;      // 10's of frames
     timeCode[8] =  '-';
     timeCode[7] = (tc[2]&0x0F)+0x30;      // seconds
     timeCode[6] = (tc[3]&0x07)+0x30;      // 10's of seconds
     timeCode[5] =  '-';
     timeCode[4] = (tc[4]&0x0F)+0x30;      // minutes
     timeCode[3] = (tc[5]&0x07)+0x30;      // 10's of minutes
     timeCode[2] = '-';
     timeCode[1] = (tc[6]&0x0F)+0x30;      // hours
     timeCode[0] = (tc[7]&0x03)+0x30;      // 10's of hours

       drop_frame_flag = bit_is_set(tc[1], 2);

     write_tc_out = 1;
   }

 }
}

Now when I run this code, I don't get any time stamps. I have gone through this code many times but I am unable to figure out the mistake in my code. Can any one help me figure out the issue?

I figure out the issue , I just add a small delay in ISR and my code is running fine now. I don't know reason behind it but anyway my code is running now. Here is my new code:-
#define F_CPU 16000000UL

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/sfr_defs.h>

#define one_time_max          588 // these values are setup for NTSC video
#define one_time_min          422 // PAL would be around 1000 for 0 and 500 for 1
#define zero_time_max          1080 // 80bits times 29.97 frames per sec
#define zero_time_min          922 // equals 833 (divide by 8 clock pulses)

#define icpPin 8        // ICP input pin on arduino
#define end_data_position      63
#define end_sync_position      77
#define end_smpte_position     80

volatile unsigned int bit_time;
volatile char valid_tc_word;
volatile char ones_bit_count;
volatile char tc_sync;
volatile char write_tc_out;
volatile char drop_frame_flag;

volatile unsigned char total_bits;
volatile unsigned char current_bit;
volatile unsigned char sync_count;

volatile unsigned char tc[8];
volatile char timeCode[11];

void USARTInit(uint16_t ubrr_value)
{

    UBRRL = ubrr_value;
    UBRRH = (ubrr_value>>8);
    UCSRC|=(1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);
    UCSRB=(1<<RXCIE)|(1<<RXEN)|(1<<TXEN);

}

unsigned char USARTReadChar()
{

    while(!(UCSRA & (1<<RXC)));
    return UDR;
}

void USARTWriteChar(char data)
{

    while(!(UCSRA & (1<<UDRE)));
    UDR=data;
}

void send_string(char s[])
{
    int i =0;

    while (s[i] != 0x00)
    {
        USARTWriteChar(s[i]);
        i++;
    }
    USARTWriteChar('\n');
}

int main(void)
{

    USARTInit(103);
    DDRB=0;
    bit_time = 0;
    valid_tc_word = 0;
    ones_bit_count = 0;
    tc_sync = 0;
    write_tc_out = 0;
    drop_frame_flag = 0;
    total_bits =  0;
    current_bit =  0;
    sync_count =  0;

    send_string("FINISHED SETUP");
    _delay_ms(1000);

    TCCR1A = 0;
    TCCR1B = (1<<ICNC1)|(1<<ICES1)|(1<<CS11);
    TIMSK = (1<<TICIE1);
    TCNT1 = 0;
    sei();
    while(1)
    {

        if (write_tc_out==1)
        {
            write_tc_out = 0;
            send_string((char*)timeCode);
        }
    }

}

ISR(TIMER1_CAPT_vect)
{

    //toggleCaptureEdge
    TCCR1B ^= _BV(ICES1);
    //Serial.println("Inter");
    bit_time = ICR1;

    //resetTimer1
    TCNT1 = 0;
_delay_us(13);

    if ((bit_time < one_time_min) || (bit_time > zero_time_max)) // get rid of anything way outside the norm
    {
        //Serial.println(bit_time, DEC);
        total_bits = 0;
    }
    else
    {
        if (ones_bit_count == 1) // only count the second ones pluse
        ones_bit_count = 0;
        else
        {
            if (bit_time > zero_time_min)
            {
                current_bit = 0;
                sync_count = 0;
            }
            else //if (bit_time < one_time_max)
            {
                ones_bit_count = 1;
                current_bit = 1;
                sync_count++;
                if (sync_count == 12) // part of the last two bytes of a timecode word
                {
                    sync_count = 0;
                    tc_sync = 1;
                    total_bits = end_sync_position;
                }
            }

            if (total_bits <= end_data_position) // timecode runs least to most so we need
            {
                // to shift things around
                tc[0] = tc[0] >> 1;

                for(int n=1;n<8;n++)
                {
                    if(tc[n] & 1)
                    tc[n-1] |= 0x80;

                    tc[n] = tc[n] >> 1;
                }

                if(current_bit == 1)
                tc[7] |= 0x80;
            }
            total_bits++;
        }

        if (total_bits == end_smpte_position) // we have the 80th bit
        {
            total_bits = 0;
            if (tc_sync)
            {
                tc_sync = 0;
                valid_tc_word = 1;
            }
        }

        if (valid_tc_word==1)
        {

            valid_tc_word = 0;

            timeCode[11]= '\0';
            timeCode[10] = (tc[0]&0x0F)+0x30;      // frames
            timeCode[9] = (tc[1]&0x03)+0x30;      // 10's of frames
            timeCode[8] =  '-';
            timeCode[7] = (tc[2]&0x0F)+0x30;      // seconds
            timeCode[6] = (tc[3]&0x07)+0x30;      // 10's of seconds
            timeCode[5] =  '-';
            timeCode[4] = (tc[4]&0x0F)+0x30;      // minutes
            timeCode[3] = (tc[5]&0x07)+0x30;      // 10's of minutes
            timeCode[2] = '-';
            timeCode[1] = (tc[6]&0x0F)+0x30;      // hours
            timeCode[0] = (tc[7]&0x03)+0x30;      // 10's of hours

            drop_frame_flag = bit_is_set(tc[1], 2);

            write_tc_out = 1;
        }

    }
}


text:
ESP32 AP Automatic Web Page
I've often encountered WiFi networks that require you to sign in through a web page that automatically opens after connecting to the access point, such as hotels. I'd like to implement something similar with an ESP32, where a web page opens automatically after connecting to the AP. Is this doable? This seems to be difficult to Google, because I just get a bunch of introductory tutorials on setting up an AP.
Here's some project context in case it helps. I'm making an IoT device that needs to connect to the user's WiFi network, so the user needs to specify the login credentials. The solution I'm trying to implement is having the ESP32 set up a temporary AP, where the user can connect to that and enter their home WiFi credentials. As it stands now, the user has to manually type in the IP address of the ESP32 after connecting to the AP, but it'd be much more user friendly if the web page opened automatically like hotel WiFi networks sometimes do.
I've tinkered with this WiFi Manager library that appears to do what I want, but I'd like to implement mine from scratch.

I think you didn't find anything, because you searched for the wrong terms. What you want is a "captive Portal". I think there are some tutorials available on the web about that. Please try a search with that term. Something like "ESP32 captive portal".

Yeah, I figured that out as I was writing the question. I decided to post it anyways, since I'm guessing others may be in the same boat as me. I've already posted an answer with that info, but thanks for the help anyways!

Of course, as soon as I linked that WiFi Manager library in my question, I figured it out. The term I was missing was "captive portal" and I was able to figure it out from there. But I decided to post the question anyways, since it might help someone else stuck in the same situation.
Here's my understanding of how it works: when your device connects to a new network, it tries to ping a server to see whether it has internet access. With the ESP32, you can set up a DNS that redirects that ping to a web server running on the ESP32, which opens up the browser on the device.
I found this tutorial helpful for me to understand how that works, along with example code. This should be enough for me to get it working.
https://iotespresso.com/create-captive-portal-using-esp32/


text:
Having trouble with MPU6050 and AFE4404 printing together, potential conflict?
I am having trouble getting the two sensors to work together. There are a total of four sensors connected to the Arduino, and while the MPU and AFE individually work fine with the other two sensors, when the two are put together only the Serial Plotter for the AFE shows up while the MPU stays at zero. I initially assumed that there were address conflicts with the two, but their i2c addresses are different: the AFE at 0x58 and the MPU at 0x68 or 0x69. How can I resolve the issue so that I can get all four sensors' graphs printing?
Below is my Arduino code:
#include "I2Cdev.h"
#include "MPU6050.h"
#include "Wire.h"

//int preValue = 0;
String str = "0, 0, 0, 0";
int mic = A0;
MPU6050 mpu;
int16_t ax, ay, az;

//PPG Stuff
#define NUM_REGISTERS       40
/* Pinbelegung */

int RESETZ = 4;
int CLK = 5;
int INT = 6;
//const int ocr1aval = 1; //||0 = 8MHz|| 1 = 4MHz|| 3 = 2MHZ ||7 = 1MHz||
const byte interruptPin = 2;

char LED2 = 0x2A; // LED2 on AFE4404

struct Register {
  uint8_t addr;
  uint32_t val;
};
/* Variablendeklaration */

//float befehl = 0;
bool Ready = 1;
int AFE_ADDR = 0x58;

unsigned long counter = 0;

/* AFE440X registers */

#define AFE_CONTROL0                0x00
#define AFE_LED2STC                 0x01
#define AFE_LED2ENDC                0x02
#define AFE_LED1LEDSTC              0x03
#define AFE_LED1LEDENDC             0x04
#define AFE_ALED2STC                0x05
#define AFE_ALED2ENDC               0x06
#define AFE_LED1STC                 0x07
#define AFE_LED1ENDC                0x08
#define AFE_LED2LEDSTC              0x09
#define AFE_LED2LEDENDC             0x0A
#define AFE_ALED1STC                0x0B
#define AFE_ALED1ENDC               0x0C
#define AFE_LED2CONVST              0x0D
#define AFE_LED2CONVEND             0x0E
#define AFE_ALED2CONVST             0x0F
#define AFE_ALED2CONVEND            0x10
#define AFE_LED1CONVST              0x11
#define AFE_LED1CONVEND             0x12
#define AFE_ALED1CONVST             0x13
#define AFE_ALED1CONVEND            0x14
#define AFE_ADCRSTSTCT0             0x15
#define AFE_ADCRSTENDCT0            0x16
#define AFE_ADCRSTSTCT1             0x17
#define AFE_ADCRSTENDCT1            0x18
#define AFE_ADCRSTSTCT2             0x19
#define AFE_ADCRSTENDCT2            0x1A
#define AFE_ADCRSTSTCT3             0x1B
#define AFE_ADCRSTENDCT3            0x1C
#define AFE_PRPCOUNT                0x1D
#define AFE_CONTROL1                0x1E
#define AFE_TIA_GAIN_SEP            0x20
#define AFE_TIA_GAIN                0x21
#define AFE_LEDCNTRL                0x22
#define AFE_CONTROL2                0x23
#define AFE_ALARM                   0x29
#define AFE_LED2VAL                 0x2A
#define AFE_ALED2VAL                0x2B
#define AFE_LED1VAL                 0x2C
#define AFE_ALED1VAL                0x2D
#define AFE_LED2_ALED2VAL           0x2E
#define AFE_LED1_ALED1VAL           0x2F
#define AFE_CONTROL3                0x31
#define AFE_PDNCYCLESTC             0x32
#define AFE_PDNCYCLEENDC            0x33
#define AFE_PROG_TG_STC             0x34
#define AFE_PROG_TG_ENDC            0x35
#define AFE_LED3LEDSTC              0x36
#define AFE_LED3LEDENDC             0x37
#define AFE_CLKDIV_PRF              0x39
#define AFE_OFFDAC                  0x3A
#define AFE_DEC                     0x3D
#define AFE_AVG_LED2_ALED2VAL       0x3F
#define AFE_AVG_LED1_ALED1VAL       0x40

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

  //ECG
  pinMode(10, INPUT); // Setup for leads off detection LO +
  pinMode(11, INPUT); // Setup for leads off detection LO -

  //PCG
  /*none needed*/

  //PPG
  pinMode(RESETZ, OUTPUT);
  pinMode(CLK, OUTPUT);
  pinMode(INT, INPUT);
  AFE_Init();

  //SCG
  #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
        Wire.begin();
  #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
        Fastwire::setup(400, true);
  #endif
  // initialize device
  mpu.initialize();
}

void PCG_Init()
{
  double micOut;
  const int sampleTime = 50;
  double preValue = 0;
}

void loop() {
  // put your main code here, to run repeatedly:
  String ECG = "0";
  //String SCG = "0";

  int PCG_val;
  String PCG;
  PCG_val = PCG_loop();
  PCG = String(PCG_val);

  int PPG_val;
  String PPG;
  PPG_val = PPG_loop() * -1;
  PPG = String(PPG_val);

//  int ECG_val;
//  String ECG;
//  ECG_val = ECG_loop();
//  ECG = String(ECG_val);

  int SCG_val;
  String SCG;
  SCG_val = SCG_loop();
  SCG = String(SCG_val);

  str = PCG + "," + PPG + "," + ECG + "," + SCG;
  Serial.println(str);
  delay(10);
}

//ECG Loop
int ECG_loop() {
  // put your main code here, to run repeatedly:
  if((digitalRead(10) == 1)||(digitalRead(11) == 1)){
  Serial.println('!');
  }
  else{
  // send the value of analog input 0:
  Serial.println(analogRead(A1));
  }
  //Wait for a bit to keep serial data from saturating
  delay(1);
  //delay (30);
}

//SCG Loop
int SCG_loop() {
    mpu.getAcceleration(&ax, &ay, &az);
    Serial.println(az/(pow(2,9)*1.0));
}

//PCG Loop
int PCG_loop() {
  //switch
  //case 1:
  int returnfill;
   double micOutput = findPTPAmp();
   returnfill = VUMeter(micOutput);
   return returnfill;
}

// Find the Peak-to-Peak Amplitude Function
double findPTPAmp(){
// Time variables to find the peak-to-peak amplitude
   unsigned long startTime= millis();  // Start of sample window
   /*unsigned int*/ double PTPAmp = 0;

// Signal variables to find the peak-to-peak amplitude
   /*unsigned int*/ double maxAmp = 0;
   /*unsigned int*/ double minAmp = 1023;

// Find the max and min of the mic output within the 50 ms timeframe
   while(millis() - startTime < sampleTime)
   {
      micOut = analogRead(mic);
      if( micOut < 1023) //prevent erroneous readings
      {
        if (micOut > maxAmp)
        {
          maxAmp = micOut; //save only the max reading
        }
        else if (micOut < minAmp)
        {
          minAmp = micOut; //save only the min reading
        }
      }
   }

  PTPAmp = maxAmp - minAmp; // (max amp) - (min amp) = peak-to-peak amplitude
  double micOut_Volts = (PTPAmp * 3.3) / 1024; // Convert ADC into voltage
  return PTPAmp;
}

// Volume Unit Meter function: map the PTP amplitude to a volume unit between 0 and 10.
int VUMeter(double micAmp){
  double fill = map(micAmp, 23, 750, 0, 10);
  while(fill != preValue)
  {
    preValue = fill;
  }
  return fill;
}

//PPG Loop
signed long val = 0;
void readADC()
{
  {
    val = AFE_Reg_Read(LED2);
    Ready = 1;
  }
}

int PPG_loop() {
  if (digitalRead(INT))
  {
    val = AFE_Reg_Read(LED2);
  }
  return val;
}

//More PPG Stuff
void AFE_Init()
{
  AFE_RESETZ_Init();
  AFE_Enable_HWPDN();
  AFE_Disable_HWPDN();
  AFE_Trigger_HWReset();
  Wire.begin();
  Wire.beginTransmission (AFE_ADDR);
  Serial.println("Initializing AFE4404...");
  if (Wire.endTransmission () == 0)
  {
    AFE_Enable_Write (); // enable to writting to registers
    AFE_Reg_Init();
    AFE_CLK_Init();
    AFE_Enable_Read ();  // enable to reading from registers
    Serial.println("Initialized Success!");
  }
  else
    Serial.println("Initialized Fail!");

}

/**********************************************************************************************************/
/*                              AFE4404_Registerinitialisierung                                           */
/**********************************************************************************************************/
void AFE_Reg_Init()
{
  //AFE_Reg_Write(34, 0x0033C3);
  AFEinitRegisters();
}

/**********************************************************************************************************/
/*                              AFE4404_Enable_Read                                                       */
/**********************************************************************************************************/
void AFE_Enable_Read ()         //Prohibit writing to registers
{
  byte configData[3];
  configData[0] = 0x00;
  configData[1] = 0x00;
  configData[2] = 0x01;// 0x01
  I2C_write (AFE_ADDR, AFE_CONTROL0, configData, 3);
}

/**********************************************************************************************************/
/*                              AFE4404_Disable_Read                                                      */
/**********************************************************************************************************/
void AFE_Enable_Write ()        //Permitt writing to registers
{
  byte configData[3];
  configData[0] = 0x00;
  configData[1] = 0x00;
  configData[2] = 0x00; //0x00
  I2C_write (AFE_ADDR, AFE_CONTROL0, configData, 3);
}

/**********************************************************************************************************/
/*                  RESETZ des AFE4404 wird Initialisiert                                                 */
/**********************************************************************************************************/
void AFE_RESETZ_Init()
{
  digitalWrite(RESETZ, HIGH);
  delayMicroseconds(30);
}

/**********************************************************************************************************/
/*                  Reset internal registers by setting RESETZ = LOW for 25 - 50 us                       */
/**********************************************************************************************************/
void AFE_Trigger_HWReset()
{
  digitalWrite(RESETZ, LOW);              //Sets Arduino pins 22-29 LOW
  delayMicroseconds(30); //30
  digitalWrite(RESETZ, HIGH);              //Sets Arduino pins 22-29 HIGH
  delay(10); // 10
}

/**********************************************************************************************************/
/*                             AFE4404 Power Down                                                         */
/**********************************************************************************************************/
void  AFE_Enable_HWPDN()
{
  digitalWrite(RESETZ, LOW);                  //Power Down by setting the RESETZ pin to LOW for more than 200 us
  delay(10);
}

/**********************************************************************************************************/
/*                                AFE4404 Power Up                                                        */
/**********************************************************************************************************/
void  AFE_Disable_HWPDN()
{
  digitalWrite(RESETZ, HIGH);                  //Power Up the AFE by setting the RESETZ pin to HIGH
  delay(10);
}

/**********************************************************************************************************/
/*                                AFE4404 Set Clock Mode to Internal                                      */
/**********************************************************************************************************/

void AFE_CLK_Init()
{
  AFE_Reg_Write(35, 0x104218);        //Set CLK Mode to internal clock (default Wert: 124218 mit interner CLK)
  AFE_Reg_Write(41, 0x2);             //Don´t set the internal clock to the CLK pin for outside usage
  AFE_Reg_Write(49, 0x000021);        //Division ratio for external clock mode set to fit the Arduino Mega 16MHz
  AFE_Reg_Write(57, 0);               //Set the lowes sampling rate to 61Hz (~17 ms)
}

/*********************************************************************************************************/
/*                                   AFE4404_Reg_Write                                                   */
/*********************************************************************************************************/
void AFE_Reg_Write (int reg_address, unsigned long data)
{
  byte configData[3];
  configData[0] = (byte)(data >> 16);
  configData[1] = (byte)(((data & 0x00FFFF) >> 8));
  configData[2] = (byte)(((data & 0x0000FF)));
  I2C_write(AFE_ADDR, reg_address, configData, 3);
}

/*********************************************************************************************************/
/*                                   AFE4404_Reg_Read                                                    */
/*********************************************************************************************************/
signed long AFE_Reg_Read(int reg_address)
{
  byte configData[3];
  signed long retVal;
  I2C_read (AFE_ADDR, reg_address, configData, 3);
  retVal = configData[0];
  retVal = (retVal << 8) | configData[1];
  retVal = (retVal << 8) | configData[2];
  if (reg_address >= 0x2A && reg_address <= 0x2F)
  {
    if (retVal & 0x00200000)  // check if the ADC value is positive or negative
    {
      retVal &= 0x003FFFFF;   // convert it to a 22 bit value
      return (retVal ^ 0xFFC00000);
    }
  }
  return retVal;
}

/**********************************************************************************************************/
/*                              Write to AFE on I2C                                                       */
/**********************************************************************************************************/
char I2C_write (int slave_address, int reg_address, byte configData[], int byteCount)
{
  int trans_end = 0;
  signed long retVal;

  Wire.beginTransmission(slave_address);
  Wire.write(reg_address);
  Serial.print(configData[0]);
  Serial.print(",");
  Serial.print(configData[1]);
  Serial.print(",");
  Serial.println(configData[2]);
  retVal = configData[0];
  retVal = (retVal << 8) | configData[1];
  retVal = (retVal << 8) | configData[2];
  Serial.println(retVal);
  Serial.println(reg_address);
  Wire.write(configData, 3);
  Serial.println("test");
  Wire.endTransmission();
  return (trans_end);

  /* while(1)
    {
     if(byteCount == 0)
     {
       Wire.endTransmission();
       Serial.println("test");
       return (trans_end);
     }else{
       //unsigned int reg_data = (unsigned int) *write_data++;
       Wire.write(configData, 3);
       byteCount--;
     }
    }*/
}

/**********************************************************************************************************/
/*                              Read Data of AFE on I2C                                                   */
/**********************************************************************************************************/
char I2C_read(int slave_address, int reg_address, byte *read_Data, int byteCount)
{
  int trans_end = 0;

  Wire.beginTransmission(slave_address);
  Wire.write(reg_address);
  Wire.endTransmission();
  Wire.requestFrom(slave_address, 3);
  while (Wire.available() && (byteCount != 0))
  {
    *read_Data++ = Wire.read();
    byteCount--;
  }
  return (trans_end);
}

void AFEinitRegisters(void) {

  unsigned char i;
  struct Register reg[NUM_REGISTERS];
  reg[0].addr = 0x01; reg[0].val = 0x000050;
  reg[1].addr = 0x02; reg[1].val = 0x00018F;
  reg[2].addr = 0x03; reg[2].val = 0x000320;
  reg[3].addr = 0x04; reg[3].val = 0x0004AF;
  reg[4].addr = 0x05; reg[4].val = 0x0001E0;
  reg[5].addr = 0x06; reg[5].val = 0x00031F;
  reg[6].addr = 0x07; reg[6].val = 0x000370;
  reg[7].addr = 0x08; reg[7].val = 0x0004AF;
  reg[8].addr = 0x09; reg[8].val = 0x000000;
  reg[9].addr = 0x0A; reg[9].val = 0x00018F;
  reg[10].addr = 0x0B; reg[10].val = 0x0004FF;
  reg[11].addr = 0x0C; reg[11].val = 0x00063E;
  reg[12].addr = 0x0D; reg[12].val = 0x000198;
  reg[13].addr = 0x0E; reg[13].val = 0x0005BB;
  reg[14].addr = 0x0F; reg[14].val = 0x0005C4;
  reg[15].addr = 0x10; reg[15].val = 0x0009E7;
  reg[16].addr = 0x11; reg[16].val = 0x0009F0;
  reg[17].addr = 0x12; reg[17].val = 0x000E13;
  reg[18].addr = 0x13; reg[18].val = 0x000E1C;
  reg[19].addr = 0x14; reg[19].val = 0x00123F;
  reg[20].addr = 0x15; reg[20].val = 0x000191;
  reg[21].addr = 0x16; reg[21].val = 0x000197;
  reg[22].addr = 0x17; reg[22].val = 0x0005BD;
  reg[23].addr = 0x18; reg[23].val = 0x0005C3;
  reg[24].addr = 0x19; reg[24].val = 0x0009E9;
  reg[25].addr = 0x1A; reg[25].val = 0x0009EF;
  reg[26].addr = 0x1B; reg[26].val = 0x000E15;
  reg[27].addr = 0x1C; reg[27].val = 0x000E1B;
  reg[28].addr = 0x1D; reg[28].val = 0x009C3F;
  reg[29].addr = 0x1E; reg[29].val = 0x000103;
  reg[30].addr = 0x20; reg[30].val = 0x008025; //0x008003
  reg[31].addr = 0x21; reg[31].val = 0x000125;//0x000003 //bit8: PROG_TG_EN
  reg[32].addr = 0x22; reg[32].val = 0x000100;//ILED2 = 32
  reg[33].addr = 0x23; reg[33].val = 0x000000;
  reg[34].addr = 0x32; reg[34].val = 0x00155F;
  reg[35].addr = 0x33; reg[35].val = 0x00991F;
  reg[36].addr = 0x36; reg[36].val = 0x000190;
  reg[37].addr = 0x37; reg[37].val = 0x00031F;
  reg[38].addr = 0x34; reg[38].val = 0x001563;
  reg[39].addr = 0x35; reg[39].val = 0x00991F;

  for (i = 0; i < NUM_REGISTERS; i++)
    AFE_Reg_Write(reg[i].addr, reg[i].val);

}

I am plotting each of the four sensors on LabView. Any help would be much appreciated!

You never change ECG to anything from 0, so of course it's always zero.

I don't even know where to begin with this program. It's such a mess I don't think it's salvageable. You should learn some basic C syntax before you start programming.

Troubleshooting I2C issues can be frustrating.  In order to figure out the problem, I recommend you construct the simplest possible Arduino sketch, using just the two sensors that seem to have a problem working together.  You should be able to write a very simple program that does nothing but acquire a simple value from each sensor, say 2 times/second.
Once you have the simplest possible program running, you should be able to figure it out.  Right now all your program complexity is making it harder than it needs to be.
Good luck!
Frank


text:
Ethernet Shield not connecting
I've mounted an Ethernet Shield on top of an Arduino UNO. The Arduino is connected via usb to my pc and to the network via ethernet through a switch.
I'm running a simplified verison of the WebServer example and the function to Ethernet.begin() always returns EthernetNoHardware.
I've tried different setups changing the ethernet cables and connecting directly to the router. I also tried adding specific ip, gateway and subnet parameters to Ethernet.begin() however the output doesn't change and the server can't be reached:
#include <SPI.h>
#include <Ethernet.h>

byte mac[] = { 0x90, 0xA2, 0xDA, 0x0F, 0xCC, 0x1E }; //mac address on the sticker
IPAddress ip(192, 168, 1, 134);
IPAddress gateway(192,168,1,1);
IPAddress subnet(255,255,255,0);
IPAddress DNSserver(192,168,1,1);
EthernetServer server(80);

void setup() {
  Ethernet.init(10);
  Serial.begin(9600);
  while (!Serial) {
    ;
  }

  Ethernet.begin(mac, ip, gateway, subnet);

  if (Ethernet.hardwareStatus() == EthernetNoHardware) {
    Serial.println("Ethernet shield not found.");
  }

  server.begin();
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());
}

output:
Ethernet shield not found.
server is at 192.168.1.134

Any idea on what the issue might be?

I'm using a W5100

In your sketch DNS IP parameter is missing in Ethernet.begin.
It should be Ethernet.begin(mac, ip, dns, gateway, subnet);


text:
Using MFRC522 along with other inputs (Bluetooth, keypad)
I'm making a little parking lot, which includes mostly opening a servo motor using either keypad, Bluetooth (hc-05) and freshly added, RFID (RC522).
I can't get inputs from other sources if I want to get the UID from the RFID meaning when I added the only piece of code that I found that returns the UID it seems to block all the void loop() hence all the other inputs/code don't work.
Here's the full code:
#include <LiquidCrystal.h>  //Lcd functions library
#include <Servo.h>          //Servo Motor
#include <SoftwareSerial.h>//Bluetooth functions library:HC05 IS SUPERIOR!
#include "TM1637.h"        //4 digit display functions library
#include <SPI.h>
#include <MFRC522.h>
//Credit to Baroryan

//copyright (c)*/
const int rs = 38, en = 39, d4 = 36 ,d5 = 37, d6 = 41, d7 = 40;//Defining LCD PINS
const int DA=31, D0=30,D1=33,D2=32,D3=35;//Defining KEYPAD data PINS
const int servoPin=43,buzzer=42,rx=53,tx=52;//Defining(By order): servo pin, buzzer pin, 4DD pins, and bluetooth pins(rx tx)
//buzzer pin is 36!
//,CLK=34,DIO=35

#define SS_PIN 45
#define RST_PIN 44
int count = 0;
int cnt=0;//this cnt is used later on to make sure all 5 chars are equal.
int cnt2=0;//used for switch case to count how many chars were already received
int cnt3=0;
char c=0;//this is where we place the char received from the user

char password[5] = {'8', '5', '2', '0', '#'};
char keysPressed[5] = "";
char keys[5]="";

byte customChar2[] = {
  B00000,
  B00000,
  B01010,
  B00000,
  B10001,
  B01110,
  B00000,
  B00000
};

byte customChar[] = {//Custom Char for lcd screen, in this case; a heart.
  0x00,
  0x00,
  0x0A,
  0x1F,
  0x1F,
  0x0E,
  0x04,
  0x00
};
//  #define DA 25 Used to define Keypad pins and other misc using #Define which talks to the processor->
//  #define D0 24  ->decided to use const int instead.
//  #define D1 27
//  #define D2 26
//  #define D3 29
//  #define servoPin 37
//  #define buzzer 36
//  #define CLK 34
//  #define DIO 35
void lcdSetup();
void gateOpenSequence();
void returnKey(int key);
void wrongPassword();
void Beep();
SoftwareSerial Bluetooth(rx,tx);//intialize bluetooth to pins
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);//intialize LCD to pins
MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance.
Servo servo;//intialize servo
byte nuidPICC[4];

void printHex(byte *buffer, byte bufferSize) {
  for (byte i = 0; i < bufferSize; i++) {
    Serial.print(buffer[i] < 0x10 ? " 0" : " ");
    Serial.print(buffer[i], HEX);
  }
}

void setup()
{
  Serial.begin(9600);
  Bluetooth.begin(9600);
  SPI.begin();      // Initiate  SPI bus
  pinMode(DA ,INPUT);
  pinMode(D0 ,INPUT);
  pinMode(D1 ,INPUT);
  pinMode(D2,INPUT);
  pinMode(D3,INPUT);
  mfrc522.PCD_Init();   // Initiate MFRC522
  lcd.begin(20,4);
  lcdSetup();//Self Created function that turns lcd to our preffered default screen "Home screen"
  servo.attach(servoPin);
  servo.write(5);
  pinMode(buzzer,OUTPUT);
  digitalWrite(buzzer, HIGH);
  delay(200);
  digitalWrite(buzzer, LOW);
  Bluetooth.print("Enter 1 to open the gate!");//Write to user bluetooth terminal instructions
  lcd.createChar(2, customChar2);
  lcd.createChar(1, customChar);
}

void loop()
{

  if (!mfrc522.PICC_IsNewCardPresent())
  {
    return;
  }
  //Select one of the cards
  if (!mfrc522.PICC_ReadCardSerial())
  {
    return;
  }
  //Show UID on serial monitor
  Serial.print("UID tag :");
  String content= "";
  byte letter;

  for (byte i = 0; i < mfrc522.uid.size; i++)
  {
     Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
     Serial.print(mfrc522.uid.uidByte[i], HEX);
     content.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
     content.concat(String(mfrc522.uid.uidByte[i], HEX));
  }
  Serial.println();
  Serial.print("Message : ");
  content.toUpperCase();
  if (content.substring(1) == "17 27 C7 A6" || "BA FA 21 28") //change here the UID of the card/cards that you want to give access
  {
    Serial.println("Authorized access");
    Serial.println();
    delay(3000);
  }

 else   {
    Serial.println(" Access denied");
    delay(3000);
  }

  char Data=Bluetooth.read();//Recieves Data from bluetooth and places it in variable 'Data'
  if(Data=='1'){//if data from bluetooth equals to 1(1 recieved from bluetooth IS NOT an integer, it is a char.)
    gateOpenSequence();//Self created function that executes all actions when Gate need to be opened.
  }
  while(digitalRead(DA)==1){         //While recieving characters from keypad.
    int key =digitalRead(D3)*8 + digitalRead(D2)*4 +digitalRead(D1)*2 + digitalRead(D0);//Certain formula used to decipher what key has been pressed
    returnKey(key);//Self created function that translates key deciphered to keypad layout. puts key pressed into variable 'c'
    Serial.print(c);
    if(c!='D') keys[cnt3]=c;

    switch(cnt2){
      case 0:
        if(c!='D'){
          lcd.clear();
          lcd.setCursor(9, 0);
          lcd.print(keys[cnt3]);
          ++cnt3;
          ++cnt2;
          Beep();
          break;
        }
        else break;
      case 1:
        if(c!='D'){
          lcd.setCursor(8,0);
          lcd.print("*");
          lcd.print(keys[cnt3]);
          ++cnt3;
          ++cnt2;
          Beep();
          break;
        }
        else{
          lcd.clear();
          --cnt3;
          --cnt2;
          break;
        }

      case 2:
        if(c!='D'){
          lcd.setCursor(8, 0);
          lcd.print("**");
          lcd.print(keys[cnt3]);
          ++cnt2;
          ++cnt3;
          Beep();
          break;
        }
        else{
          lcd.clear();
          lcd.setCursor(9,0);
          cnt3--;
          cnt2--;
          lcd.print(keys[cnt3-1]);

          break;
        }

      case 3:
        if(c!='D'){
          lcd.setCursor(8, 0);
          lcd.print("***");
          lcd.print(keys[cnt3]);
          ++cnt2;
          ++cnt3;
          Beep();
          break;
        }
        else{
          lcd.clear();
          lcd.setCursor(9,0);
          lcd.print("*");
          cnt3--;
          cnt2--;
          lcd.print(keys[cnt3-1]);
          break;
        }
      case 4:
        if(c!='D'){
          cnt2=0;
          cnt3=0;
        }
        else{
          lcd.clear();
          lcd.setCursor(9, 0);
          lcd.print("**");
          cnt2--;
          cnt3--;
          lcd.print(keys[cnt3-1]);
        }
      break;
    }
    while(digitalRead(DA)==1);//Making sure we wont get double input from one press, forcing the loop to stay there as long as a key is pressed
    if(c!='D'){
      keysPressed[count] = c;//Placing key pressed into an array
      count++;//raising array index
    }
    else{
      keysPressed[count]="";
      count--;
     }
    if (count == 5)//when count reaches 5, meaning array is full check if array 'password' is equal to the 5 keys the user just entered.
    {
      for (int i = 0; i < 5; i++)
      {
        if (password[i] == keysPressed[i])//if keys are the same add one to cnt, if cnt equals to 5, it means all keys were the same
        {
          cnt++;
        }
      }
        if(cnt==5){
          gateOpenSequence();
          cnt=0;
        }
        else{
          wrongPassword();
          cnt=0;
        }
        }
      }
  }

void returnKey(int key)
{
  char arrkey[16]={ '1','2','3','A','4','5','6','B','7','8','9','C','*','0','#','D' };
  c=arrkey[key];

}

void lcdSetup(){
  lcd.setCursor(0,0);
  lcd.write(2);
  lcd.setCursor(1, 0);
  lcd.write(1);
  lcd.setCursor(18,0);
  lcd.write(1);
  lcd.setCursor(19,0);
  lcd.write(2);
  lcd.setCursor(2,0);
  lcd.print("----Welcome-----");
  lcd.setCursor(0,1);
  lcd.print("|  Enter password  |");
  lcd.setCursor(0,2);
  lcd.print("|and then press '#'|");
  lcd.setCursor(0, 3);
  lcd.print("|------------------|");
}
void gateOpenSequence(){
  int start = 0;
  int desired = 105;
  lcd.clear();
  lcd.setCursor(6,0);
  lcd.print("Welcome");
  lcd.setCursor(8,1);
  lcd.print("Home");
  count = 0;
  digitalWrite(buzzer,HIGH);
  while(start<desired){
  servo.write(++start);
  delay(10);
  }
  delay(1000);
  digitalWrite(buzzer,LOW);
  lcdSetup();
  while(start>5){
  servo.write(--start);
  delay(10);
  }

}
void wrongPassword(){
  lcd.clear();
  lcd.setCursor(7,0);
  lcd.print("Wrong");
  lcd.setCursor(6,1);
  lcd.print("Password");
  lcd.setCursor(4, 2);
  lcd.print("Achalta ota");
  count = 0;
  for(int jj=0;jj<3;jj++){
    Beep();
  }
  delay(2000);
  lcdSetup();

}

void Beep(){
  digitalWrite(buzzer,HIGH);
  delay(200);
  digitalWrite(buzzer,LOW);
  delay(200);
}

I will really appreciate help as I can't seem to find any explanations about these two functions:
if (!mfrc522.PICC_IsNewCardPresent())
  {
    return;
  }
  //Select one of the cards
  if (!mfrc522.PICC_ReadCardSerial())
  {
    return;
  }

mfrc522.PICC_IsNewCardPresent()

will check, if a new RFID card/tag was presented to the reader. So if this returns true, you can read the card.
mfrc522.PICC_ReadCardSerial()

will actually read the data from the card/tag, so that the UUID is then available via mfrc522.uid.

Your problem stems from how you are using these functions. Lets have a look at that exact code snippet:
if (!mfrc522.PICC_IsNewCardPresent())
{
    return;
}
//Select one of the cards
if (!mfrc522.PICC_ReadCardSerial())
{
    return;
}

When we translate the first if statement into english we get:
 If no new card is present restart the function `loop()`.

This code snippet is at the start of the function. This means, that you will only read the code below that, if a new card is present and could be read. This logic only works good, if the RFID code is the only thing done in that function, which is not the case for you.
Instead you can restructure your RFID code a bit:
if(mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial()){
    // Handling all RFID code in here
    //Show UID on serial monitor
    Serial.print("UID tag :");
    String content= "";
    byte letter;

    for (byte i = 0; i < mfrc522.uid.size; i++)
    {
        Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
        Serial.print(mfrc522.uid.uidByte[i], HEX);
        content.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
        content.concat(String(mfrc522.uid.uidByte[i], HEX));
    }
    Serial.println();
    Serial.print("Message : ");
    content.toUpperCase();
    if (content.substring(1) == "17 27 C7 A6" || "BA FA 21 28") //change here the UID of the card/cards that you want to give access
    {
        Serial.println("Authorized access");
        Serial.println();
        delay(3000);
    } else {
        Serial.println(" Access denied");
        delay(3000);
    }
}

This will execute the RFID code, if a new card could be read. Otherwise it will just continue with the rest of the code.
Note, that due to the delay(3000) call your code won't react to anything for 3 seconds after a card was presented to the reader. You might wanna ditch that delay in favor of a better responsiveness.


text:
How to connect a NRF24L01 to a Wemos D1 R2
I have troubles to connect a NRF24L01 transceiver to a Wemos D1 R2 board. I succeeded on an Arduino Uno. Does anyone know the pinout?
I used (same as with Uno):
D13 - SCK
D12 - MI
D11 - MO

D8 and D9 for CE and CSN

Code:
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

// NRF24 Radio
#define CE_PIN   'D8'
#define CSN_PIN  'D9'

RF24 radio(CE_PIN, CSN_PIN); // Create a Radio

// NRF24 Radio
radio.begin();
if (!radio.isChipConnected()) {
  Serial.println("ERROR: NRF24 Chip not connected");
} else {
  Serial.println("NRF24 Chip connected");
  radio.setDataRate( RF24_250KBPS );
  radio.setRetries(3,5); // delay, count
  radio.openWritingPipe(slaveAddress);
}

Result:
ERROR: NRF24 Chip not connected
If I use:
#define CE_PIN   8
#define CSN_PIN  9

then Wemos crashes (reboot exception (4)) so I tried with D, but I get a warning, maybe related:
warning: multi-character character constant [-Wmultichar]
   22 | RF24 radio(CE_PIN, CSN_PIN); // Create a Radio
      |            ^~~~~~
 warning: multi-character character constant [-Wmultichar]
   22 | RF24 radio(CE_PIN, CSN_PIN); // Create a Radio

Does anyone knows the pinout? ... pinout of what?

always format error messages as code ... fixed it for you

strings are defined by double quote marks, eg. "abc123" ... single characters are defined by single quote marks, eg. 'e' ... two characters inside single quotes are illegal syntax, eg. 'D8' ... remove the single quotes in the two define statements .... you are doing RF24 radio('D8', 'D9');, when you should be doing RF24 radio(D8, D9);

@jsotola Did not know that. Thanx!

FredV, answers go into the Answer box

@juraj Thanx for teaching me how to use the forum and your answer!

Select Wemos D1 R2/mini in Tools menu in IDE. Then you can use the Dx names of the pins. Don't put them in quotes.
Since D8 is CS pin at the Uno pin 10 location, you can't use it as CE. And because esp8266 has less pin than Atmega328 of Uno, there is no pin D9. I recommend you to use pins D1 and D2 for CE and CSN.
RF24 radio(D1, D2);

Here you can read how the Dx pins are mapped to esp8266 pins and what is the common function of the pins.