message:
What type of Arduino is this?

I found a bunch of Arduinos (seemingly), but I can't identify the type.

I first thought of a **Micro**, but the chip is a MEGA328PAU and the Micro should have a MEGA32U4 instead:

[![Chip of the unknown Arduino][1]][1]

I know it's also not a **Nano**, because the Nano is a bit longer:

[![Comparison of unknown Arduino with Nano][2]][2]

Next, I looked up the [List of Board Specs](https://www.arduino.cc/en/Products/Compare). Based on the chip, the following models remain:

* Lilypad, can easily be excluded due to its shape
* Lilypad SimpleSnap, can easily be excluded due to its shape
* Uno, can easily be excluded due to its size
* Ethernet, can easily be excluded, because of the Ethernet port
* Mini
* Pro
* Pro Mini

So I am left with **Mini**, **Pro Mini** and **Pro**. The back of the board is not very helpful, since it IMHO misses the markers in the silk sceen:

[![Back of the board][3]][3]

It definitely looks like the [**Pro Mini** from Arduino Store](https://store.arduino.cc/arduino-pro-mini), but the Arduino store seems not to offer the Mini and Pro, so I don't have a comparison.

What type of Arduino is this? And, if possible, do you have a visual comparison of the three remaining types?

  [1]: https://i.stack.imgur.com/Bde7D.jpg
  [2]: https://i.stack.imgur.com/0gYyg.jpg
  [3]: https://i.stack.imgur.com/NogdP.jpg

body:
It is a version of Pro Mini.
[here in DIY MORE shop][1]

The Mini has regulator. Power it over RAW pin with 7 to 12 V and measure the Vcc pin if it shows 5v or 3.3 V.

To determine the frequency, look at the resonator (the component next to pin 2).

EDIT: the resonator markings are hard to read and very cryptic. to determine the frequency you could install Sparkfun boards package. There you can select the different variants of Pro Mini. Upload Blink. If the upload is successful and it Blinks in 1 second intervals, you have the right setting.

  [1]: https://www.diymore.cc/products/pro-mini-atmega328-3-3v-5v-16m-replace-atmega128-for-arduino-nano?_pos=6&_sid=8931d4b6d&_ss=r


sender: user

message:
How can I save my float 'ave' on the EEPROM continuously?

How can I save my output continuously to EEPROM? Or is this even possible? Please help me out.

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

    void loop() {
      static unsigned long count = 0;
      static float sum = 0;
      float ave = 0;
      int volt = analogRead(A1);
      float voltage = map(volt, 0, 1023, 0, 2500) / 100.0;
      Serial.print("Voltage: ");
      Serial.println(voltage, 2);
      sum = sum + voltage;
      count++;
      ave = sum / count;
      Serial.print("Average: ");
      Serial.println(ave, 2);
      Serial.println("-----");
      delay(3000);
    }

sender: assistant

body:
It's possible, but it's certainly not advised.

EEPROM has a limited number of writes before it's dead. By writing continuously to the EEPROM you will kill it in no time at all.


body:
The answer is: Read the Arduino Reference and find [EEPROM.put][1]

But your actual problem is that

1) if you write to eeprom every 3 seconds, the Arduino eventually
    won't survive you

2) you eventually rather want to write the sum and the count, in
    your case ?

You should also think about how to initialize from EEPROM after Restart.

Perhaps it's sufficient to save restart values only once after 1 minute / 1 hour / daily if it still changes?

BTW the "Update only if it changed" is already built into the put() method.

  [1]: https://www.arduino.cc/en/Reference/EEPROMPut


message:
Adafruit motorshield v2.3 not working

I want to connect my adafruit motor shield v2.3 to a touch board from bare conductive so that the motor turns when one of the electrodes is touched.

I've tested the touch part and that isn't a problem so i tested the motor shield on my arduino uno. I am using the DCMotorTest example and when uploading it doesn't give any errors. The shield is getting powered, but the motor isn't turning.

The motor does turn when connected to a 9v battery.
The motor doesn't turn when connected to motor shield without external power and VIN jumper connected.enter image description here
The motor doesn't turn when connected to motor shield with external power with and without VIN jumper connected.

```
/*
This is a test sketch for the Adafruit assembled Motor Shield for Arduino v2
It won't work with v1.x motor shields! Only for the v2's with built in PWM
control

For use with the Adafruit Motor Shield v2
----> http://www.adafruit.com/products/1438
*/

#include <Wire.h>
#include <Adafruit_MotorShield.h>

// Create the motor shield object with the default I2C address
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
// Or, create it with a different I2C address (say for stacking)
// Adafruit_MotorShield AFMS = Adafruit_MotorShield(0x61);

// Select which 'port' M1, M2, M3 or M4. In this case, M1
Adafruit_DCMotor *myMotor = AFMS.getMotor(1);
// You can also make another motor on port M2
//Adafruit_DCMotor *myOtherMotor = AFMS.getMotor(2);

void setup() {
  Serial.begin(9600);           // set up Serial library at 9600 bps
  Serial.println("Adafruit Motorshield v2 - DC Motor test!");

  AFMS.begin();  // create with the default frequency 1.6KHz
  //AFMS.begin(1000);  // OR with a different frequency, say 1KHz

  // Set the speed to start, from 0 (off) to 255 (max speed)
  myMotor->setSpeed(150);
  myMotor->run(FORWARD);
  // turn on motor
  myMotor->run(RELEASE);
}

void loop() {
  uint8_t i;

  Serial.print("tick");

  myMotor->run(FORWARD);
  for (i=0; i<255; i++) {
    myMotor->setSpeed(i);
    delay(10);
  }
  for (i=255; i!=0; i--) {
    myMotor->setSpeed(i);
    delay(10);
  }

  Serial.print("tock");

  myMotor->run(BACKWARD);
  for (i=0; i<255; i++) {
    myMotor->setSpeed(i);
    delay(10);
  }
  for (i=255; i!=0; i--) {
    myMotor->setSpeed(i);
    delay(10);
  }

  Serial.print("tech");
  myMotor->run(RELEASE);
  delay(1000);
}
```

https://i.stack.imgur.com/uzsEb.jpg

body:
You have two possibilities of powering the shield according to the adafruit documentation.

A: power the Arduino over the power plug (not the USB plug) of the Arduino and set the VIN jumper.

B: Leave the VIN jumper off and power over the power connector of the shield.

Don't try other possibilities. They may kill the shield or the Arduino.

The reason your motor doesn't turn is because you switched it off
`myMotor->run(RELEASE);`  immediately after you switched it on `myMotor->run(FORWARD);`.


body: I just used a different motor-shield and it works now, thank you all for your replies and research in this!


message:
Is it possible to split project into several folders?

It is possible to split the project into server files. However, it looks like they all must be in the same folder with the.ino file.

Is it possible to split project into several folders? I’ve got several git repositories which I want to use in the same project and I can’t use them as libraries. Each repository must have its own folder…

body:
I will try to give an answer as it is not easy to understand what you mean.

Probably it is also better if you know how the Arduino IDE works, before try to make complex projects.

Short answer:
**Yes, it is possible**

Normally, you have an ino-file, some other files and many libraries. If you want create something for your project, you can just create a folder inside the library folder.

But this is not what you want right?

You can create many folders inside your project and include any header inside your folders just with
`#include "subfolder/yourfile.h"`

The files will not be opened with your Arduino IDE.

You can also create your "mini library", so the compiler will compile it with your project. This library need to be in a subfolder called `src`. At this point it will be converted and compiled for your project.

Simple working example:
**testsub.ino**
```cpp
#include "src/test.h"
Test *test = new Test();
void setup(){
  Serial.print(test->number());
}
void loop(){
}

```

Create a subfolder `src` and place your files:
**test.h**
```cpp
class Test
{
public:
  Test();
  int number();
};
```
and
**test.cpp**
```cpp
#include "test.h"
Test::Test() {
}
int Test::number() {
  return 95;
}
```

If you want another "library", you can create another subfolder called `src`.


message:
expected '}' at end of input

hi i am getting this error, im guessing i have a bracket missing or one in the wrong place.  any help is appreciate, still new at this. thank you

(code bellow)

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

    Adafruit_PWMServoDriver pwm1 = Adafruit_PWMServoDriver(0x40);

    USB Usb;
    XBOXRECV Xbox(&Usb);

    // our servo # counter
    // You can change the value from 0 to 15 (servo 1 through 16)
    uint8_t util1servo = 0;
    uint8_t util2servo = 1;
    uint8_t ldoorservo = 2;
    uint8_t rdoorservo = 7;
    uint8_t sdoorservo = 3;
    uint8_t mdoorservo = 8;

    //Servo limits definition.
    //You will have to figure out which numbers match your servo be carefull with these,
    //it can break your servo if you go beyond the limits. The ones listed here are for my own setup
    #define UTIL1MIN  150 // Close position of the Top Utility arm
    #define UTIL1MAX  310 // Open position of the Top Utility arm
    #define UTIL2MIN  140 // Close position of the Bottom Utility arm
    #define UTIL2MAX  300 // Open position of the Bottom Utility arm
    #define LDOORMIN  390 // Close position of the Left door
    #define LDOORMAX  550 // Open position of the Left door
    #define RDOORMIN  555 // Close position of the Right door
    #define RDOORMAX  360 // Open position of the Right door
    #define SDOORMIN  492 // Close position of the Small door
    #define SDOORMAX  200 // Open position of the Small door
    #define MDOORMIN  550 // Close position of the Mid door
    #define MDOORMAX  380 // Open position of the Mid door

    //Status for each door open/close
    int LDOORSTATUS = 0; // Status 0 = Closed, 1 = Open
    int RDOORSTATUS = 0; // Status 0 = Closed, 1 = Open
    int SDOORSTATUS = 0; // Status 0 = Closed, 1 = Open
    int MDOORSTATUS = 0; // Status 0 = Closed, 1 = Open

    void setup() {

       pwm1.begin();

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

      Wire.begin();

    }

    void loop() {

    //Left door
    if (Xbox.getButtonClick(LEFT, 0)){
      if (Xbox.getButtonPress(R1, 0)) {
        if(LDOORSTATUS == 0){
              for (uint16_t lpulselen = LDOORMIN; lpulselen < LDOORMAX; lpulselen++){
              pwm1.setPWM(ldoorservo, 0, lpulselen); //Open the door
              delay(1);
              }
              LDOORSTATUS = 1;
              }
            else if (LDOORSTATUS == 1){
                 for (uint16_t lpulselen = LDOORMAX; lpulselen > LDOORMIN; lpulselen--){
                 pwm1.setPWM(ldoorservo, 0, lpulselen); //Close the door
                 delay(1);
                 }
                 LDOORSTATUS = 0;
         }

body:
Auto-formatting produced the following - look at your `loop()` function and you'll see the problem:

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

    Adafruit_PWMServoDriver pwm1 = Adafruit_PWMServoDriver(0x40);

    USB Usb;
    XBOXRECV Xbox(&Usb);

    // our servo # counter
    // You can change the value from 0 to 15 (servo 1 through 16)
    uint8_t util1servo = 0;
    uint8_t util2servo = 1;
    uint8_t ldoorservo = 2;
    uint8_t rdoorservo = 7;
    uint8_t sdoorservo = 3;
    uint8_t mdoorservo = 8;

    //Servo limits definition.
    //You will have to figure out which numbers match your servo be carefull with these,
    //it can break your servo if you go beyond the limits. The ones listed here are for my own setup
    #define UTIL1MIN  150 // Close position of the Top Utility arm
    #define UTIL1MAX  310 // Open position of the Top Utility arm
    #define UTIL2MIN  140 // Close position of the Bottom Utility arm
    #define UTIL2MAX  300 // Open position of the Bottom Utility arm
    #define LDOORMIN  390 // Close position of the Left door
    #define LDOORMAX  550 // Open position of the Left door
    #define RDOORMIN  555 // Close position of the Right door
    #define RDOORMAX  360 // Open position of the Right door
    #define SDOORMIN  492 // Close position of the Small door
    #define SDOORMAX  200 // Open position of the Small door
    #define MDOORMIN  550 // Close position of the Mid door
    #define MDOORMAX  380 // Open position of the Mid door

    //Status for each door open/close
    int LDOORSTATUS = 0; // Status 0 = Closed, 1 = Open
    int RDOORSTATUS = 0; // Status 0 = Closed, 1 = Open
    int SDOORSTATUS = 0; // Status 0 = Closed, 1 = Open
    int MDOORSTATUS = 0; // Status 0 = Closed, 1 = Open

    void setup() {

      pwm1.begin();

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

      Wire.begin();

    }

    void loop() {

      //Left door
      if (Xbox.getButtonClick(LEFT, 0)) {
        if (Xbox.getButtonPress(R1, 0)) {
          if (LDOORSTATUS == 0) {
            for (uint16_t lpulselen = LDOORMIN; lpulselen < LDOORMAX; lpulselen++) {
              pwm1.setPWM(ldoorservo, 0, lpulselen); //Open the door
              delay(1);
            }
            LDOORSTATUS = 1;
          }
          else if (LDOORSTATUS == 1) {
            for (uint16_t lpulselen = LDOORMAX; lpulselen > LDOORMIN; lpulselen--) {
              pwm1.setPWM(ldoorservo, 0, lpulselen); //Close the door
              delay(1);
            }
            LDOORSTATUS = 0;
          }


message:
Circuit requirement for Arduino Due custom circuit without the ATMEGA16U2

I would like to create a custom Arduino board based on the Arduino Due. Upon looking at the Due's [schematics][1] under the documentation tab there are some stuff that i do not need and removed them. the last thing that i want removed is the ATMEGA16U2. This part just takes so many components that i want it removed.

I would like to build my code using the arduino IDE and with the 16u2 gone i do not know a way how to upload my codes.

This seems to be possible since under the documentations there is a native usb port of the due that is directly connected to the SAM3X8E,

from here on out im lost what how do i upload my code to the same sam3x8E

Special tools that i have that might be usefull:

 - J-link EDU Mini

 - USB to UART

My Current draft schematics:

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

  [1]: https://store.arduino.cc/usa/due
  [2]: https://i.stack.imgur.com/Wbrep.png

body:
Since you have USB you just connect it to your computer. As long as the flash is blank (use the erase button) it will enter the BOSSA bootloader at powerup and you can use the Arduino IDE to upload the code as normal (or the bossac command line tool).

There are two ways of entering the bootloader:

1. Wipe the flash with the ERASE button (or trigger from 16U2).
2. Open the native port at 1200 baud.

The latter is only possible if you have first programmed the board with a sketch with that ability in it. The most sure-fire way is to include the erase button.

You can either provide a physical button (as shown in the existing schematics) or a simple jumper that can be shorted when erasing is needed.


message:
Stuck in a loop using IR Receiver

I am new to Arduino Programming and I have bought an Arduino UNO , Ultrasonic Sensor (HC-SR04), A Piezo Buzzer, IR Receiver (VS1838B) and a RGB LED....

I wrote a program to Calculate Distance form the Ultrasonic Sensor to an object and a Processing Sketch to Display the results.

Now I want to use the IR Receiver to increase the Distance Threshold which makes the buzzer beep...I mean I want to press 1 in my remote to keep the distance about 5 cm after which the buzzer beeps, and when I press 2 the distance becomes 10 cm and so on...I want to stop everything when I press 0 in my remote...

I have already found out the hex codes of my remote buttons but the program makes the task harder...
Please help me with the program that I have already written :-

```
#include <NewTone.h>
#include <IRremote.h>

const int rec = 9;
IRrecv irrecv(rec);
decode_results results;

#define BUTTON_0 0xFF6897
#define BUTTON_1 0xFF30CF
#define BUTTON_2 0xFF18E7
#define BUTTON_3 0xFF7A85
#define BUTTON_EQ 0xFF906F
#define BUTTON_4 0xFF10EF

const int redPin = 5;
const int greenPin = 6;
const int bluePin = 10;
const int trigPin = 12;
const int echoPin = 11;
const int buzPin = 3;
double duration;
double distanceCm, distanceInch;
double dur;

void setup() {

  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(bluePin, OUTPUT);
  pinMode(buzPin, OUTPUT);
  irrecv.enableIRIn();
  Serial.begin(9600);
}

void loop()
{
  if (irrecv.decode(&results))
  {
    if (results.value != BUTTON_0)
    {

      digitalWrite(trigPin, LOW);
      delayMicroseconds(2);
      digitalWrite(trigPin, HIGH);
      delayMicroseconds(10);
      digitalWrite(trigPin, LOW);

      duration = pulseIn(echoPin, HIGH);
      distanceCm = duration * 0.034 / 2;
      distanceInch = duration * 0.0133 / 2;
      dur = duration / 10000;

      Serial.print(distanceCm);
      Serial.print("  cm ");
      Serial.print("                         ");
      Serial.print(distanceInch);
      Serial.print(" Inch ");
      Serial.print("                         ");
      Serial.print(dur);
      Serial.print(" Seconds");
      Serial.print("\n");
    }

    if (results.value == BUTTON_0)
    {

      noNewTone(buzPin);
      analogWrite(redPin, 0);
      analogWrite(greenPin, 0);
      analogWrite(bluePin, 0);
    }

    if (results.value == BUTTON_1)
    {

      if (distanceCm <= 5)
      {
        NewTone(buzPin, 2000);
        analogWrite(redPin, 255);
        analogWrite(greenPin, 0);
        analogWrite(bluePin, 0);
      }
      else if (distanceCm <= 10 && distanceCm > 5)
      {
        noNewTone(buzPin);
        analogWrite(redPin, 0);
        analogWrite(greenPin, 0);
        analogWrite(bluePin, 255);
      }
      else
      {
        noNewTone(buzPin);
        analogWrite(redPin, 0);
        analogWrite(greenPin, 255);
        analogWrite(bluePin, 0);
      }

    }

    if (results.value == BUTTON_2)
    {

      if (distanceCm <= 10)
      {
        NewTone(buzPin, 2000);
        analogWrite(redPin, 255);
        analogWrite(greenPin, 0);
        analogWrite(bluePin, 0);
      }
      else if (distanceCm <= 20 && distanceCm > 10)
      {
        noNewTone(buzPin);
        analogWrite(redPin, 0);
        analogWrite(greenPin, 0);
        analogWrite(bluePin, 255);
      }
      else
      {
        noNewTone(buzPin);
        analogWrite(redPin, 0);
        analogWrite(greenPin, 255);
        analogWrite(bluePin, 0);
      }

    }

    if (results.value == BUTTON_3)
    {

      if (distanceCm <= 30)
      {
        NewTone(buzPin, 2000);
        analogWrite(redPin, 255);
        analogWrite(greenPin, 0);
        analogWrite(bluePin, 0);
      }
      else if (distanceCm <= 50 && distanceCm > 30)
      {
        noNewTone(buzPin);
        analogWrite(redPin, 0);
        analogWrite(greenPin, 0);
        analogWrite(bluePin, 255);
      }
      else
      {
        noNewTone(buzPin);
        analogWrite(redPin, 0);
        analogWrite(greenPin, 255);
        analogWrite(bluePin, 0);
      }

    }

    if (results.value == BUTTON_4)
    {

      if (distanceCm <= 100)
      {
        NewTone(buzPin, 2000);
        analogWrite(redPin, 255);
        analogWrite(greenPin, 0);
        analogWrite(bluePin, 0);
      }
      else if (distanceCm <= 200 && distanceCm > 100)
      {
        noNewTone(buzPin);
        analogWrite(redPin, 0);
        analogWrite(greenPin, 0);
        analogWrite(bluePin, 255);
      }
      else
      {
        noNewTone(buzPin);
        analogWrite(redPin, 0);
        analogWrite(greenPin, 255);
        analogWrite(bluePin, 0);
      }

    }
    irrecv.resume();
  }
}
```

I am using the "IRremote.h" and "NewTone.h" Libraries....

The main problem is that the "irrecv.resume();" pauses the program and waits for the IR input but I want the program to run continuously till I give an IR Input...

I request you to help me with the program.

---

I edited my program to this and this worked:-

```
#include <NewTone.h>
#include <IRremote.h>

const int rec = 2;
IRrecv irrecv(rec);
decode_results results;

#define BUTTON_0 0xFF6897
#define BUTTON_1 0xFF30CF
#define BUTTON_2 0xFF18E7
#define BUTTON_3 0xFF7A85
#define BUTTON_EQ 0xFF906F
#define BUTTON_4 0xFF10EF

const int redPin = 5;
const int greenPin = 6;
const int bluePin = 10;
const int trigPin = 12;
const int echoPin = 11;
const int buzPin = 3;
double duration;
double distanceCm, distanceInch;
double dur;

void setup() {

  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(bluePin, OUTPUT);
  pinMode(buzPin, OUTPUT);
  Serial.begin(9600);
  irrecv.enableIRIn();
}

void loop()
{
  if (irrecv.decode(&results))
  {

    do
    {
      if (results.value == BUTTON_0)

      {

        noNewTone(buzPin);
        analogWrite(redPin, 0);
        analogWrite(greenPin, 0);
        analogWrite(bluePin, 0);
      }

      if (results.value == BUTTON_1)
      {
        sonic();

        if (distanceCm <= 5)
        {
          red();
        }
        else if (distanceCm <= 10 && distanceCm > 5)
        {
          blue();
        }
        else
        {
          green();
        }

      }

      if (results.value == BUTTON_2)
      {
        sonic();
        if (distanceCm <= 10)
        {
          red();
        }
        else if (distanceCm <= 20 && distanceCm > 10)
        {
          blue();
        }
        else
        {
          green();
        }
      }

      if (results.value == BUTTON_3)
      {
        sonic();
        if (distanceCm <= 30)
        {
          red();
        }
        else if (distanceCm <= 50 && distanceCm > 30)
        {
          blue();
        }
        else
        {
          green();
        }
      }

      if (results.value == BUTTON_4)
      {
        sonic();
        if (distanceCm <= 100)
        {
          red();
        }
        else if (distanceCm <= 200 && distanceCm > 100)
        {
          blue();
        }
        else
        {
          green();
        }

      }
    }
    while (digitalRead(rec) == 1);

    irrecv.resume();
  }
}

void sonic()
{
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);

  duration = pulseIn(echoPin, HIGH);
  distanceCm = duration * 0.034 / 2;
  distanceInch = duration * 0.0133 / 2;
  dur = duration / 10000;

  Serial.print(distanceCm);
  Serial.print("  cm ");
  Serial.print("                         ");
  Serial.print(distanceInch);
  Serial.print(" Inch ");
  Serial.print("                         ");
  Serial.print(dur);
  Serial.print(" Seconds");
  Serial.print("\n");
}

void green()
{
  noNewTone(buzPin);
  analogWrite(redPin, 0);
  analogWrite(greenPin, 255);
  analogWrite(bluePin, 0);
}

void blue()
{
  noNewTone(buzPin);
  analogWrite(redPin, 0);
  analogWrite(greenPin, 0);
  analogWrite(bluePin, 255);
}

void red()
{
  NewTone(buzPin, 2000);
  analogWrite(redPin, 255);
  analogWrite(greenPin, 0);
  analogWrite(bluePin, 0);
}

```

But now the problem is I need to press the IR Remote button two times because when I press once the program moves to the `irrecv.resume();` command and waits for another IR Input and I need to press the button again.

Can this be solved (with only one press)?

body:
 1. You really should use switch-case.
 2. irrecv.resume() does not halt the code.

Your program is running fine. It seems like you want to make sensor readings continuously and act only when you press the button. Am I right?


body:
Your code becomes more readable, if you use functions with return values.

For example, something like this structure

    unsigned int limit; // 0 = off, else limit in cm  ...
    void loop() {
      if (irrecv.decode(&results)) {
          byte key = getIRKey(results.value); // 0 , 1, 2, etc.,  0xFF for unknown
          irrecv.resume();
          switch (key) {
             case 0: limit = 0; break;
             case 1: limit = 5; break;
             ...
             default: break; // wrong key does not change limit
          }
      }
      if (limit) {
         unsigned int dist = sonic(); // returns the measured distance or 0
         if (dist && dist < limit) NewTone(buzPin, 2000);
         else noNewTone(buzPin); // off: too far
      } else noNewTone(buzPin); // off: no check
    }

This code should not block. Have fun modifying sonic() and creating the other helper function.


message:
Digispark ATtiny 85 erases flash after power loss

I have some issues with my Digispark ATtiny85 board.
If I upload the blink sketch for example the LED starts blinking and everything looks fine. But as soon as I unplug the Digispark from the USB port and plug it back in nothing happens. I know that the programm starts with a delay of 5 seconds so programming via USB becomes possible, but still nothing. Its seems like the flash-memory (where the programm is stored) of the ATtiny 85 is empty.

Here is the example blink sketch:
```
// the setup routine runs once when you press reset:
void setup() {
  // initialize the digital pin as an output.
  pinMode(0, OUTPUT); //LED on Model B
  pinMode(1, OUTPUT); //LED on Model A
}

// the loop routine runs over and over again forever:
void loop() {
  digitalWrite(0, HIGH);   // turn the LED on (HIGH is the voltage level)
  digitalWrite(1, HIGH);
  delay(1000);               // wait for a second
  digitalWrite(0, LOW);    // turn the LED off by making the voltage LOW
  digitalWrite(1, LOW);
  delay(1000);               // wait for a second
}
```

I also tried uploading the sketch from a Laptop running on Windows but without success.

I am using Linux Mint and Arduino IDE 1.8.10.

Since I am new to Microcontrollers, I would be grateful for explainations, tipps or useful links.
Thank you!

body:
I got the same issue, on two boards. Will probably try to burn the bootloader using usbasp, maybe they burned the wrong one back in china.

EDIT:

As expected flashing the micronucleus bootloader using USBasp solved the problem on both of the boards. I've used burn-o-mat as the arduino was not seeing my programmer.

Just download the firmware from github (I've used this: https://github.com/f4goh/micronucleus/archive/master.zip )

and connect like so (here the guy is using arduino uno, doesn't matter): https://hamprojects.wordpress.com/2018/12/27/digispark-microcontrollers-implementation/


message:
High-frequency PWM on an Adafruit Feather M0

I'm trying to get a Bluefruit Feather M0, which has a SAMD21G on it, to do high-frequency  PWM by accessing timer registers directly, rather than using the Arduino API to do PWM at ~1 kHz or ~500 Hz. Actual frequency isn't important at this stage, I just want a lot more than 1 kHz.

I found an [example][1] for an MKR1000, based on a similar processor. I've adapted it as shown below. Comparing the [Adafruit pinout][2] with the original code and with the [datasheet][3], it's apparent that the pin numberings are different and that pin 11, which is the only one of the two example pins that is accessible, is on TCC0 here and not TCC1.

The only change I see that I needed to make is to duplicate all the TCC1 setup in `setupTimers()` and the TCC1 duty cycle control in `loop()` for TCC0. Yet on the scope, I see no PWM output. I then tried setting pin 13 to PWM as well, so I'd see it on the on board LED. Still nothing. I'm somewhat stuck now.

Does anyone have any ideas?

    void setup() {
     // put your setup code here, to run once:
     setupTimers();
     Serial.begin(9600);
    }

    void loop() {
     // put your main code here, to run repeatedly:
     int t = 0;
     Serial.println("\nRunning PWM 0 to 100%");
     for (t = 0; t < 1000; t = t + 1) {
      REG_TCC1_CC1 = t;                              // TCC1 CC1 - on D3  - PWM signalling
      while (TCC1->SYNCBUSY.bit.CC1);                // Wait for synchronization
      REG_TCC0_CC1 = t;                              // TCC1 CC1 - on D3  - PWM signalling
      while (TCC0->SYNCBUSY.bit.CC1);                // Wait for synchronization
      delay(1);
      Serial.print(".");
     }

     delay(2000);
    }

    // Output PWM 24Khz on digital pin D3  and D11 using timer TCC1 (10-bit resolution)
    void setupTimers() {
     REG_GCLK_GENDIV = GCLK_GENDIV_DIV(1) |          // Divide the 48MHz clock source by divisor N=1: 48MHz/1=48MHz
      GCLK_GENDIV_ID(4);            // Select Generic Clock (GCLK) 4
     while (GCLK->STATUS.bit.SYNCBUSY);              // Wait for synchronization

     REG_GCLK_GENCTRL = GCLK_GENCTRL_IDC |           // Set the duty cycle to 50/50 HIGH/LOW
      GCLK_GENCTRL_GENEN |         // Enable GCLK4
      GCLK_GENCTRL_SRC_DFLL48M |   // Set the 48MHz clock source
      GCLK_GENCTRL_ID(4);          // Select GCLK4
     while (GCLK->STATUS.bit.SYNCBUSY);              // Wait for synchronization

     // Enable the port multiplexer for the digital pin D3 and D11  **** g_APinDescription() converts Arduino Pin to SAMD21 pin
     PORT->Group[g_APinDescription[3].ulPort].PINCFG[g_APinDescription[3].ulPin].bit.PMUXEN = 1;
     PORT->Group[g_APinDescription[11].ulPort].PINCFG[g_APinDescription[11].ulPin].bit.PMUXEN = 1;
     PORT->Group[g_APinDescription[13].ulPort].PINCFG[g_APinDescription[13].ulPin].bit.PMUXEN = 1;

     // Connect the TCC1 timer to digital output D3 and D11 - port pins are paired odd PMUO and even PMUXE
     // F & E specify the timers: TCC0, TCC1 and TCC2
     PORT->Group[g_APinDescription[2].ulPort].PMUX[g_APinDescription[2].ulPin >> 1].reg = PORT_PMUX_PMUXO_E;  // D3 is on PA11 = odd, use Device E on TCC1/WO[1]
     PORT->Group[g_APinDescription[11].ulPort].PMUX[g_APinDescription[11].ulPin >> 1].reg = PORT_PMUX_PMUXE_F; // D11 is on PA08 = even, use device F on TCC1/WO[0]
     PORT->Group[g_APinDescription[13].ulPort].PMUX[g_APinDescription[13].ulPin >> 1].reg = PORT_PMUX_PMUXE_E; // Try the LED.. doesn't work with E or F

     //Actually, pin 11 on the Feather is on PA16. Still even, not sure of the significance, but it's now TCC0/WO[6] and still port F.
     //All the stuff further down is about TCC1!

     // Feed GCLK4 to TCC0 and TCC1
     REG_GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN |         // Enable GCLK4 to TCC0 and TCC1
      GCLK_CLKCTRL_GEN_GCLK4 |     // Select GCLK4
      GCLK_CLKCTRL_ID_TCC0_TCC1;   // Feed GCLK4 to TCC0 and TCC1
     while (GCLK->STATUS.bit.SYNCBUSY);              // Wait for synchronization

     // Dual slope PWM operation: timers countinuously count up to PER register value then down 0
     REG_TCC1_WAVE |= TCC_WAVE_POL(0xF) |           // Reverse the output polarity on all TCC0 outputs
      TCC_WAVE_WAVEGEN_DSBOTH;     // Setup dual slope PWM on TCC0
     while (TCC1->SYNCBUSY.bit.WAVE);               // Wait for synchronization

     // Each timer counts up to a maximum or TOP value set by the PER register,
     // this determines the frequency of the PWM operation: Freq = 48Mhz/(2*N*PER)
     REG_TCC1_PER = 1000;                           // Set the FreqTcc of the PWM on TCC1 to 24Khz
     while (TCC1->SYNCBUSY.bit.PER);                // Wait for synchronization

     // Set the PWM signal to output , PWM ds = 2*N(TOP-CCx)/Freqtcc => PWM=0 => CCx=PER, PWM=50% => CCx = PER/2
     REG_TCC1_CC1 = 500;                             // TCC1 CC1 - on D3  50%
     while (TCC1->SYNCBUSY.bit.CC1);                   // Wait for synchronization
     REG_TCC1_CC0 = 500;                             // TCC1 CC0 - on D11 50%
     while (TCC1->SYNCBUSY.bit.CC0);                   // Wait for synchronization

     // Divide the GCLOCK signal by 1 giving  in this case 48MHz (20.83ns) TCC1 timer tick and enable the outputs
     REG_TCC1_CTRLA |= TCC_CTRLA_PRESCALER_DIV1 |    // Divide GCLK4 by 1
      TCC_CTRLA_ENABLE;             // Enable the TCC0 output
     while (TCC1->SYNCBUSY.bit.ENABLE);              // Wait for synchronization

     //Do everything again for TCC0

     // Dual slope PWM operation: timers countinuously count up to PER register value then down 0
     REG_TCC0_WAVE |= TCC_WAVE_POL(0xF) |           // Reverse the output polarity on all TCC0 outputs
      TCC_WAVE_WAVEGEN_DSBOTH;     // Setup dual slope PWM on TCC0
     while (TCC0->SYNCBUSY.bit.WAVE);               // Wait for synchronization

     // Each timer counts up to a maximum or TOP value set by the PER register,
     // this determines the frequency of the PWM operation: Freq = 48Mhz/(2*N*PER)
     REG_TCC0_PER = 1000;                           // Set the FreqTcc of the PWM on TCC1 to 24Khz
     while (TCC0->SYNCBUSY.bit.PER);                // Wait for synchronization

     // Set the PWM signal to output , PWM ds = 2*N(TOP-CCx)/Freqtcc => PWM=0 => CCx=PER, PWM=50% => CCx = PER/2
     REG_TCC0_CC1 = 500;                             // TCC1 CC1 - on D3  50%
     while (TCC0->SYNCBUSY.bit.CC1);                   // Wait for synchronization
     REG_TCC0_CC0 = 500;                             // TCC1 CC0 - on D11 50%
     while (TCC0->SYNCBUSY.bit.CC0);                   // Wait for synchronization

     // Divide the GCLOCK signal by 1 giving  in this case 48MHz (20.83ns) TCC1 timer tick and enable the outputs
     REG_TCC0_CTRLA |= TCC_CTRLA_PRESCALER_DIV1 |    // Divide GCLK4 by 1
      TCC_CTRLA_ENABLE;             // Enable the TCC0 output
     while (TCC0->SYNCBUSY.bit.ENABLE);              // Wait for synchronization
    }

  [1]: https://www.hackster.io/voske65/high-speed-pwm-on-arduino-atsamd21-859b06
  [2]: https://cdn-learn.adafruit.com/assets/assets/000/046/245/original/adafruit_products_Feather_M0_Bluefruit_v2.2-1.png?1504885440
  [3]: http://ww1.microchip.com/downloads/en/DeviceDoc/SAMD21-Family-DataSheet-DS40001882D.pdf

body:
For your specific problem: the Feather's `D11` is the SAMD's `PA16` and on `TCC0/WO[6]` (use `REG_TCC0_CCB2` and `PORT_PMUX_PMUXE_F`), and also on `TCC2/WO[0]` (use `REG_TCC2_CCB0` and `PORT_PMUX_PMUXE_E`).

An easier way: I have made a high-frequency-PWM library for this (called [Arduino_SAMD21_turbo_PWM][1]), and I have implemented the pin table for the Adafruit Feather M0.

I haven't tested it though, mainly because I don't have an Adafruit Feather M0. Still, feel free to have a try.

The pin mapping table itself for the Adafruit Feather M0, which AFAIK has the same pin mappings as the Arduino Zero, is [here][2] on Github; maybe it can help as well.

  [1]: https://github.com/ocrdu/Arduino_SAMD21_turbo_PWM
  [2]: https://github.com/ocrdu/Arduino_SAMD21_turbo_PWM/blob/master/extras/pintables.txt


message:
Only print when the button is pressed and not being pressed anymore

I have an Arduino and a [microswitch][1] that I want to use to know when the switch is initially being pressed (get "OnsetTime" on Serial) and when the switch is not being pressed anymore (get "OffsetTime" on Serial).

Imagine a bird sitting on the switch. I want to get an output "OnsetTime" when the bird first sits on the switch and an output "OffsetTime" when the bird flies away from the switch.

Right now, I have an output that constantly prints out "OnsetTime" when the switch is pressed.
I would appreciate it if anybody can help me figure out how can I implement the below code to get the outputs only when the switch is initially pressed and not being pressed anymore.

    void setup() {
      pinMode(7, INPUT);
      Serial.begin(9600);
    }

    void loop() {
      if (digitalRead(7) == HIGH) {
        Serial.println("OnsetTime");
        }
    }
        //Serial.println("GetOffsetTime");

  [1]: https://uk.rs-online.com/web/p/microswitches/1594590/

body:
If you want to be simple, you can use [this library][1]. The code will be

    #include <ezButton.h>

    ezButton button(7);  // create Button object that attach to pin 7;

    void setup() {
      Serial.begin(9600);
      button.setDebounceTime(100); // set debounce time to 100 milliseconds
    }

    void loop() {
      button.loop(); // MUST call the loop() function first

      if(button.isPressed())
        Serial.println("OnsetTime");

      if(button.isReleased())
        Serial.println("GetOffsetTime");
    }
If you want to understand in depth, You can see the code and instruction in [this tutorial][2]

  [1]: https://www.arduinolibraries.info/libraries/ez-button
  [2]: https://arduinogetstarted.com/tutorials/arduino-button#content_modifying_arduino_code


body:
You can save the value of the switch read to compare it on the next loop. This way you're able to detect changes.

    int lastValue;

    void setup() {
      pinMode(7, INPUT);
      lastValue= digitalRead(7);

      Serial.begin(9600);
    }

    void loop() {
      int currentValue = digitalRead(7);
      if (lastValue != currentValue) {
        lastValue = currentValue;

        if (currentValue == HIGH) {
          Serial.println("OnsetTime");
        } else {
          Serial.println("OffsetTime");
        }
      }
    }

Please be aware that switches bounce. If you see multiple messages at each mechanical change, insert a `delay(...)`.


message:
What is ECC608 crypto chip accelerator used for in Arduino Uno Wifi rev2?

[Arduino Uno Wifi rev2][1] includes an ECC608 crypto accelerator chip.

Even their documentation states "As for the WiFi connection, that's made secure with the new ECC608 crypto chip accelerator."

My question is: **how exactly the ECC608 is used?** I'd like to see the sources the Arduino makes the "WiFi secure" with it.

  [1]: https://store.arduino.cc/arduino-uno-wifi-rev2

body:
The library for the chip is [ArduinoECCX08][1]. It is used by the [ArduinoBearSSL][2] library. The ArduinoBearSSL is used by the [ArduinoIoTCloud
][3] library and [Arduino_OAuth][4] library.
.

  [1]: https://github.com/arduino-libraries/ArduinoECCX08
  [2]: https://github.com/arduino-libraries/ArduinoBearSSL
  [3]: https://github.com/arduino-libraries/ArduinoIoTCloud
  [4]: https://github.com/arduino-libraries/Arduino_OAuth


message:
PC not recognizing Arduino when working with a class and MIDIUSB library

I've recently bought an Arduo Due to create some sort of a Midi controller together with the MIDIUSB library.

I have create a simple a test program with 1 potentiometer (without the use of a class) to test the MIDIUSB library and everything works fine, so I decided to expanded my program to make it work with more than 1 potentiometer (with the use of a class).

However my pc stopped recognizing my Arduino as a MIDI device with my updated code. When I upload my previous example code it all works fine. I get no compile errors or whatsoever.
I don't understand what I'm doing wrong.
If anybody could explain me what I'm doing wrong or could give me a solution you would be a hero since I can't really work further if this issue doesn't get resolved.
Thanks!

Here is my code for Custom_MIDI_controller_V2.ino:

    #include "MIDIUSB.h"
    #include "Class.h"
    #define TOLERANCE 8

    byte NUMBER_POTS = 5;

    Pot PO0(A0, 1, 14);
    Pot PO1(A1, 1, 15);
    Pot PO2(A2, 1, 16);
    Pot PO3(A3, 1, 17);
    Pot PO4(A4, 1, 18);

    Pot *POTS[] = {&PO0, &PO1, &PO2, &PO3, &PO4};

    void setup() {

    }

    void loop() {
      for (int i = 0; i < NUMBER_POTS; i++) {
        int potValue = POTS[i]->getValue();
          if(potValue != 255) {
            controlChange(POTS[i]->_channel, POTS[i]->_control, potValue);
            MidiUSB.flush();
          }
       }
    }

    void controlChange(byte channel, byte control, byte value) {
      midiEventPacket_t event = {0x0B, 0xB0 | channel, control, value};
      MidiUSB.sendMIDI(event);
    }

Here is my Class.cpp code:

    #include "Arduino.h"
    #include "Class.h"

    #define TOLERANCE 8

    Pot::Pot(int pin, int channel, int control) {
      _pin = pin;
      _channel = channel;
      _control = control;
      _value = analogRead(_pin);
      _oldValue = _value - 10;
    }

    int Pot::getValue() {
      int diff = abs(_value - _oldValue);
      if(diff > TOLERANCE)
      {
        _oldValue = _value;
        return map(_value, 0, 1023, 127, 0);
      } else {
        return 255;
      }
    }

And this is my header Class.h code:

    #ifndef Class_h
    #define Class_h
    #include "Arduino.h"

    class Pot
    {
      public:
        Pot(int pin, int channel, int control);
        int getValue();
        int _pin;
        int _channel;
        int _control;
        int _value;
        int _oldValue;
    };

    #endif

body:
You need to take care with constructors in C++.  They get called during the global variable initialisation phase of the execution, which happens before `main()` gets called.

`main()` calls the routines that initialise and configure the peripherals and such in the chip, and by having `analogRead()` in your constructor (which is itself another error I will mention below) there is a good chance (I don't know the full initialisation sequence of that chip though) that it will never complete, and thus your program hangs at that point.

Your `analogRead()` doesn't want to be in the constructor, anyway, since that will only execute once when the object is constructed.  Instead you want to have `analogRead()` called at the point you need to get the analog value. In your code that would be at the start of `int Pot::getValue()`.


message:
Controlling Multiple Brushless Motors with Arduino

I'm working on making an FPV racing drone as an introductory project to using Arduino. I need to be able to control four brushless motors using an Arduino Uno.

First of all, does anyone have any recommendations for motor type and ESC type? But my real question is: how can I power all four motors using one battery? What components do I need to buy? I've tried searching the internet for the answer but I can't find my specific use case, although it doesn't seem like it's uncommon at all.

body:
Arduino really isn't the best processor for a drone. It can certainly be done however. You can [buy a MultiWii flight controller][1] which is based around an Arduino Mega and functions as a drone flight controller.

You can't just ask which motors and ESCs to use. How heavy is your drone? How fast does it need to fly? Is there a payload? To figure out which motors to use, go watch some videos by FliteTest or a multitude of other videos online suggesting how to build a drone. You can certainly power everything off one battery. Again, watch some videos on how multirotor drones are made.

Takeway: An Arduino is a very poor choice for making a flight controller, and there quite a few components needed to build a drone, so watch some videos and learn how!

  [1]: https://www.readytoflyquads.com/multiwii-pro-flight-controller


message:
Arduino Uno & Wemos (0.66” Across) OLED Shield

As I wrote in title, I have Arduino Uno and Wemos (0.66” Across) OLED Shield which i bought along wemos d1 mini.

For some reason I want to use it with uno. but there are just 0.96 tutorials internet and I don't know which pins to connect. I would appreciate any help.

PINS UNDER blue stick are

TX
RX
D1
D2
D3
so on..

[![Wemos (0.66” Across) OLED Shield -- Driver IC: SSD1306 (I2C Address: 0x3C or 0x3D)][1]][1]

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

body:
The first thing I see when googling "0.66 lolin oled" is the link to https://wiki.wemos.cc/products:d1_mini_shields:oled_shield and their [Get started guide](https://wiki.wemos.cc/tutorials:shields:get_started_with_oled_shield). This yields the libraries to be used with it:

* for the OLED: https://github.com/mcauser/Adafruit_SSD1306/tree/esp8266-64x48 with the dedicated [test sketch](https://github.com/mcauser/Adafruit_SSD1306/blob/esp8266-64x48/examples/ssd1306_64x48_i2c/ssd1306_64x48_i2c.ino)
* for the A & B buttons: https://github.com/wemos/LOLIN_OLED_I2C_Button_Library


message:
1.7MHz Square wave generator

const uint8_t OUTPUT_PIN = 3;  // = OC2B
    const uint8_t PERIOD = 9;      // 9 CPU cycles ~ 1.778 MHz

    void setup()
    {
        pinMode(OUTPUT_PIN, OUTPUT);
        TCCR2B = 0;           // stop timer
        TCNT2  = 0;           // reset timer
        TCCR2A = _BV(COM2B1)  // non-inverting PWM on OC2B
               | _BV(WGM20)   // fast PWM mode, TOP = OCR2A
               | _BV(WGM21);  // ...ditto
        TCCR2B = _BV(WGM22);  // ...ditto
        OCR2A = PERIOD - 1;
        OCR2B = PERIOD/2 - 1;
    }

    void soundBuzzer() {
        TCCR2B |= _BV(CS20);  // F_CPU / 1
    }

    void silenceBuzzer() {
        TCCR2B &= ~_BV(CS20);
        TCNT2 = 0;
    }

[I got it from here, look down to the answers][1]

This program supposed to generate a square-wave of frequency around 1.7MHz but it is not working for me. I have tried the simulation on Proteus 8 and there is no output. Only one error shows during the compilation which is the 'loop' function is missing, I have added one and still there is no output. Please somebody help me.

  [1]: https://arduino.stackexchange.com/questions/37613/generate-1-7-mhz-with-pwm-in-uno

body:
In the `setup` there is some settings for timer2, but no change of prescaller, so the timer stays stopped.

Obviously it was started by calling `soundBuzzer()` somewhere in code. But this function name is now kinda misleading. Just set prescaller in the `setup` and it should be working.


message:
Servomotor AND Button

I am having trouble trying to make servomotor and button work together. The button code here below works fine when alone in a separate code but when it is transferred to the code with the servomotor function in it, it doesn't work.

Is there anything I need to be wary of when integrating the button code here to the preexisting code?

```
#include <Servo.h> // Library required for the servomotor (Make sure to download)
#include <Button.h> // Library required for the microswitch (Make sure to download)

// Parameters for the experiment
// Note: 1000 is one second
char Experiment = 'Acclimatization';
char Bird_Name = 'birdname here';
int Frequency = 30 * 1000; // The motor moves every x seconds
int Frequency_Deviation = 5 * 1000; // There are x second deviations plus and minus from the frequency set above
int Duration = 3 * 1000;  // The food is uncovered for x seconds

int servoPin = 9; // Declare the servomotor pin (Can be varied from setup to setup)
Button button(7); // Declare the microswitch pin (Can be varied from setup to setup)

Servo Servo1;

void setup() {
   Servo1.attach(servoPin);
   //analogWrite(servoPin, 0);
   Serial.begin(9600);
   button.setDebounceTime(100); // set debounce time to 100 milliseconds
}

void loop(){
   // Get onset and offset times of when the bird arrives and leaves the perch
   button.loop();
   if(button.isPressed())
    Serial.println("OnsetTime");
   if(button.isReleased())
    Serial.println("OffsetTime");

   // Calculate the acclimatization parameters below
   delay(random(Frequency-Frequency_Deviation,Frequency+Frequency_Deviation)); // Calculates frequency (See paramaters above)
   Servo1.write(0); // Starts from 0 degrees
   delay(Duration); // Duration that the food is uncovered (See parameters above)
   Servo1.write(75); // Goes to the x degrees
}
```

body:
Short answer: You have a blocking delay interrupting your button debounce time of 100ms.

Your button library has a debounce time of 100ms. This means you must be holding the button down for more that 100ms before it will register as pressed.

You have a 3 second blocking delay at the end of your loop. When you call `delay(XX)`, your processor *cannot do anything* during this time (like check for a button), it's just waiting.

Think about how the code is running. In your main loop, you are calling the function `button.loop()`, and it's checking to see if your button is pressed. If it's pressed, it's starts a timer (your debounce). The goal of this timer is for another 100ms to pass by with your button still being pressed to make sure you actually pressed it. `Button.isPressed()` fails, and it moves to its next set of instructions, which is move the servo and wait 3 seconds, during which time it *cannot check the button*. Then it starts all over again, and it calls `button.loop()` again. This all happens MUCH faster than 100ms. From the start of `void loop()` to the time it takes for it to wind back up at the 3 second blocking delay is in the nano seconds. This never gives your button library the 100ms of "pressed down" button it needs for `button.isPressed()` to return true.

I suggest spending some time looking at the behind the scenes of your button library and see how the debounce works. You can do that, or you can use the example debounce sketch off the main arduino website and learn how that works. The next thing you'd want to do is to learn how to make your code "wait" without using the blocking call `delay()`. This is done by using timers with millis(). A good way to learn this is the example arduino sketch "Blink Without Delay".

Hope that clears some things up.


message:
How to connect accelerometer, GPS, microphone and a GSM module to a Arduino?

I am a noob in the Arduino world and have only started reading about it. I have zero experience with Arduino some suggestions to increase my level will also be highly appreciated. But I have a lot of ideas, I want to work on.

I want to measure the velocity and noise levels with the GPS coordinates of a moving vehicle and send it to my phone using gsm or wifi.
Should I include a small LCD also? again suggestions will be highly appreciated.

body:
It depends.

If you are a beginner, do it in steps:

- Get an Arduino Uno
- Get a feeling for MCUs connecting a LED and resistor.
- Connect the buzzer and get it working.
- Disconnect it, connect the display and get it working.
- Same for one sensor.
- Than try multiple sensors.
- Than play with the WIFI module.
- Than combine everything.

The key is to split up your (for a beginner) big project into smaller easier to handle projects.

If you want to add an LCD, depends fully on YOUR requirements; we don't know exactly what you want. If you send all data via WIFI in principle the receiver can display it, but maybe you have a good reason to display it on a display.


message:
Lock screen if I leave my seat?

Background: I change the job and in the new company you need to pay pizza for the whole team if you forget to lock your screen :-)

I want it to be automated: I walk away and the screen should lock. No additional action should be required. Keyboard shortcuts, special mouse movements or unplugging devices from USB are not valid solutions.

How could this be solved (with or without arduino)?

Please write slowly, I never worked with sensors or arduino before :-)

I need this for Mac and Ubuntu.

body:
A single [distance sensor][1], properly placed, should be enough to detect when you leave. That's the arduino part.

With python you can then use the serial over USB [to read the output from the arduino][2]. And run the command to activate the screen lock, according to your reading.

  [1]: https://create.arduino.cc/projecthub/MisterBotBreak/how-to-use-an-ultrasonic-sensor-181cee
  [2]: https://riptutorial.com/arduino/example/22868/first-serial-communication-between-arduino-and-python


body: RFID (NFC) might be the way to go.  Have an RFID tag in a wristband and an RFID reader by the side of (or under) your keyboard. As long as you keep your hands close to the keyboard the RFID reader should detect your wristband. When it doesn't sense it for a pre-defined period of time send a signal to the PC to trigger it to lock. It could then trigger the unlock when your wristband is back in range again.


body:
If you chair has a gas cylinder to adjust height, it sinks a bit when sat in. My dip is about a centimeter. That's more than enough for a beam-interruption or reflection sensor, a hall effect sensor, or even a dead-simple magnetic reed switch, like those used by home alarms to monitor windows.

You could have the reed switch turn on/wake up a micro like an ESP8266, which uses ESP-NOW to talk to another ESP plugged into a usb serial on the desktop. Once the message is sent, the micro can go into deep sleep. The desktop's serial port is read by the lang of your choice; node.js, python, c#, etc, and runs a command or fires a key combo to lock the workstation.


body:
Sorry, no Arduino required, but you probably already have a web cam on your desktop. If you don't mind being observed like Schrodinger's Cat, you can use a small utility like [YawCam][1] in [Windows][2] or [Motion][3] on [Linux][4] to trigger the screen lock when you are no longer visible at your console.

  [1]: https://www.yawcam.com/
  [2]: https://www.maketecheasier.com/use-the-webcam-as-surveillance-camera
  [3]: https://motion-project.github.io/
  [4]: https://www.maketecheasier.com/setup-motion-detection-webcam-ubuntu/


body:
Place a ultrasonic distance sensor HC-05 close to your monitor, facing towards your chest. Check the distance measured against a defined threshold (potentiometer?) and send a key press to your PC to lock it if it is exceeded.

I can go into more details if wanted, it's actually a project I thought about implementing before.

Edit: Whoops, @Eduardo Trápani suggested it already, but I think I can add to that.

I would use a digispark-like chip that can emulate key presses (WIN + L), this won't get you into trouble for installing software on your PC.


body:
At a previous job we also had the rule that the screen had to be locked (usually done   by pressing Win+L).

However, there was no pizza; instead, the computer was used to send mass e-mails to colleagues. The topics of the e-mails was as varied as the imaginations of people:

- invitations to various events;
- invitations to various celebrations at the desk of the not locked computer;
- selling of expensive items for very low prices, providing whatever reasons;
- etc etc

Many times, the content of the e-mail was the result of team-work.

The only limit was that the messages should use a decent language and not be (very) offensive. Also, I have never heard of e-mails sent in order to really harm the forgetful person (e.g. termination notice, offensive language to bosses or cutomers...).

---
The easiest and cheapest method is to just use Win+L. After you buy pizza for everybody for a few times, and have to endure their jokes / sarcasm at the same time, you will never forget to lock it again.

It is like learning to not pee in the bed during the night. It happens a few times, until you get it right.

---
For a technical solution, the sky is the limit.

As an (impractical) joke, you may want to have a look at the [OMGWTF][1] and the [winners][2].

Example: configure the screensaver to kick in and lock the screen after ~ 5 seconds of inactivity (that is roughly the time you need to stand up and walk away, before any colleague has a chance to start typing without you noticing). It will create some trouble for you also, but you are sure that the computer will never remain unlocked. No additional software, hardware or work required - besides moving the mouse and hitting buttons on the keyboard. At the same time, you will become the most productive employee in the company. :)

---
**On a more serious note**, the purpose of that rule is to make people more aware of the security needs, and the need of them being involved in the process. Usually, locking the screen is the least one can do towards security, even before choosing good passwords - screen not locked, password not needed at all.

If one fails to do even that (lock the computer screen when the computer remains unattended), then there is a big chance that the other security rules are not followed either.

  [1]: https://en.wikipedia.org/wiki/The_Daily_WTF#Olympiad_of_Misguided_Geeks
  [2]: https://thedailywtf.com/articles/Announcing-the-OMGTWTF-Winner


body:
### Bluetooth!

In the same vein as Gerben's comment, it is quite easy to use your phone for this, assuming that both your PC and your phone have bluetooth (and you take your phone with you, when you leave your seat). Moreover, if your PC does not have BT, cheap BT dongle will solve this.

Next step is writing a script that gets a list of all nearby/found BT devices and if your phone is not on that list, it just sends system call to lock.

As I have actually tried this once (although with a WIN PC), I can say it works more reliably than I would have initially expected (YMMV, obviously).

The great thing is that you (potentially) do not need any extra hardware, just a bit of code.


body:
The simplest solution would be using a pressure sensor (pressure pad) in your seat. Or a pressure mat if you use a standing up desk.

Ideally, you can calibrate it with an Arduino and send a "Windows Key + L" or a "Ctrl + Cmd + Q" if it is an Apple.

I reckon no other solution can be simpler to implement nor to maintain.

If you want a slightly more refined solution you can connect a scale, tare it with your weight and set a weight threshold for the Arduino to send the signal.

Edit: In ubuntu, you can set up any key combination to lock the screen. But the rest of the answer stands.


body:
Use an obscure window manager which other people don't know how to use.

I use [i3](https://i3wm.org/) and like to deliberately leave my workstation unlocked, because it's funny when I come back and find people pressing various key combinations to try and activate the group chat window (sending a funny message in my name is how they would prove they've 'hacked me') which I put into a hidden buffer.

Two and a half years in this role and they still haven't figured it out...all they need to do is RTFM...


message:
Why is my MPU6050 DMP failing to initialize but I can still get raw accel values from MPU6050

I have been using MPU6050 modules for some time now for yaw measurements using the integrated DMP chip. Everything has gone swimmingly until yesterday, when my initialization code started reporting that I can connect to my MPU6050 chip but DMP init has failed with code 1.

Thinking I had somehow blown up the DMP chip (don't know how, as there is no direct connection), I replaced the module, but got the same result, with three different MPU6050 modules.

As an experiment, I modified my code to read raw Z-axis acceleration values instead of DMP quaternions, and this was successful.  Plotting the values in Excel showed that the values responded as expected when I manually rotated the sensor around the Z-axis.

So now I know I can connect to the MPU6050 module and read sensor values, but I somehow lost the ability to use the DMP. Any ideas as to why this might be happening?

Here are two versions of my code. The first version is the original, and the second one has been modified to just show the Z-axis acceleration values.

TIA,

Frank

Version 1 (original):

    // Visual Micro is in vMicro>General>Tutorial Mode
    //
    /*
        Name:       MPU6050_DRV8871_NoiseTest.ino
        Created: 12/8/2019 10:20:28 AM
        Author:     FRANKNEWXPS15\Frank
    */

    /*
     Name:       Adafruit DRV8871 Motor Driver Test.ino
     Created: 5/30/2019 6:43:18 PM
     Author:     FRANKWIN10\Frank
    */
    //#include <Adafruit_INA219.h>
    #pragma region INCLUDES
    #include <elapsedMillis.h>
    #include <PrintEx.h> //allows printf-style printout syntax
    #include "MPU6050_6Axis_MotionApps_V6_12.h"  //changed to this version 10/05/19
    #include "I2Cdev.h" //02/19/19: this includes SBWire.h
    #include <NewPing.h> //added 01/15/15
    #pragma endregion INCLUDES

    StreamEx mySerial = Serial; //added 03/18/18 for printf-style printing
    elapsedMillis  sinceLastNavUpdateMsec; //added 10/15/18 to replace lastmillisec

    //MPU6050 mpu(0x69); //06/23/18 chg to AD0 high addr on 2-motor robot
    MPU6050 mpu(0x68); //06/23/18 chg to AD0 high addr on 2-motor robot

    void(*resetFunc) (void) = 0; //added 12/08/19 to handle MPU6050/I2C reset failure issue

    #pragma region MPU6050_SUPPORT
    uint8_t mpuIntStatus;   // holds actual interrupt status byte from MPU. Used in Homer's Overflow routine
    uint8_t devStatus;      // return status after each device operation (0 = success, !0 = error)
    uint16_t packetSize;    // expected DMP packet size (default is 42 bytes)
    uint16_t fifoCount;     // count of all bytes currently in FIFO
    uint8_t fifoBuffer[64]; // FIFO storage buffer

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

    //RTC/FRAM/MPU6050 status flags
    bool bMPU6050Ready = true;
    bool dmpReady = false;  // set true if DMP init was successful
    volatile float global_yawval = 0; //updated by GetIMUHeadingDeg()
    const uint16_t MAX_GETPACKET_LOOPS = 100; //10/30/19 added for backup loop exit condition in GetCurrentFIFOPacket()
    uint8_t GetCurrentFIFOPacket(uint8_t* data, uint8_t length, uint16_t max_loops = MAX_GETPACKET_LOOPS); //prototype here so can define a default param
    bool bFirstTime = true;
    #pragma endregion MPU6050 Support

    // Basic sketch for trying out the Adafruit DRV8871 Breakout

    #define MOTOR1_IN1 9
    #define MOTOR1_IN2 10
    #define MOTOR2_IN1 6
    #define MOTOR2_IN2 5

    const int INTER_STEP_DELAY_MS = 100;

    const int NAV_UPDATE_INTERVAL_MSEC = 200;

    const int MIN_MOTOR_SPEED = 60; //empirically determined

    enum MotorStates
    {
     MOTOR_FWD_INCREASING,
     MOTOR_FWD_DECREASING,
     MOTOR_REV_INCREASING,
     MOTOR_REV_DECREASING
    };

    enum MotorStates motState = MOTOR_FWD_INCREASING;
    const int MOTOR_SPEED_MAX = 255;
    //const int MOTOR_SPEED_MAX = 100;
    const int MOTOR_SPEED_MIN = 60; //empirically determined
    int motor_speed = 0;
    int pgmloops = 0;

    void setup() {
     Serial.begin(115200);
     Wire.setClock(50000);

     // initialize MPU6050 added 09/03/18
     Serial.println(F("Initializing MPU6050 ..."));
     mpu.initialize();

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

     Serial.println(F("Initializing DMP..."));
     devStatus = mpu.dmpInitialize();

     // supply your own gyro offsets here, scaled for min sensitivity
     ////12/03/19 settings from calibration routines
     //mpu.setXGyroOffset(58);
     //mpu.setYGyroOffset(20);
     //mpu.setZGyroOffset(12);
     //mpu.setXAccelOffset(1618);
     //mpu.setYAccelOffset(3046);
     //mpu.setZAccelOffset(4554);

     //12/16/19 settings from calibration routines
     mpu.setXAccelOffset(-3066);
     mpu.setYAccelOffset(2658);
     mpu.setZAccelOffset(872);
     mpu.setXGyroOffset(167);
     mpu.setYGyroOffset(-26);
     mpu.setZGyroOffset(73);

     // make sure it worked (returns 0 if successful)
     if (devStatus == 0)
     {
      //12/06/19 no longer needed; cal vals already acquired
      // Calibration Time: generate offsets and calibrate our MPU6050
      //mpu.CalibrateAccel(6);
      //mpu.CalibrateGyro(6);
      //Serial.println();
      //mpu.PrintActiveOffsets();

      // turn on the DMP, now that it's ready
      Serial.println(F("Enabling DMP..."));
      mpu.setDMPEnabled(true);

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

      // get expected DMP packet size for later comparison
      packetSize = mpu.dmpGetFIFOPacketSize();
      bMPU6050Ready = true;
      mySerial.printf("\nMPU6050 Ready at %2.2f Sec\n", millis() / 1000.f);
     }
     else
     {
      // ERROR!
      // 1 = initial memory load failed
      // 2 = DMP configuration updates failed
      // (if it's going to break, usually the code will be 1)
      Serial.print(F("DMP Initialization failed (code "));
      Serial.print(devStatus);
      Serial.println(F(")"));

      bMPU6050Ready = false;
     }

     Serial.println("DRV8871 test");

     pinMode(MOTOR1_IN1, OUTPUT);
     pinMode(MOTOR1_IN2, OUTPUT);
     pinMode(MOTOR2_IN1, OUTPUT);
     pinMode(MOTOR2_IN2, OUTPUT);

     //ina219.begin();
     //mySerial.printf("Speed\tVolts\tMAmps\tMWatts\n"); //column headers
     mySerial.printf("Speed\n"); //column headers

     TCCR2B = (TCCR2B & B11111000) | B00000011; // for PWM frequency of 980.39 Hz on pins 3,11

     sinceLastNavUpdateMsec = 0;
    }

    void loop()
    {
     if (sinceLastNavUpdateMsec >= NAV_UPDATE_INTERVAL_MSEC)
     {
      if (pgmloops % 50 == 0)
      {
       bFirstTime = false;
       mySerial.printf("Min\tYaw\tState\tSpd\tfifoC\tIloops\Oloops\n");
      }

      sinceLastNavUpdateMsec -= NAV_UPDATE_INTERVAL_MSEC;

      //12/10/19 added connection test and reset global 'GetPacket' params
      bool getYawResult = false;
      fifoCount = 0;
      GetPacketLoopCount = 0;
      OuterGetPacketLoopCount = 0;
      global_yawval = 999;
      if (mpu.testConnection())
      {
       getYawResult = GetIMUHeadingDeg(); //updates global_yawval if successful
      }
      else
      {
       mySerial.printf("MPU6050 Not Connected!\n");
      }

      if (getYawResult == 0)
      {
       mySerial.printf("MPU6050 and/or I2C failure - Stopping Test!\n");
       mySerial.printf("min\tyaw\tfifoC\tICount\tOCount\n");
       mySerial.printf("%3.2f\t%3.2f\t%d\t%d\t%d\n",
        millis() / 60000.0,global_yawval, fifoCount, GetPacketLoopCount, OuterGetPacketLoopCount);
       //resetFunc(); //this should completely reset the Arduino so we can start over

       //stop motor 1
       analogWrite(MOTOR1_IN1, 0);
       analogWrite(MOTOR1_IN2, 0);

       //stop motor 2
       analogWrite(MOTOR2_IN1, 0);
       analogWrite(MOTOR2_IN2, 0);
       while (1); //stop the system so I can see failure readout
      }

      mySerial.printf("%3.2f\t%3.2f\t%d\t%d\t%d\t%d\t%d\n",
       millis() / 60000.0, global_yawval,motState,motor_speed,fifoCount, GetPacketLoopCount,
       OuterGetPacketLoopCount);

      //Motor speed/dir management
      switch (motState)
      {
      case MOTOR_FWD_INCREASING:
       // ramp up forward
       digitalWrite(MOTOR1_IN1, LOW);
       digitalWrite(MOTOR2_IN1, LOW);
       motor_speed = (motor_speed > MIN_MOTOR_SPEED) ? motor_speed : MIN_MOTOR_SPEED;
       //if (motor_speed <= MIN_MOTOR_SPEED)
       //{
       // //Serial.println("give it a whack to start!");
       // analogWrite(MOTOR1_IN2, MIN_MOTOR_SPEED);
       // analogWrite(MOTOR2_IN2, MIN_MOTOR_SPEED);
       //}
       //else
       {
        analogWrite(MOTOR1_IN2, motor_speed);
        analogWrite(MOTOR2_IN2, motor_speed);
       }
       motor_speed++;
       if (motor_speed >= MOTOR_SPEED_MAX)
       {
        motState = MOTOR_FWD_DECREASING;
       }
       break;
      case MOTOR_FWD_DECREASING:
       // ramp down forward
       digitalWrite(MOTOR1_IN1, LOW);
       digitalWrite(MOTOR2_IN1, LOW);

       analogWrite(MOTOR1_IN2, motor_speed);
       analogWrite(MOTOR2_IN2, motor_speed);

       motor_speed--;

       if (motor_speed <= MOTOR_SPEED_MIN)
       {
        motState = MOTOR_REV_INCREASING;
       }
       break;
      case MOTOR_REV_INCREASING:
       digitalWrite(MOTOR1_IN2, LOW);
       digitalWrite(MOTOR2_IN2, LOW);

       motor_speed = (motor_speed > MIN_MOTOR_SPEED) ? motor_speed : MIN_MOTOR_SPEED;
       //if (motor_speed <= MIN_MOTOR_SPEED)
       //{
       // //Serial.println("give it a whack to start!");
       // analogWrite(MOTOR1_IN1, MIN_MOTOR_SPEED);
       // analogWrite(MOTOR2_IN1, MIN_MOTOR_SPEED);
       //}
       //else
       {
        analogWrite(MOTOR1_IN1, motor_speed);
        analogWrite(MOTOR2_IN1, motor_speed);
       }

       motor_speed++;

       if (motor_speed >= MOTOR_SPEED_MAX)
       {
        motState = MOTOR_REV_DECREASING;
       }
       break;
      case MOTOR_REV_DECREASING:
       digitalWrite(MOTOR1_IN2, LOW);
       digitalWrite(MOTOR2_IN2, LOW);

       analogWrite(MOTOR1_IN1, motor_speed);
       analogWrite(MOTOR2_IN1, motor_speed);

       motor_speed--;

       if (motor_speed <= MOTOR_SPEED_MIN)
       {
        motState = MOTOR_FWD_INCREASING; //start over
       }
       break;
      default:
       break;
      }

      pgmloops++;
      if (pgmloops == 1000)
      {
       pgmloops = 0;
      }
     }

    }

    void PrintTelemetryData(int spd)
    {

     ////get current, voltage, power readings
     //shuntvoltage = ina219.getShuntVoltage_mV();
     //busvoltage = ina219.getBusVoltage_V();
     //current_mA = ina219.getCurrent_mA();
     //power_mW = ina219.getPower_mW();
     //loadvoltage = busvoltage + (shuntvoltage / 1000);
     //mySerial.printf("%d\t%2.2f\t%2.2f\t%2.2f\n",
     // spd, loadvoltage, current_mA, power_mW);
     mySerial.printf("%d\n", spd);
    }

    bool GetIMUHeadingDeg()
    {
     //Purpose: Get latest yaw (heading) value from IMU
     //Inputs: None.  This function should only be called after mpu.dmpPacketAvailable() returns TRUE
     //Outputs:
     // returns true if successful, otherwise false
     // global_yawval updated on success
     //Plan:
     //Step1: check for overflow and reset the FIFO if it occurs. In this case, wait for new packet
     //Step2: read all available packets to get to latest data
     //Step3: update global_yawval with latest value
     //Notes:
     // 10/08/19 changed return type to boolean
     // 10/08/19 no longer need mpuIntStatus

     bool retval = false;

     int flag = GetCurrentFIFOPacket(fifoBuffer, packetSize, MAX_GETPACKET_LOOPS); //get the latest mpu packet

     if (flag != 0) //0 = error exit, 1 = normal exit, 2 = recovered from an overflow
     {
      // display Euler angles in degrees
      mpu.dmpGetQuaternion(&q, fifoBuffer);
      mpu.dmpGetGravity(&gravity, &q);
      mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);

      //compute the yaw value
      global_yawval = ypr[0] * 180 / M_PI;

      //if (global_yawval == 180)
      //{
      // mySerial.printf("erroneous yaw value detected!");
      // return false;
      //}
      retval = true;
     }

     return retval;
    }

    uint8_t GetCurrentFIFOPacket(uint8_t* data, uint8_t length, uint16_t max_loops)
    {
     max_loops = max(10, max_loops); //added 12/04/19 to ensure we loop at least 10 times. This really IS a hard-coded number!

     fifoCount = mpu.getFIFOCount();

     GetPacketLoopCount = 0;
     int max_outer_loops = 10;

     //11/10/19 I have seen this fail with fifoC > 28 on occasion, so now I loop max 10 times
     OuterGetPacketLoopCount = 0;
     while (fifoCount != packetSize && OuterGetPacketLoopCount < max_outer_loops)
     {
      mpu.resetFIFO();
      delay(1);

      fifoCount = mpu.getFIFOCount();
      GetPacketLoopCount = 0;

      while (fifoCount < packetSize && GetPacketLoopCount < max_loops)
      {
       GetPacketLoopCount++;
       fifoCount = mpu.getFIFOCount();
       delay(2);
      }

      OuterGetPacketLoopCount++;
     }

     //if we get to here, there should be exactly one packet in the FIFO
     if (OuterGetPacketLoopCount < max_outer_loops)
     {
      mpu.getFIFOBytes(data, packetSize);
      return 1;
     }
     return 0; //failed to get a good packet
    }

Version 2 (modified to read raw Z-axis accel:

    // Visual Micro is in vMicro>General>Tutorial Mode
    //
    /*
        Name:       MPU6050_DRV8871_NoiseTest.ino
        Created: 12/8/2019 10:20:28 AM
        Author:     FRANKNEWXPS15\Frank
    */

    /*
     Name:       Adafruit DRV8871 Motor Driver Test.ino
     Created: 5/30/2019 6:43:18 PM
     Author:     FRANKWIN10\Frank
    */
    //#include <Adafruit_INA219.h>
    #pragma region INCLUDES
    #include <elapsedMillis.h>
    #include <PrintEx.h> //allows printf-style printout syntax
    #include "MPU6050_6Axis_MotionApps_V6_12.h"  //changed to this version 10/05/19
    #include "I2Cdev.h" //02/19/19: this includes SBWire.h
    #include <NewPing.h> //added 01/15/15
    #pragma endregion INCLUDES

    StreamEx mySerial = Serial; //added 03/18/18 for printf-style printing
    elapsedMillis  sinceLastNavUpdateMsec; //added 10/15/18 to replace lastmillisec

    //MPU6050 mpu(0x69); //06/23/18 chg to AD0 high addr on 2-motor robot
    MPU6050 mpu(0x68); //06/23/18 chg to AD0 high addr on 2-motor robot

    void(*resetFunc) (void) = 0; //added 12/08/19 to handle MPU6050/I2C reset failure issue

    #pragma region MPU6050_SUPPORT
    uint8_t mpuIntStatus;   // holds actual interrupt status byte from MPU. Used in Homer's Overflow routine
    uint8_t devStatus;      // return status after each device operation (0 = success, !0 = error)
    uint16_t packetSize;    // expected DMP packet size (default is 42 bytes)
    uint16_t fifoCount;     // count of all bytes currently in FIFO
    uint8_t fifoBuffer[64]; // FIFO storage buffer

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

    //RTC/FRAM/MPU6050 status flags
    bool bMPU6050Ready = true;
    bool dmpReady = false;  // set true if DMP init was successful
    volatile float global_yawval = 0; //updated by GetIMUHeadingDeg()
    const uint16_t MAX_GETPACKET_LOOPS = 100; //10/30/19 added for backup loop exit condition in GetCurrentFIFOPacket()
    uint8_t GetCurrentFIFOPacket(uint8_t* data, uint8_t length, uint16_t max_loops = MAX_GETPACKET_LOOPS); //prototype here so can define a default param
    bool bFirstTime = true;
    #pragma endregion MPU6050 Support

    // Basic sketch for trying out the Adafruit DRV8871 Breakout

    #define MOTOR1_IN1 9
    #define MOTOR1_IN2 10
    #define MOTOR2_IN1 6
    #define MOTOR2_IN2 5

    const int INTER_STEP_DELAY_MS = 100;

    const int NAV_UPDATE_INTERVAL_MSEC = 200;

    const int MIN_MOTOR_SPEED = 60; //empirically determined

    enum MotorStates
    {
     MOTOR_FWD_INCREASING,
     MOTOR_FWD_DECREASING,
     MOTOR_REV_INCREASING,
     MOTOR_REV_DECREASING
    };

    enum MotorStates motState = MOTOR_FWD_INCREASING;
    const int MOTOR_SPEED_MAX = 255;
    //const int MOTOR_SPEED_MAX = 100;
    const int MOTOR_SPEED_MIN = 60; //empirically determined
    int motor_speed = 0;
    int pgmloops = 0;

    void setup() {
     Serial.begin(115200);
     Wire.setClock(50000);

     // initialize MPU6050 added 09/03/18
     Serial.println(F("Initializing MPU6050 ..."));
     mpu.initialize();

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

     Serial.println(F("Initializing DMP..."));
     devStatus = mpu.dmpInitialize();

     // supply your own gyro offsets here, scaled for min sensitivity
     ////12/03/19 settings from calibration routines
     //mpu.setXGyroOffset(58);
     //mpu.setYGyroOffset(20);
     //mpu.setZGyroOffset(12);
     //mpu.setXAccelOffset(1618);
     //mpu.setYAccelOffset(3046);
     //mpu.setZAccelOffset(4554);

     //12/16/19 settings from calibration routines
     mpu.setXAccelOffset(-3066);
     mpu.setYAccelOffset(2658);
     mpu.setZAccelOffset(872);
     mpu.setXGyroOffset(167);
     mpu.setYGyroOffset(-26);
     mpu.setZGyroOffset(73);

     // make sure it worked (returns 0 if successful)
     if (devStatus == 0)
     {
      //12/06/19 no longer needed; cal vals already acquired
      // Calibration Time: generate offsets and calibrate our MPU6050
      //mpu.CalibrateAccel(6);
      //mpu.CalibrateGyro(6);
      //Serial.println();
      //mpu.PrintActiveOffsets();

      // turn on the DMP, now that it's ready
      Serial.println(F("Enabling DMP..."));
      mpu.setDMPEnabled(true);

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

      // get expected DMP packet size for later comparison
      packetSize = mpu.dmpGetFIFOPacketSize();
      bMPU6050Ready = true;
      mySerial.printf("\nMPU6050 Ready at %2.2f Sec\n", millis() / 1000.f);
     }
     else
     {
      // ERROR!
      // 1 = initial memory load failed
      // 2 = DMP configuration updates failed
      // (if it's going to break, usually the code will be 1)
      Serial.print(F("DMP Initialization failed (code "));
      Serial.print(devStatus);
      Serial.println(F(")"));

      bMPU6050Ready = false;
     }

     Serial.println("DRV8871 test");

     pinMode(MOTOR1_IN1, OUTPUT);
     pinMode(MOTOR1_IN2, OUTPUT);
     pinMode(MOTOR2_IN1, OUTPUT);
     pinMode(MOTOR2_IN2, OUTPUT);

     //ina219.begin();
     //mySerial.printf("Speed\tVolts\tMAmps\tMWatts\n"); //column headers
     mySerial.printf("Speed\n"); //column headers

     TCCR2B = (TCCR2B & B11111000) | B00000011; // for PWM frequency of 980.39 Hz on pins 3,11

     sinceLastNavUpdateMsec = 0;
    }

    void loop()
    {
     if (sinceLastNavUpdateMsec >= NAV_UPDATE_INTERVAL_MSEC)
     {
      if (pgmloops % 50 == 0)
      {
       bFirstTime = false;
       mySerial.printf("Min\tYaw\tState\tSpd\tfifoC\tIloops\Oloops\n");
      }

      sinceLastNavUpdateMsec -= NAV_UPDATE_INTERVAL_MSEC;

      //12/10/19 added connection test and reset global 'GetPacket' params
      bool getYawResult = false;
      fifoCount = 0;
      GetPacketLoopCount = 0;
      OuterGetPacketLoopCount = 0;
      global_yawval = 999;
      if (mpu.testConnection())
      {
       getYawResult = GetIMUHeadingDeg(); //updates global_yawval if successful
       float Zaccel = mpu.getAccelerationZ();
       mySerial.printf("Zaccel = %3.2f\n", Zaccel);
      }
      else
      {
       mySerial.printf("MPU6050 Not Connected!\n");
      }

      //if (getYawResult == 0)
      //{
      // mySerial.printf("MPU6050 and/or I2C failure - Stopping Test!\n");
      // mySerial.printf("min\tyaw\tfifoC\tICount\tOCount\n");
      // mySerial.printf("%3.2f\t%3.2f\t%d\t%d\t%d\n",
      //  millis() / 60000.0,global_yawval, fifoCount, GetPacketLoopCount, OuterGetPacketLoopCount);
      // //resetFunc(); //this should completely reset the Arduino so we can start over

      // //stop motor 1
      // analogWrite(MOTOR1_IN1, 0);
      // analogWrite(MOTOR1_IN2, 0);

      // //stop motor 2
      // analogWrite(MOTOR2_IN1, 0);
      // analogWrite(MOTOR2_IN2, 0);
      // while (1); //stop the system so I can see failure readout
      //}

      //mySerial.printf("%3.2f\t%3.2f\t%d\t%d\t%d\t%d\t%d\n",
      // millis() / 60000.0, global_yawval,motState,motor_speed,fifoCount, GetPacketLoopCount,
       //OuterGetPacketLoopCount);

      //Motor speed/dir management
      switch (motState)
      {
      case MOTOR_FWD_INCREASING:
       // ramp up forward
       digitalWrite(MOTOR1_IN1, LOW);
       digitalWrite(MOTOR2_IN1, LOW);
       motor_speed = (motor_speed > MIN_MOTOR_SPEED) ? motor_speed : MIN_MOTOR_SPEED;
       //if (motor_speed <= MIN_MOTOR_SPEED)
       //{
       // //Serial.println("give it a whack to start!");
       // analogWrite(MOTOR1_IN2, MIN_MOTOR_SPEED);
       // analogWrite(MOTOR2_IN2, MIN_MOTOR_SPEED);
       //}
       //else
       {
        analogWrite(MOTOR1_IN2, motor_speed);
        analogWrite(MOTOR2_IN2, motor_speed);
       }
       motor_speed++;
       if (motor_speed >= MOTOR_SPEED_MAX)
       {
        motState = MOTOR_FWD_DECREASING;
       }
       break;
      case MOTOR_FWD_DECREASING:
       // ramp down forward
       digitalWrite(MOTOR1_IN1, LOW);
       digitalWrite(MOTOR2_IN1, LOW);

       analogWrite(MOTOR1_IN2, motor_speed);
       analogWrite(MOTOR2_IN2, motor_speed);

       motor_speed--;

       if (motor_speed <= MOTOR_SPEED_MIN)
       {
        motState = MOTOR_REV_INCREASING;
       }
       break;
      case MOTOR_REV_INCREASING:
       digitalWrite(MOTOR1_IN2, LOW);
       digitalWrite(MOTOR2_IN2, LOW);

       motor_speed = (motor_speed > MIN_MOTOR_SPEED) ? motor_speed : MIN_MOTOR_SPEED;
       //if (motor_speed <= MIN_MOTOR_SPEED)
       //{
       // //Serial.println("give it a whack to start!");
       // analogWrite(MOTOR1_IN1, MIN_MOTOR_SPEED);
       // analogWrite(MOTOR2_IN1, MIN_MOTOR_SPEED);
       //}
       //else
       {
        analogWrite(MOTOR1_IN1, motor_speed);
        analogWrite(MOTOR2_IN1, motor_speed);
       }

       motor_speed++;

       if (motor_speed >= MOTOR_SPEED_MAX)
       {
        motState = MOTOR_REV_DECREASING;
       }
       break;
      case MOTOR_REV_DECREASING:
       digitalWrite(MOTOR1_IN2, LOW);
       digitalWrite(MOTOR2_IN2, LOW);

       analogWrite(MOTOR1_IN1, motor_speed);
       analogWrite(MOTOR2_IN1, motor_speed);

       motor_speed--;

       if (motor_speed <= MOTOR_SPEED_MIN)
       {
        motState = MOTOR_FWD_INCREASING; //start over
       }
       break;
      default:
       break;
      }

      pgmloops++;
      if (pgmloops == 1000)
      {
       pgmloops = 0;
      }
     }

    }

    void PrintTelemetryData(int spd)
    {

     ////get current, voltage, power readings
     //shuntvoltage = ina219.getShuntVoltage_mV();
     //busvoltage = ina219.getBusVoltage_V();
     //current_mA = ina219.getCurrent_mA();
     //power_mW = ina219.getPower_mW();
     //loadvoltage = busvoltage + (shuntvoltage / 1000);
     //mySerial.printf("%d\t%2.2f\t%2.2f\t%2.2f\n",
     // spd, loadvoltage, current_mA, power_mW);
     mySerial.printf("%d\n", spd);
    }

    bool GetIMUHeadingDeg()
    {
     //Purpose: Get latest yaw (heading) value from IMU
     //Inputs: None.  This function should only be called after mpu.dmpPacketAvailable() returns TRUE
     //Outputs:
     // returns true if successful, otherwise false
     // global_yawval updated on success
     //Plan:
     //Step1: check for overflow and reset the FIFO if it occurs. In this case, wait for new packet
     //Step2: read all available packets to get to latest data
     //Step3: update global_yawval with latest value
     //Notes:
     // 10/08/19 changed return type to boolean
     // 10/08/19 no longer need mpuIntStatus

     bool retval = false;

     int flag = GetCurrentFIFOPacket(fifoBuffer, packetSize, MAX_GETPACKET_LOOPS); //get the latest mpu packet

     if (flag != 0) //0 = error exit, 1 = normal exit, 2 = recovered from an overflow
     {
      // display Euler angles in degrees
      mpu.dmpGetQuaternion(&q, fifoBuffer);
      mpu.dmpGetGravity(&gravity, &q);
      mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);

      //compute the yaw value
      global_yawval = ypr[0] * 180 / M_PI;

      //if (global_yawval == 180)
      //{
      // mySerial.printf("erroneous yaw value detected!");
      // return false;
      //}
      retval = true;
     }

     return retval;
    }

    uint8_t GetCurrentFIFOPacket(uint8_t* data, uint8_t length, uint16_t max_loops)
    {
     max_loops = max(10, max_loops); //added 12/04/19 to ensure we loop at least 10 times. This really IS a hard-coded number!

     fifoCount = mpu.getFIFOCount();

     GetPacketLoopCount = 0;
     int max_outer_loops = 10;

     //11/10/19 I have seen this fail with fifoC > 28 on occasion, so now I loop max 10 times
     OuterGetPacketLoopCount = 0;
     while (fifoCount != packetSize && OuterGetPacketLoopCount < max_outer_loops)
     {
      mpu.resetFIFO();
      delay(1);

      fifoCount = mpu.getFIFOCount();
      GetPacketLoopCount = 0;

      while (fifoCount < packetSize && GetPacketLoopCount < max_loops)
      {
       GetPacketLoopCount++;
       fifoCount = mpu.getFIFOCount();
       delay(2);
      }

      OuterGetPacketLoopCount++;
     }

     //if we get to here, there should be exactly one packet in the FIFO
     if (OuterGetPacketLoopCount < max_outer_loops)
     {
      mpu.getFIFOBytes(data, packetSize);
      return 1;
     }
     return 0; //failed to get a good packet
    }

body:
So, it turns out that the problem was located squarely between the programmer's ears, as usual.

As part of another experiment to use an I2C sniffer program to find out why the MPU6050 was failing intermittently, I had added the following line to my setup() function

    Wire.setClock(50000);

To slow the I2C clock down enough so that a sniffer program could keep up.  Apparently the slower than normal I2C clock speed was enough to screw up the DMP Initialization process.

The funny (weird, not 'ha ha') thing was the way I discovered this was by adding some 'Serial.print()' statements into the loop that writes the DMP firmware onto the DMP chip at each startup. For some reason, the print statements allowed the load to succeed, even with the lower I2C clock speed.  Boy was I surprised!

Even weirder is that I could not substitute a 'delay(x)' in place of the print statement; any delay (even as small as 'delay(1);') caused the DMP load to fail, while a print statement worked fine.

Once I saw there was something weird going on with the rate at which the load operations were being executed, I remembered about the 'Wire.SetClock(50000)' command and commented it out to go back to the default I2C rate.  Voila` problem solved!

I have NO clue as to why the DMP firmware load is clock speed sensitive, and even less clue why the print statements allowed the load to complete, but I'm back in business now, so I'm going to file this one in the "Who knew?" category and move on ;-)

Frank


message:
Execution of functions at the "same time"

everyone
I'm designing a vehicle security system, basically I can already read amd i control all the components (GSM, GPS, Magnetic Sensor, Giroscop, buzzer...) connected to the microcontroller.

But then the functions are basically three main ones  (at void loop) that I need to be working in "simultaneous", any idea of how I can do that?

Below the code, half long but that's all I need...

there are some comments in portuguese. i apologize for that, but the important thing is in the code
thanks in advance

    #include <SoftwareSerial.h>
    #include <TinyGPS++.h>
    SoftwareSerial sgsm(3,2);
    String number = "25884xxxxxxx" ;
    unsigned char Buff[250];
    unsigned char BuffIndex;

    #include<Wire.h>
    int sensorMag = 5;  //SENSOR MAGNETICO

    TinyGPSPlus gps;
    double latitude, longitude;
    String response;
    int lastStringLength = response.length();
    String link;

    const int MPU6050_addr=0x68;
    int16_t AccX,AccY,AccZ,Temp,GyroX,GyroY,GyroZ;

    #include <IRremote.h>
    int RECV_PIN = 4;   //REMOTE
    IRrecv irrecv(RECV_PIN);
    decode_results results;

    int Sirene = 6;     //BUZZER
    int Motor = 7;      //MOTOR

    /////===================================================================== Inicializacao do sensores =============================================================================================================================
    void setup()
    {
    Serial.begin(9600);
    sgsm.begin(9600);
    delay (1000);
    Wire.begin();
    Wire.beginTransmission(MPU6050_addr);
    Wire.write(0x6B);
    Wire.write(0);
    Wire.endTransmission(true);
    delay (1000);
    pinMode(sensorMag, INPUT); //SENSOR MAGNETICO
    pinMode(Sirene, OUTPUT);  //Sirene
    pinMode(Motor, OUTPUT);   //MOTOR
    irrecv.enableIRIn();
    Serial.println("SISTEMA INICIALIZADO");
    }

    /////=====================================================================  Inicio do Loop  =============================================================================================================================
    void loop()
    {
     //GPS();
     remote ();
     ReceberComando();

     }

    /////=====================================================================   Remote controle  =============================================================================================================================

    void remote (){
     if (irrecv.decode(&results))
    {
    Serial.println(results.value, HEX);
    Serial.println("  ");
    if (results.value== 0xFF6897)
    {
    //while (results.value==0xFF5AA5){
    Serial.println("SISTEMA INACTIVO");
    digitalWrite(Motor, LOW);
    Serial.println("  ");
    //Acelerometro();
    delay(500);
    }
    else
    {
     while (results.value==0xFF10EF)
      {
        Serial.println("Sistema Armado");
        digitalWrite(Motor, HIGH);
        delay(1000);
        Serial.println("  ");
        SensorMagnetico();
        delay(1000);
        Acelerometro();
        delay(1000);
      }
    }
    }

    irrecv.resume(); // Receive the next value
    delay(1000);
    }

    void SensorMagnetico()
    {
    int EstadosensorMag = digitalRead(sensorMag);
    if (EstadosensorMag = digitalRead(sensorMag)== HIGH){
     Serial.println("A porta N. 1 da sua viatura foi aberta!");
     digitalWrite(Sirene, HIGH);
     delay(1000);
     mensagem2();
     delay(1000);
     enviolink();
     delay (1000);
    }
    else
     Serial.println("Portas Fechadas");
     digitalWrite(Sirene, LOW);
     delay(100);
     //digitalWrite(Motor, HIGH);
    }

    void Acelerometro(){
    Wire.beginTransmission(MPU6050_addr);
    Wire.write(0x3B);
    Wire.endTransmission(false);
    Wire.requestFrom(MPU6050_addr,14,true);
    AccX=Wire.read()<<8|Wire.read();
    AccZ=Wire.read()<<8|Wire.read();
    Serial.print("AccX = ");
    Serial.print(AccX);
    Serial.print(" || AccZ = ");
    Serial.println(AccZ);
    delay(1000);

    if (AccZ > 2000){
    digitalWrite(Sirene, HIGH);
    delay(2000);
    }
    else
    digitalWrite(Sirene, LOW);
    }

    /////====================  coordenadas/ GPS=============================

     void GPS(){
     if(Serial.available()) {
       gps.encode(Serial.read());
     }
     if(gps.location.isUpdated()) {
       Serial.print("latitude:");
       latitude = gps.location.lat();
       Serial.print("longitude:");
       longitude = gps.location.lng();
       link = "www.google.com/maps/place/" + String(latitude, 6) + "," + String(longitude, 6) ;
       Serial.println(link);

     }
    }

    /////=========  Receber Comandos de texto + localizacao ======================
    void ReceberComando()
    {
    Serial.begin(9600);
    sgsm.begin(9600);
    Serial.print("Inicializado o GSM e apagando SMS");
    clear_SMS_Memory();
    delay(3000);
    sgsm.println("AT+CMGF=1");
    delay(3000);
    sgsm.println("AT+CNMI=2,2,0,0,0");
    memset(Buff, '\0', 250);// Initialize the string    BuffIndex=5;  }
    delay (9000);

    pinMode(Motor, OUTPUT); // controle do motor

    while(1)
    {
     if(sgsm.available()>0)
     {
      Buff[BuffIndex] = sgsm.read();
      if( (Buff[BuffIndex-2] == 'D') && (Buff[BuffIndex-1] == 'M') && (Buff[BuffIndex] == '1'))// Desativar Motor Agora
      {
      digitalWrite(Motor, HIGH);
      send2("Motor da sua viatura desligado! aguarde pelas coordenadas...");
      Serial.println ("Set sgsm Number");
      delay(10000);
      GPS();
      delay(10000);
      enviolink();
      Serial.println(" ");

      }
      if( (Buff[BuffIndex-2] == 'A') && (Buff[BuffIndex-1] == 'R') && (Buff[BuffIndex] == 'M'))//Ativar Motor Agora
      {
      digitalWrite(Motor, LOW);
      digitalWrite (Sirene, LOW);
      send2("Motor Ativo....A viatura esta segura!, Aguarde a localizacao!");
      Serial.println ("Set sgsm Number");
      delay(1000);
      GPS();
      delay(1000);
      enviolink();
      Serial.println(" ");

       }

       if( (Buff[BuffIndex-2] == 'L') && (Buff[BuffIndex-1] == 'O') && (Buff[BuffIndex] == 'C'))//Retorna coordenadas
      {
      send2("Buscado a localizacao actual!");
      GPS();
      delay(10000);
      enviolink();
      Serial.println(" ");
      delay(10000);

       }
           /// Pode se acrescentar mais condicoes
      BuffIndex++;
      if(BuffIndex>250)
       {
        BuffIndex=5;
        }
     }
    }
    }

    /////===============  Mensagens de Texto =======

    void send2(String SMS)
     {
     Serial.println ("Sending Message");
     sgsm.println("AT+CMGF=1");    //Sets the GSM Module in Text Mode
     delay(1000);
     Serial.println ("Set sgsm Number");
     sgsm.println("AT+CMGS=\"" + number + "\"\r"); //Mobile phone number to send message
     delay(1000);
     sgsm.println(SMS);
     delay(100);
     sgsm.println((char)26);// ASCII code of CTRL+Z
     delay(1000);
     }

    void mensagem()// mensagens das variaveis; e inicializacao do carro
    {
     Serial.println ("Sending Message");
     sgsm.println("AT+CMGF=1");    //Sets the GSM Module in Text Mode
     delay(1000);
     Serial.println ("Set sgsm Number");
     sgsm.println("AT+CMGS=\""+ number + "\"\r"); //Mobile phone number to send message
     delay(1000);
     String SMS = "Sistema de Alarme habilitado";   //sgsm content
     sgsm.println(SMS);
     delay(100);
     sgsm.println((char)26);// ASCII code of CTRL+Z
     delay(1000);
    }

    void mensagem2()// mensagens das variaveis; e inicializacao do carro
    {
     Serial.println ("Sending Message");
     sgsm.println("AT+CMGF=1");    //Sets the GSM Module in Text Mode
     delay(1000);
     Serial.println ("Set sgsm Number");
     sgsm.println("AT+CMGS=\""+ number + "\"\r"); //Mobile phone number to send message
     delay(1000);
     String SMS = "Alerta de intrução! Verifique a sua viatura.";   //sgsm content
     sgsm.println(SMS);
     delay(100);
     sgsm.println((char)26);// ASCII code of CTRL+Z
     delay(1000);
    }

    ////=========================   Apaga mensagens no cartao  ===========
    void clear_SMS_Memory()
    {
    unsigned short i = 0;
    for (i = 0; i <= 30; i++)
    {
    sgsm.print("AT+CMGD=");
    sgsm.println(i);
    delay(100);
    }
    while (sgsm.available() > 0) sgsm.read();
    }

    /////=====================  Leitura  de Inputs do GSM ==========

    void updateSerial()
    {
     delay(500);
     while (Serial.available())
     {
     sgsm.write(Serial.read());//Forward what Serial received to Software Serial Port
     }
     while(sgsm.available())
     {
     Serial.write(sgsm.read());//Forward what Software Serial received to Serial Port
     }
    }

    /////======= localizacao ========================================
    void enviolink()
    {
      sgsm.println("AT+CMGF=1");    //Sets the GSM Module in Text Mode
      delay(1000);  // Delay of 1000 milli seconds or 1 second
      sgsm.println("AT+CMGS=\"+25884xxxxxxx\"\r"); // Replace x with mobile number
      delay(1000);
      sgsm.println(link);// The SMS text you want to send
      delay(100);
      sgsm.println((char)26);// ASCII code of CTRL+Z
      delay(1000);
    }

body:
Without analyzing the complete code, the steps to go are:

- Remove the `delay` function calls. These mostly delay the program in such a way that other parts are not executed in time or 'at the same time'.
- Instead use the [`millis` command][1] and check again time stamps (of `unsigned long int` type) to reach the delays you need.
- Create a state machine. This means in simple form that you use an enumeration (`enum` type) which can have one out of a set of values (like Stopped, Accelerating, Decelerating), for each 'states'  you can define in your sketch.
- Use these state machines and times to move from one state to another, and while changing state (or during a state) you can perform the actions you need.

  [1]: https://www.arduino.cc/reference/en/language/functions/time/millis/


body:
Since you put "simultaneous" in quotes, I'm assuming you realize that one MCU can only do one thing at a time, but cleverly programmed, it can do small pieces of several things faster than you and I can perceive the difference. (I state this for completeness, for the benefit of readers who may not have thought this out yet.)

A couple of techniques will help you here.

One is what I call "maybedo" functions - functions you call frequently, that do or do not do something (depending on conditions such as time or input signals) but they *do it quickly and return immediately*. See my [answer here][1] for more explanation of "maybedo" functions.

Another and very important one is to avoid `delay()` calls. Try a timer library such as SimpleTimer. This lets your `loop()` function and those it calls, keep short. The SimpleTimer library entry is a "maybedo" for up to 10 timer-driven functions. All you have to do is call `mytimers.run()` frequently. Mostly it won't do much, but occasionally it will find one or more timers have expired and will call their associated functions for you. You just have to have set up the timers to call some simple - and again, *short* - functions to do something. And to be clear, we're talking about software-based timers, not the MCU's hardware timers. The library's work is based on the `millis()` function, but it automates that for you.

  [1]: https://arduino.stackexchange.com/questions/65717/2-analog-sensors-pulse-sensor-and-lm35-problem?answertab=active#tab-top


body:
As others have said, Arduinos are single-threaded, real mode computers. They only do one thing at a time. However, they do that one thing fast enough that you can make your apps switch between things rapidly enough that they keep multiple tasks running, like a circus clown keeping lots of plates spinning on sticks.

You have to use "roll-your-own" cooperative multitasking, where each time through your app's loop, you look for work to do on each of the tasks you're juggling. You have to make each pass through the loop fast so you don't miss things.

You should avoid the `delay()` function entirely if at all possible. The `delay()` and `delayMicros()` functions bring your app to a complete halt for the entire duration of the delay.

Search on "Arduino blink without delay" and look at the sample app that points to. It shows how to use `millis()` to manage timed actions without using `delay()`. You should apply that approach to everything you do.