text:
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
}

I have absolute no knowledge of the MPU6050 and the DMP therein. But, as noone reacted to your question. let me present you an idea. As this cite states "For this DMP, InvenSense has a discouragement policy, by not supplying enough information how to program the DMP. " it is hard for the lib creator (Jeff Rowberg in your case) to reverse engineer the firmware of the DMP. He did it manage but the firmware must be uploaded to the MCU with every start. Now, my idea is, what happens if you restart the Arduino prog. but do not unpower the MCU long enough to clear the memory?  (e.g. only reset Ard.)

There was also a huge rewriting of the DMP firmware that was released  in October 2019. But if I understood you correctly, the error occurs long after you have changed to the version "MPU6050_6Axis_MotionApps_V6_12.h".

I also found out the the Error 1 can only occur, if the comparison of the firmware that was written and the firmware that was read out of the DMP memory after the write were not equal. The comparison is made chunk wise.

Peter,  thanks for the hint. I was able to determine that there is indeed a problem with the memory write process.  When I uncommented some debugging code in the memory write function, I got this: Block write verification error, bank 0, address 0!
Expected: 0x00 0xF8 0xF6 0x2A 0x3F 0x68 0xF5 0x7A 0x00 0x06 0xFF 0xFE 0x00 0x03 0x00 0x00
Received: 0x00 0xF8 0xF6 0x2A 0x3F 0x68 0xF5 0x7A 0x00 0x06 0xFF 0xFE 0x00 0x03 0x08 0x7B
DMP memory write failed.  Note the last two bytes differ

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


text:
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);
}

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 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.

For my apps, I created a class ArduinoObject. Each ArduinoObject has a setup() function and a loop() function, as well as an active boolean flag. My apps manage an array of ArduinoObjects. If an object's active flag is true, the app's loop calls its loop function on each pass through. If not, it isn't called at all. This makes it very easy to manage a whole bunch of what you call "MaybeDo" tasks dynamically.

The app uses a fixed-sized C array with enough elements for the max number of ArduinoObjects my app needs. If I need to add another task, I add an ArduinoObject to the array. If I want one of the objects to go to sleep, I set its active flag to false.  The code that manages the array of ArduinoObject ignores NULL values, so I can set one of them to NULL if I'm completely done with it. The code that adds a new object searches for the first empty slot in the array. Each ArduinoObject is written to take very little time on each pass through its loop.

Interesting task structure - thanks!

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 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.

You have a minor typo in your answer. The function is millis() not milli. A newbie might not know that, and might fail to find the function with that typo in it.

@DuncanC Thanks for the notification, I updated my answer. I also added a reference to the page.

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.

source: Stack Exchange

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

sort: votes


text:
My ESP8266-01 doesn't want to respond to AT command after a successful flash!
Well hello, experts,
I've been trying to fix my issue all time, but all in vain.
I have an Esp8266-01 with 1MB memory. I've flashed it with an official AT firmware V2.0.0 of espressif with the help of this tutorial-arduino as a usb/TTL-: "https://www.allaboutcircuits.com/projects/flashing-the-ESP-01-firmware-to-SDK-v2.0.0-is-easier-now/", and it was a successful flash.
However, when trying to send AT commands in the serial monitor at different baud rates nothing happens.
I'll provide you with all the information down here:

Schematic for both flash and normal mode:

I used the official flasher tool from espressif
I used both Arduino IDE and Termite with no results
I've uploaded the blink sketch successfully into my module, but it never runs and blinks.
After lots of tries and resets I started to receive some information:

But still no answers from this module!!!
Could you help me, please?

The tutorial is to flash SDK 2.0 AT firmware. The AT 2.0.0 firmware is build with RTOS SDK. The 2.0 AT firmware available on Espressif site was build with settings not compatible with esp-01. It is built for 2 MB flash and  communicates over pins 13 and 15.
The latest NonOS SDK AT firmware is 1.7.1 (SDK 3), but it requires 2 MB flash too. It is possible to flash it to 1 MB module with the 2MB-c1 parameter with esptool.py. (The OTA update command will not work.)
GitHub user loboris (Boris Lovosevic) builds customized versions of AT firmware with SDK 3 for all flash sizes. You can download the files from his ESP8266_AT_LoBo GitHub repository. If you can't run his flash.sh utility, then for 1 MB flash you can Flash Download Tool with bin/upgrade/esp8266_AT_1_2.bin file and the right addresses for 1 MB flash: boot_v1.7.bin on 0x0; esp8266_AT_1_2.bin on 0x01000; esp_init_data_default.bin on 0xfc000 and blank.bin on 0x7e000 and 0xfe000.

Comments are not for extended discussion; this conversation has been moved to chat.

You need pullup resistors, 10kΩ or so, on both the NRST and GPIO0 lines. After you press and release the reset button the NRST line will be floating, and its voltage (and logic level) will be undefined. It's not unusual to see the behavior of a board change just by waving your hand over it if you leave inputs floating, so it's not surprising that you will sometimes get it to work.

Thanks for this great help, and I'll give it a try right away.

I just noticed that the TX/RX connections are incorrect. The TX from the Arduino should have the voltage divider and should feed into RX on the ESP-01. The TX from the ESP-01 should be connected to the RX on the Arduino. Ideally you would have a proper level translator between the 5V Arduino and the 3.3V ESP-01, but this might work.

Ah, never mind that last comment. It looks like you must be using the ESP-01 in place of the Arduino microcontroller. I initially thought that you were using the Arduino microcontroller to talk to the ESP-01.

That's it, I used the arduino board as a bridge in order to communicate with my esp8266.

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


text:
why is memcpy of unsigned long killing my sampling speed?
I'm using a Mega 2560 to communicate with a mixture of analog (i.e. measured via analogRead()) and I2C based sensors. Sampled data is placed in a 16 byte array, then written to an SD card once a 512 byte buffer is completely filled. The problem I'm running into is that when I collect data from a MAX30102 pulse oximeter using
measure.pox = pulseOx.getIR();

from my code below, the cycle time of my collectHR() loop drops to about 20 mS. If I preallocate this spot by using the line directly below it (storing a constant instead of reading a new uint32_t each loop), my cycle time is about half a millisecond. What's confusing to me is that if I cast the uint32_t into a string using dtostrf:
dtostrf(pulseOx.getIR(),3,0,pOxBuf); // read pulseOx, convert it into a 3 byte string

it only takes about 1.2 mS to actually read a sample from the MAX30102. It seems to me that by favoring a struct over a string (from an earlier iteration of this code that wrote all data as a txt file instead of a bin file) so that I can write binary to my SD card, I'm absolutely throttling my speed. Shouldn't working bytewise be more efficient than working with a string? What is happening to the other 18 mS that occurs between reading the unsigned long and placing it into by byte buffer, buffer1? Implementing this code using string arrays instead of a struct, I was able to run at approximately 125 Hz. Now I'm at roughly 50 Hz. I'd appreciate any insight here. Relevant code shown below:
#include <Wire.h>
#include "MAX30105.h"
#include <SPI.h>
#include <SdFat.h>
#define moisture0 A0 // Upper back sensor analog pin
#define moisture1 A7 // Trunk sensor analog pin
#define ECGpin A3 // ECG analog pin

SdFat SD; // replace SD with SDfat.
File sdLog; // placeholder to create datalogger

struct meas // a 16 byte structure to hold all of our measurements
{
  unsigned long mils;
  int ECG;
  uint32_t pox;
  int tempInt;
  int m1;
  int m2;
};
struct meas measure; // create an instance of the above structure

byte buffer1[512];
byte *measureLoc = (byte *) &measure; // to access measure structure as bytes
char fileName[] = "WIHMSlog.bin";

void setup {
    Serial.begin(230400);
}

void loop() {
sdLog = SD.open(fileName, O_WRITE | O_CREAT | O_AT_END); // Create file for the datalogging and verify its existance
collectHR();
sdlog.close()
}

void collectHR() {
  unsigned int loopCount = 0;
  int buffLen = 0; // starting position in buffer
  int buffSize = 16;

  while (loopCount < 3200) { // some multiple of 32 (since 512 byte/sd block divided by 16 bytes per loop cycle = 32 cycles per sd write cycle

    measure.ECG = analogRead(ECGpin); // read ECG and stick the int into measures
    measure.pox = pulseOx.getIR();
    //measure.pox = 5555; // Placeholder value
    measure.mils = micros();
    measure.m1 = analogRead(moisture0);
    measure.m2 = loopCount; // just a test to ensure this is actually iterating in the card

    if (buffLen == 512) { // SD buffer is full, time to write!
      sdLog.write(buffer1, 512);
      buffLen = 0;
    }
    memcpy(buffer1 + buffLen, measureLoc, buffSize); // place the 16 byte data structure into the buffer
    buffLen = buffLen + buffSize; // increase the index size in the array
    loopCount++;
    Serial.println(micros());
  }

}

The sequence of operations looks a bit strange. Consider what happens at the very start: buffLen is initially 0, then you immediately increase it to 16 and then you copy the data to that buffer at offset 16. But what about the first 16 bytes? Why did you leave them unused? Also, it is not clear why you even need to constantly pump bytes from measure to buffer1, i.e. from memory to memory. Why don't you just declare an array of 32 struct measure elements and use it directly?

Thanks for your input! You're absolutely right that the first 16 bytes remain empty. I had initially thought it would make it easier to determine when each collectHR() loop ended in the file by searching for 16 0's, but now that you point it out it seems like a total waste of memory. I have moved the increment to below. the memcpy call to account for this. I hadn't thought of casting an array of structs; I'll give that a go. Do you have any insight as to why specifically the memcpy of the pulseOx.getIR() call is so much slower than the time it takes to retrieve those 4 bytes from the sensor?

use unsigned int for buffLen, because 15*3200 is more than int can take

Are you sure to have 512 byte of free RAM? The SDfat library holds a 512 byte buffer anyway, and another one for the file system itself. It physically writes to SD only full blocks anyway.

Please fix/remove that millisSet garbage...

Juraj Good catch, thanks! I've amended this above.
@DataFiddler I allegedly have about 5800 bytes left to play with. I'm aware SDfat utilizes a 512 byte buffer, but does that mean that every write() call pushes 512 bytes to the card, or that nothing is sent to the card at all until 512 bytes worth of write() are amassed?
Sorry millisSet() offended you, I've removed it. I tried to post just the relevant portions of the code but seem to have missed that variable in the initial post. Garbage is removed...

A write without flush or close only copies in memory, unless a 512 byte boundary is crossed and a different sector is used. BTW: sorry, did not notice you mentioned atmega2560

did unsigned int solve the problem?

unsigned int did not solve the problem, but did allow longer sets of loops. I implemented AnT's suggestion to create an array of structs and eliminated the memcpy command altogether in favor of write(meas), but this is even slower than using memcpy!


text:
Keeping Adafruit Feather charged
I'm creating a keyboard for someone using an Adafruit Feather 32u4 Bluetooth LE as the brains. The case I want to put in into would be hard to remove to charge the battery.
Can I use this USB LiIon/LiPoly charger to charge the LiPo battery and keep power to the board? And then unpluging from the USB mini-B would switch over to the battery?

From the very page you linked to:
"... we added a connector for any of our 3.7V Lithium polymer batteries and built in battery charging. You don't need a battery, it will run just fine straight from the micro USB connector. But, if you do have a battery, you can take it on the go, then plug in the USB to recharge. The Feather will automatically switch over to USB power when its available. We also tied the battery thru a divider to an analog pin, so you can measure and monitor the battery voltage to detect when you need a recharge."
So, the board has a charger and battery connector already built in.


text:
Using the same variable between if-statements within loop()
I wonder if there is a good way to use the same variable value between two different if-statements within the loop().
Within the Servomotor section of the code, I want to use the value from the first if-statement's RewardTime within the next if-statement's RewardTime. Thus far, I cannot find a way to do it.
(Since there is no communication between these variables right now, the RewardTime remains 0).
I'd appreciate a certain guidance in this matter.
#include <Servo.h> // Library required for the servomotor (Make sure to download if not in the library)
#include <Button.h> // Library required for the microswitch (Make sure to download if not in the lbrary)

// PARAMETERS
// COPY THESE VALUES IN PROCESSING CODE MANUALLY
// Explanation: To prevent possible Arduino-Processing overflow. Do not want too much information flow between Arduino and Processing.
const float Scale = 1 * 1000; // milliseconds
const float Base = 1 * 1000; // milliseconds

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

unsigned long previousMillis = 0;
bool switching = false;
int State = LOW;

char BirdSings = 0;
//static float RewardTime = 0;

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

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

   // SERVOMOTOR
   // Get times when the feeder is covered (food present) and uncovered (food not present)
    unsigned long currentMillis = millis();
    while (Serial.available() > 0) {
    unsigned long currentMillis = millis();
   if (Serial.read() == '\n') { // When there is a song
     //Serial.println(2); // Food is uncovered
     previousMillis = currentMillis; // 0 becomes the current milli
     static float RewardTime = (Serial.parseFloat() * Scale) + Base; // CALCULATE THE RewardTime HERE
     Serial.println(RewardTime);
     if (State == LOW)
      State = HIGH;
     else
      State = LOW;
    }
   }

  if (State == HIGH && switching == false){
    Servo1.write(0); // 0 degree
    unsigned long secondCurrentMillis = millis();
    if (secondCurrentMillis - previousMillis > RewardTime) { // USE THE ABOVE RewardTime HERE
      switching = true;
      previousMillis = secondCurrentMillis;
      if (State == LOW)
        State = HIGH;
      else
        State = LOW;
    }
  }
  if(State == LOW && switching == true){
    Servo1.write(90); // 90 degrees
    switching = false;
    //Serial.println(3); // Food is covered
    }
}

Make the variable global, thus put it outside the loop function; also you don't need the static keyword anymore.
float RewardTime = 0;

Than inside your first if statement, remove the static float keywords:
RewardTime = (Serial.parseFloat() * Scale) + Base;

Some other tips:

normally local variables do not start with a capital (so rewardTime is like most coding conventions)
Always use brackets.
if (State == LOW)
  State = HIGH;
else
  State = LOW;

Change to:
  if (State == LOW)
  {
    State = HIGH;
  }
  else
  {
    State = LOW;
  }

However, to make it more simpler, use the ternary operator, you can change it to:
State = (State == LOW ? HIGH : LOW);

Which means: if some condition ? Do this : Else do this;

HIGH / LOW and true / false are identical, so State = ! State;is sufficient.

@DataFiddler But you shouldn't be dependent on the values inside a library. Suppose in future they will change the values to 20 and 30 instead of true/false. If the Arduino API intended a Boolean they should have used a Boolean type.

if they ever change change the definition of HIGH and LOW, I will stop using Arduino. They even don't dare to change the return type of digitalRead, which is a good decision.

@DataFiddler … good point, and I fully agree it would break many sketches. But they really should use a Boolean as input argument type, or an enumeration EPinState (LOW, HIGH) or something like that.

That question mark is called Elvis operator for the people that doesn't know, it's similar as an if else but with some compiler it could be faster (This happens on intel for example with the cmov instruction)

@alessandromrc I think the Elvis operator is indeed the more informal name (thanks for the addition). Btw, I think it's in general not a good idea to write for performance reasons unless known beforehand or when needed (afterwards), it just reads easier (if it fits on a single line mostly).

Since you defined it within the first if statement, it is only "in-scope" or defined within that block. To make it visible to both if statements, define it in the next outer block that contains both if statements - in this case, somewhere between void loop(){ and if (Serial.read()...


text:
Porting "far" flash memory access from Arduino Mega to Due
I have a project that runs on the Arduino Mega 2560 which takes up almost the complete amount of flash memory available (https://github.com/fredlcore/bsb_lan/blob/master/BSB_lan.ino). Because of this, I'm planning on migrating the project to the Arduino Due.
My main problem at the moment is to port those functions that access flash memory in the "far" memory area (>64k) for which on the one hand various _PF functions (like strncpy_PF) are provided, and on the other hand a dummy "pointer" type uint_farptr_t (which is actually uint32_t) is available.
My problems now are twofold:

While the _PF functions have specific definements for the Due which under "normal" circumstances should work without changes in the code, they expect different variable types. For example, strncpy_PF takes uint_farptr_t (i.e. uint32_t) as argument for src on the Mega, it expects a const char * on the Due. Compilation thus results in lots of errors.
For the Mega to be able to access char arrays (which are 16 Bit on the Mega) above 128k, I need a rather dirty workaround (see function calc_enum_offset() in the code linked above). Basically I need to take the memory address of a 16 Bit char pointer and make some calculations to get the final address from which I read the strings. On the Mega, I can do these calculations on the basis of uint_farptr_t and then read from the calculated memory address with pgm_read_byte_far() for example. On the Due, however, pgm_read_byte_far(addr) is translated to (*(const unsigned char *)(addr)). Again, the uint32_t type does not fit this.

Do you have any suggestions on how I should tackle these issues with the least amount of code?

the pointer type on Due has 32 bits so const char* is uint32_t. I would use ifdefs to skip use of far variants

@Juraj: Hm, uint_farptr_t on the Mega is also uint32_t, and I use it to access the memory locations of the strings in flash rom (which I calculate based on the (truncated) 16-Bit char pointer. Is there a way to access the memory locations of the const char* texts on the Due in a similar way, say by getting the memory address of the const char*, make some calculations on this address and read (e.g. a character) from the resulting memory location? This may be not/less efficient, but if it would enable me to keep most of my code running on two architectures, it would be what I'm looking for.

The Due, being ARM, is a von Neumann architecture. That means that it has no concept of "progmem", "near" or "far" pointers, etc.  There are no _P or _PF variant functions, but the Arduino core provides simple stubs as a convenience.
Instead all "flash" memory access is just simple memory accesses using const.
The best thing you can do is to use preprocessor macros to select between AVR and ARM code:
#if defined(__AVR__)
    strncpy_PF(buffer, enumstr+c, sizeof(buffer));
    buffer[sizeof(buffer)-1] = 0;
    outBufLen+=sprintf(outBuf+outBufLen,"%d - %s",val,buffer);
#else
    outBufLen += sprintf(outBuf + oufBufLen, "%d - %s", val, cmdtbl[i].enumstr);
#endif

In fact, given the huge amount of "hackiness" involved in that program with regards the cmdtbl, and the massive amounts of code that just aren't needed on the Due, it may be better to start a fresh program that is Due specific and delete the swathes of unneeded code.

Thank you for the useful example, and yes, a rewrite would certainly be the best option, but given the fact that the current user base with the Arduino Mega is several hundred users whom I would still like to provide with bugfixes without having to maintain two code-bases, that's not an option. Applying your example in varying forms to all the 100+ occurrences of the ...far... functions would make the code a complete mess. So I'm still hoping whether there is a way to solve this on the level of the functions being called and then handled there based on the respectivee architecture?

You could put everything into wrapper functions then supplicate those functions for each platform. Move the different platforms to different include files, then only include the right for for the current architecture.

That sounds like a feasible plan, thank you!


text:
ESP8266 keeps restarting after a few hours of use and dead after 1 month of use
I have tried to make a water heater relay controlled by an ESP8266 (NodeMCU v1.0). The ESP8266 is connected to a central WiFi in my house, the ESP8266 also has its own WiFi so I use STA and AP mode for the ESP8266. The ESP8266 will give a webpage when its IP address accessed. I have been able to use it for about a month, even though sometimes the ESP8266 restarting after 4-24h of use. But then after 1 month the ESP8266 just die. I have tried to upload blink led, and it doesn't work, even though I can upload the program successfully using Arduino IDE.
Here is my Arduino ESP8266 code
#include <NTPClient.h>
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Arduino.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <FS.h>
#include <Hash.h>
#include <Ticker.h>
#include <SD.h>
#include <SPI.h>

//Client
#define STASSID "******"
#define STAPSK  "*********"

//Host
#define APSSID "**********"
#define APPSK "*********"

#define relayheaterPin D1
#define relaypompaPin D2
#define temperaturPin 3
#define CS_PIN  D8
#define voltagedetectorPin 1

IPAddress staticIP(192, 168, 100, 186); //ESP8266 static ip
IPAddress gateway(192, 168, 100, 1); //IP Address of your WiFi Router (Gateway)
IPAddress subnet(255, 255, 255, 0); //Subnet mask
IPAddress DNS(8, 8, 8, 8); //DNS
IPAddress DNS2(8, 8, 4, 4); //DNS

OneWire oneWire(temperaturPin);
DallasTemperature sensors(&oneWire);

AsyncWebServer server(80);

Ticker timer_pompa;
Ticker get_Temperature;

File dataFile;
String dataMessage;
unsigned long seeks;

WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP);
unsigned long timeOffset = 25200;
String formattedDate;
String dayStamp;
String timeStamp;

const char* ssid = STASSID;
const char* password = STAPSK;
const char* APssid = APSSID;
const char* APpassword = APPSK;

bool b_Pompa = 0;
bool b_Pompa_Temp=0;
bool b_Heater = 0;
unsigned int i = 0;

unsigned long ret=0;
float f_temp;
unsigned long ul_max_temp = 38;
unsigned long ul_min_temp = 36;

void v_SD_setup() {
  if (!SD.begin(CS_PIN)) {
//    Serial.println("An Error has occurred while mounting SD Card");
    return;
  }
  dataFile = SD.open("temperature.csv", FILE_WRITE);
  dataFile.close();
}

void v_OTA_setup () {
//  Serial.begin(115200);
  WiFi.persistent(false);
  WiFi.disconnect(true);
  WiFi.mode(WIFI_AP_STA);
  WiFi.softAP(APssid, APpassword);
  WiFi.config(staticIP, subnet, gateway, DNS, DNS2);
  WiFi.begin(ssid, password);
  while (WiFi.waitForConnectResult() != WL_CONNECTED) {
    delay(5000);
    ESP.restart();
  }
//  Serial.println(WiFi.localIP());
//  Serial.println(WiFi.softAPIP());
  ArduinoOTA.onStart([]() {
    String type;
    if (ArduinoOTA.getCommand() == U_FLASH) {
      type = "sketch";
    } else { // U_SPIFFS
      type = "filesystem";
    }
  });
  ArduinoOTA.begin();
}

void getTimeStamp() {
  timeClient.update();
  formattedDate = timeClient.getFormattedDate();

  // Extract date
  int splitT = formattedDate.indexOf("T");
  dayStamp = formattedDate.substring(0, splitT);

  // Extract time
  timeStamp = formattedDate.substring(splitT+1, formattedDate.length()-1);
}

// Write the sensor readings on the SD card
void logSDCard() {
  dataFile = SD.open("temperature.csv", FILE_WRITE);
  dataMessage = String(dayStamp) + "T" + String(timeStamp) + "," +
                String(f_temp) + "," + String(b_Pompa) + "," + String(!digitalRead(voltagedetectorPin))+ "\r\n";
  if (dataFile) {
    dataFile.print(dataMessage);
    dataFile.close();
  }
}

//Send Temperature, Pump, and Heater Condition Data from SD Card until EOF
String s_Read_Data(){
  String dataString= "Waktu, Temperature, Pompa, Heater\r\n";
  unsigned int len;
  dataFile = SD.open("temperature.csv");
  if (dataFile) {
    if (dataFile.size()>5580) {
      seeks=dataFile.size()-5580;
    } else {
      seeks=0;
    }
    dataFile.seek(seeks);
    while(dataFile.available()) {
     dataString+=dataFile.readString();
    }
    dataFile.close();
  } else {
    dataString="Error Opening File";
  }
  return dataString;
}

char* v_Pompa_On(){
   b_Pompa=1;
   digitalWrite(relaypompaPin, b_Pompa);
   return "Pompa is ON";
}

char* v_Pompa_Off(){
   b_Pompa=0;
   digitalWrite(relaypompaPin, b_Pompa);
   timer_pompa.detach();
   return "Pompa is OFF";
}

char* v_Heater(){
   b_Heater=!b_Heater;
   digitalWrite(relayheaterPin, b_Heater);
   if(digitalRead(voltagedetectorPin) ==0) {
    return "Heater is ON";
   } else {
    return "Heater is OFF";
   }
}

char* c_Heater_Condition(){
   if(digitalRead(voltagedetectorPin) ==0) {
    return "Heater is ON";
   } else {
    return "Heater is OFF";
   }
}

char* c_Pompa_Conditon(){
   if(b_Pompa ==1) {
    return "Pompa is ON";
   } else {
    return "Pompa is OFF";
   }
}

void v_getTemp () {
//  char buf[20];
  sensors.requestTemperatures();
  f_temp = sensors.getTempCByIndex(0);
  if (f_temp!=-127) {
   getTimeStamp();
   if (dayStamp!="1970-01-01") {
    logSDCard();
   }
  }
}

char* c_getTemperature () {
  char buf[20];
  sensors.requestTemperatures();
  sprintf(buf, "%f", sensors.getTempCByIndex(0));
  return buf;
}

void v_Timer_Pompa() {
  if (b_Pompa ==0) {
     v_Pompa_On();
  }
  if (ret<=0) {
    v_Pompa_Off();
    timer_pompa.detach();
    return;
  }
  ret--;
}

char* v_Pompa_10_min () {
  ret=10;
  v_Timer_Pompa();
  timer_pompa.attach(60, v_Timer_Pompa);
  return "Pompa is ON";
}

void v_server_setup () {
  // Initialize SPIFFS
  if(!SPIFFS.begin()){
//    Serial.println("An Error has occurred while mounting SPIFFS");
    return;
  }
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(SPIFFS, "/index.html");
  });
  server.on("/phone", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(SPIFFS, "/index-phone.html");
  });
  server.on("/pompa_timer", HTTP_POST, [](AsyncWebServerRequest * request){},NULL,[](AsyncWebServerRequest * request, uint8_t *data, size_t len, size_t index, size_t total) {
     char str[30];
     char *ptr;
     for (size_t i = 0; i < len; i++) {
       str[i]=data[i];
     }
     ret = strtol(str, &ptr, 10);
     v_Timer_Pompa();
     timer_pompa.attach(60, v_Timer_Pompa);
     request->send(200);
  });
  server.on("/max_temp", HTTP_POST, [](AsyncWebServerRequest * request){},NULL,[](AsyncWebServerRequest * request, uint8_t *data, size_t len, size_t index, size_t total) {
     char str[30];
     char *ptr;
     for (size_t i = 0; i < len; i++) {
       str[i]=data[i];
     }
     ul_max_temp = strtol(str, &ptr, 10);
     request->send(200);
  });
  server.on("/min_temp", HTTP_POST, [](AsyncWebServerRequest * request){},NULL,[](AsyncWebServerRequest * request, uint8_t *data, size_t len, size_t index, size_t total) {
     char str[30];
     char *ptr;
     for (size_t i = 0; i < len; i++) {
       str[i]=data[i];
     }
     ul_min_temp = strtol(str, &ptr, 10);
     if (ul_min_temp<=ul_max_temp) {
        request->send(200, "text/plain", "Success!");
     } else {
        request->send(200, "text/plain", "Minimum Temperature has to be lower than Maximum Temperature");
     }
  });
  server.on("/read_data", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(200, "text/plain", s_Read_Data());
  });
  server.on("/time_left", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(200, "text/plain", (String)ret);
  });
  server.on("/heater_condition", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(200, "text/plain", c_Heater_Condition());
  });
  server.on("/pompa_condition", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(200, "text/plain", c_Pompa_Conditon());
  });
  server.on("/heater", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain",v_Heater() );
  });
  server.on("/pompa_on", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain",v_Pompa_On() );
  });
  server.on("/pompa_off", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain",v_Pompa_Off() );
  });
  server.on("/get_temperature", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain",c_getTemperature() );
  });
  server.on("/10_min_on", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain",v_Pompa_10_min() );
  });
  server.begin();
}

void setup() {
  //WiFi Setup
  v_OTA_setup();
  v_server_setup();
  v_SD_setup();

  //Pin Setup
  pinMode(relayheaterPin,OUTPUT);
  pinMode(relaypompaPin,OUTPUT);
  pinMode(temperaturPin,INPUT);
  pinMode(voltagedetectorPin,INPUT_PULLUP);

  //Sensors and time Setup
  sensors.begin();
  timeClient.begin();
  timeClient.setTimeOffset(timeOffset);

  //Get Sensors Reading
  v_getTemp();
  get_Temperature.attach(120, v_getTemp);
}

void loop() {
  ArduinoOTA.handle();
  if (WiFi.status() != WL_CONNECTED) {
    delay(5000);
    ESP.restart();
  }
  if ((b_Pompa ==1) && ((f_temp-ul_max_temp) <= 0)) {
    b_Pompa_Temp=1;
    b_Heater=1;
    digitalWrite(relayheaterPin, b_Heater);
  } else {
    if (b_Pompa_Temp==0) {
     if (f_temp<=ul_min_temp) {
       b_Heater=1;
       digitalWrite(relayheaterPin, b_Heater);
     } else if(f_temp>=ul_max_temp){
       b_Heater=0;
       digitalWrite(relayheaterPin, b_Heater);
     }
    } else {
      b_Heater=0;
      digitalWrite(relayheaterPin, b_Heater);
      b_Pompa_Temp=0;
    }
  }
}

Additionally, sometimes when I access ip_address/read_data I got no response, but after waiting for a while I got some response. Before the ESP8266 dies (after 1 month of use) when I accessed ip_address/read_data I got no response, and then when I restart the ESP8266 It just dies. Any idea why? 2 of my ESP8266s have died this past 2 months :(
Note: I powered my ESP8266 using LM7805 with supply from 12V 1A switching power supply.

one problem is the String class. the esp8266 arduino is always unreachable on network after a while even it works and accesses the network as client. that is a know issue and the solution is not merged into the library yet https://github.com/esp8266/Arduino/pull/6889

Is it possible for me to solve the String class problem by changing the String class into array of char? I have tried changing the string into array of char and getting the char from SD card file by using dataFile.readString().c_str(); but then the hardware wdt turns on and the esp restarts when I access ip_address/read_data.

How do you control the relay?

Exactly how are you connecting the microcontroller to the relay? Exactly how are you connecting the 5V power to the microcontroller?


text:
Error with led Blinking (avrdude: ser_open(): can't set com-state)
I am new with Arduino and I made something very basic and I don't know why it is not working . I placed the positive led in pin 13 and the negative in GND and wrote this code :
#define LED 13
void setup() {
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(LED, OUTPUT);
}

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

I verified if it 's connected to Arduino Uno and when I upload the code I have this errors :
Sketch uses 924 bytes (2%) of program storage space. Maximum is 32256 bytes.
Global variables use 9 bytes (0%) of dynamic memory, leaving 2039 bytes for local variables. Maximum is 2048 bytes.
avrdude: ser_open(): can't set com-state for "\\.\COM4"
An error occurred while uploading the sketch

Sometimes IDE has problems ? What I did wrong ?

Genuine Arduino or a cheap Chinese clone?

I bought a kit from keyestudio

It's this a bad company ?

Starting from https://forum.arduino.cc/index.php?topic=54796.msg2032153#msg2032153 someone seems to have found a solution.

so you didn't use a resistor and shorted the pin to ground with the LED? btw. the Uno has on board LED on pin 13 and Blink example does the same as your sketch

Yes. I followed this tutorial : https://www.youtube.com/watch?v=dnPPoetX0uw

Does this answer your question? avrdude ser_open() can't set com-state

Dp you have some older version of Uno, because R3 doesn't have a resistor on pin 13.

I have the same question on any sketch

You do not have a problem with LED blinking (although there seems a resistor missing for your led), but with uploading a sketch.
Hard test: switch off your computer, remove USB cable, switch on computer, check the COM port appearing when connecting the Arduino via USB cable. Then start IDE and try upload again.
Eventually something else was blocking the COM port.


text:
Which arduino will be suitable with bill acceptor
I want to connect a bill acceptor (protocol ID003) and 3 switches and an Ethernet shield to Arduino. I am building a system that accepts bill and pass on the information to our software. Which Arduino will be the best choice, we need something which will have lot of code and also communication should be fast.

ARDUINO MEGA 2560 REV3
ARDUINO DUE
Arduino Uno REV3

--Edit--
This is I want to create:
A bill acceptor connected with arduino. Arduino has 3 buttons. (1. Play button, 2. redeem cash button. 3rd is not necessary).
When user login on machine, I get the details of user account through an API.
When user inserts money in bill acceptor, it enables the play button and add money in users account (If user already has money in account, button will be enabled). User can play until his account is not empty (i.e. if user has 200 in account, he can play 10 times). User can earn or lose money.
I have to send this transaction detail through an API.
If user press redeem button, it will print a slip of account details (Total money in account)
I am using Python.
I need to know which arduino is suitable for this, Ethernet shield compatible with that arduino (I think I am going to use ARDUINO MEGA 2560 REV3, but I don’t know Ethernet shield compatible with this model).
Also I need some Idea how can I make this. This is first time I am using arduino and bill acceptor.

A "lot of code" isn't very specific; it's pretty hard to advise which board has enough memory. Same with "communication should be fast". Can you put any numbers to those? The Uno has about 28K of code space (at the assembly language level); it may be possible to translate that - very roughly - into lines of C++. They've shown serial speeds of 2M baud. On the other hand, a Mega isn't that expensive, has much more memory but probably similar serial capability. More details can get you a better answer.

Hi @JRobert, thanks for comment. I have edited question. Can you suggest something?

Is your board talking to Python on a PC or other device? Or do you mean to run Python on the Arduino board? If the latter, I expect you'll need more than an Uno. I use AtTinys, and Unos but keep one Mega available by for just this kind of project, where I don't know yet what resources I'll need. The Mega always has more than enough (for me, so far :), so I can get my project working right away, and decide later whether to port it to a smaller MCU.

Define 'lot of code', the Arduino Uno has 32 KB Flash, the Mega 256 KB.
Define 'fast', the Uno/Mega are 16 MHz, the Due 48 MHz
Three switches use 3 GPIO's, shouldn't be a problem on neither of them; the Mega has more GPIOs than the Uno, but both have plenty for your needs.
The Ethernet shield are available for all three
I don't know the 'bill acceptor', add a datasheet.

Conclusion: it depends on what is lot of code, and what is fast.

Hi, thanks for response, I have edited question. Can you suggest something?


text:
GSM module not working after power off
I am making a project on gsm module(sim 900a unofficial shield), when I will send a SMS led will turn ON. after uploading code, module works fine, and led turned ON after sending message. But when I power off sim900a and Arduino, and power on back, it's not working, led not power up after sending message, when I reupload sketches it is working fine, means every time after power off I need to upload code again, I am learning c and don't have much knowledge? Is my code right? Or some other fault?
#include <SoftwareSerial.h> //software serial library for serial communication b/w arduino & GSM

    SoftwareSerial mySerial(8, 9);//connect Tx pin of GSM to pin 8 of arduino && Rx pin of GSM to pin no 9 of arduino

    int led = 7;
    String message;

    void setup()
    {
      mySerial.begin(9600);   // Setting the baud rate of GSM Module
      Serial.begin(9600);    // Setting the baud rate of Serial Monitor (Arduino)
      delay(100);

      mySerial.println("AT+CNMI=2,2,0,0,0"); // AT Command to receive a live SMS
      delay(1000);
      pinMode(led,OUTPUT);
      digitalWrite(led,LOW);
    }

    void loop()
    {
      if (mySerial.available()>0){
      message = mySerial.readString();
      }

      if(message.indexOf("ON") > -1){
          Serial.println("LED ON");
         digitalWrite(led,HIGH);
         }
        else if(message.indexOf("OFF") > -1){

          Serial.println("LED OFF");
          digitalWrite(led,LOW);

      }

      delay(10);
    }

Circuit diagram

The GSM takes time to start up.  Your program needs to be far more complex than the simple "Throw commands at it and hope" method you are using.
First you need to query the modem repeatedly until it responds.  This is usually done with the AT command.  A sequence would look like:
Send: AT
(Wait for OK response or timeout)
Send: AT
(Wait for OK response or timeout)
Send: AT
(Wait for OK response or timeout)
Send: AT
(Wait for OK response or timeout)
Recv: OK

Once the modem has booted and is ready to receive commands you can start sending commands.  You shouldn't just "print and delay" though like you are at the moment. Instead you should send the command and then examine the response to see if the command worked ("OK") or failed ("ERR").

Is there any librery for it on GitHub, or do you have any prewritten code that work fine, I have not much knowledge of 'C', I am a farmer and my farm is 3 k.m. from my home, so I want to make water motor automatic that I want to control from my home,

@Devid The Arduino IDE comes with a GSM library bundled with it. I have never used it though, so I don't know if it works with the SIM900A.


text:
Arduino code for turning an led on by one clap and then off by one clap
I want my Arduino to turn on a LED when sound sensor detects a clap (noise) and keeps the LED on until the sound sensor detects another clap (noise) which turns the LED off.
int Sensor = A0;
boolean status_lights = false;

void setup() {
  pinMode(Sensor, INPUT);
  pinMode(13, OUTPUT);
}

void loop() {
  int status_sensor = digitalRead(Sensor);
  if (status_sensor == 0)
  {
    if (status_lights == true)
    {
      status_lights = false;
      digitalWrite(13, LOW);
    }
    else {
      status_lights = true;
      digitalWrite(13, HIGH);
    }
  }
}

My sound sensor has 3 pins.
sound sensor details
EDIT: My code only turns on the led but dosen't turn it off when I clap.

you have no code that is used for debugging... at least print the value of status_sensor to see what it actually is

If the sound level is below the threshold, the DO pin of the sensor signals a high value. If the sound level exceeds the threshold, i.e you clap you hands, the DO is pulled to GND and the signal gets LOW for a short while. After this short while the signals gets HIGH again.
Now look at you loop:
void loop()
{
  int status_sensor = digitalRead(Sensor);

  if (status_sensor == 0)
  {
    // you enter this block if you clap your hands and the
    // mcu is fast enough to capture the signal / DO pin (LOW)
    // within the short time interval
    // I'm sure it is fast enough to enter this block multiple
    // times in the interval the clap is active.
    if (status_lights == true)
    {
      status_lights = false;
      digitalWrite(13, LOW);
    }
    else
    {
      status_lights = true;
      digitalWrite(13, HIGH);
    }
  }
}

You see, the LED is toggled as long as the LOW interval of the sensor is active (DO=LOW).
I interpret you statement "My code only turns on the led but dosen't turn it off when I clap." so, that the LED is on, when the program starts without a clap. That means that the environmental noise is loud enough to activate the sensor. Then the loop above is iterated permanently and you switch on and off the LED at a very fast speed. That's like you would apply a PWM waveform on the LED pin. The LED is on but dimmed to about 50%.
To find out if I'm right, just add a delay in the loop. My assumption seems to be correct, if the LED blinks with one herz (one time per second).  The you can adjust the sound threshold until the LED stops blinking.
void loop()
{
  int status_sensor = digitalRead(Sensor);

  // Add the delay here ..........
  delay(500);

  if (status_sensor == 0)
  {

If you have calibrated the sensor, remove the delay from the code and add a new delay after changing the LED states. That should be much shorter, because it's only there to ensure that you don't toggle the LED while the sensor is active.
    if (status_lights == true)
    {
      status_lights = false;
      digitalWrite(13, LOW);
    }
    else
    {
      status_lights = true;
      digitalWrite(13, HIGH);
    }
    // wait until the clap is over
    delay(100);

+1 for this code comment: "I’m sure it is fast enough to enter this block multiple times in the interval the clap is active." When you clap, it toggles the DO pin high and low multiple times, and it looks something like this: https://arduino.stackexchange.com/a/54495/37523

@VE7JRO The documentation of the sensor is not really helpful, so thank you for giving an example. I was not really sure whether the  use something like a  smoothing condenser. But obviously that's not the case. (73 Peter, DF4VB)


text:
ESP8266-01 Serial.print returns a blank given a valid string
I am currently trying to create a led matrix with ws2812b leds. I am using an uno on the rear of the display to control the leds and now I want to add wifi capabilities. Since I already had serial control implemented into the uno, I decided to use an ESP8266-01 to take wifi commands and then send them via serial to the uno. The problem is that no matter what I send to the ESP, it always prints a blank to to the uno.
The code for the ESP:

#include <ESP8266WiFi.h>

// config: ////////////////////////////////////////////////////////////

#define UART_BAUD 9600

#define MODE_AP // phone connects directly to ESP
//#define MODE_STA // ESP connects to WiFi router

#define PROTOCOL_TCP
//#define PROTOCOL_UDP

#ifdef MODE_AP
// For AP mode:
const char *ssid = "LedSign";  // You will connect your phone to this Access Point
const char *pw = "aaron"; // and this is the password
IPAddress ip(192, 168, 0, 1); // From RoboRemo app, connect to this IP
IPAddress netmask(255, 255, 255, 0);
const int port = 6969; // and this port
// You must connect the phone to this AP, then:
// menu -> connect -> Internet(TCP) -> 192.168.0.1:9876
#endif

boolean led = false;

String message;

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

#ifdef PROTOCOL_TCP
#include <WiFiClient.h>
WiFiServer server(port);
WiFiClient client;
#endif

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);

  delay(500);

  Serial.begin(UART_BAUD);

  #ifdef MODE_AP
  //AP mode (phone connects directly to ESP) (no router)
  WiFi.mode(WIFI_AP);
  WiFi.softAPConfig(ip, ip, netmask); // configure ip address for softAP
  WiFi.softAP(ssid, pw); // configure ssid and password for softAP
  #endif

  #ifdef PROTOCOL_TCP
  Serial.println("Starting TCP Server");
  server.begin(); // start TCP server
  #endif

  for (int i = 0; i < 10; i++)
  {
    Serial.println("Booting up");
    delay(100);
  }

}

void loop() {

  #ifdef PROTOCOL_TCP
  if(!client.connected()) { // if client not connected
    client = server.available(); // wait for it to connect
    if (led){
      pinMode(LED_BUILTIN,LOW);
      led = false;
      delay(100);
    }
    else
    {
      pinMode(LED_BUILTIN,HIGH);
      led = true;
      delay(100);
    }
    return;

  }

  // here we have a connected client

  if(client.available()) {
    String message;
    long time = millis();
    Serial.println("Message Recieved: ");
    while(client.available()) {
      message = client.readStringUntil('\n'); // read char from client (RoboRemo app)
      message.trim();
      //message+=c;
      if (millis()-time >= 200)
      {
        break;
      }
    }
    client.print("You typed: ");
    client.println(message);
    pinMode(LED_BUILTIN,LOW);
    delay(400);
    pinMode(LED_BUILTIN,HIGH);
    delay(400);
    pinMode(LED_BUILTIN,LOW);
    // now send to UART:
    delay(10);
    message.trim();
    message = message + '-';
    Serial.println(message);
    //Serial.println(message);
  }
  /*
  if(Serial.available()) {

    // read the data until pause:

    while(1) {
      if(Serial.available()) {
        buf2[i2] = (char)Serial.read(); // read char from UART
        if(i2<bufferSize-1) i2++;
      } else {
        //delayMicroseconds(packTimeoutMicros);
        delay(packTimeout);
        if(!Serial.available()) {
          break;
        }
      }
    }
    */
    // now send to WiFi:
    //client.write((char*)buf2, i2);
    //i2 = 0;
  //}
  #endif

}

The code for the uno (just for testing functionality of ESP, no leds):
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(13,OUTPUT);
  digitalWrite(13,LOW);
}

void loop() {
  // put your main code here, to run repeatedly:

  if(Serial.available() > 0)
  {
    String message = Serial.readStringUntil('-');
    message.trim();
    Serial.print("The message was: ");
    Serial.println(message);
    digitalWrite(13,HIGH);
    delay(200);
    digitalWrite(13,LOW);

    if (message.equals("h"))
    {
      for (int i = 0; i < 10; i++)
      {
        digitalWrite(13,HIGH);
        delay(50);
        digitalWrite(13,LOW);
        delay(50);
      }
    }
    Serial.flush();
  }

}

I have confirmed that the ESP is reading the data from TCP by having it print the string back at me. I know that the ESP is attempting to send the data because the led blinks indicating it triggered the if statement. I know that the uno is getting something over serial becasue the serial lights flash, the builtin led flashes (my code), and the uno prints back what it got to serial (though that is just a blank).
What the uno prints /
14:15:03.495 -> The message was:

I am at my wits end with this so any help is greatly appreciated.

When you print the String "The message was: " on the UNO, where do you read it? On your serial terminal? But then the Serial port is connected with the terminal over USB and also to the ESP via the pins 0 and 1. I fear that can not work. You can not connect two endpoints to the same serial port.  As the UNO has only 1 hardware serial. You have to use a SoftwareSerial to communicate with the ESP. Or you do not use the connection to the serial terminal on the PC. And access the returned string over the network connection by reading from serial on the ESB..

Yeah using software serial was a good point although that did not appear to be the issue. Is there anything else that this could be? I am still getting the same serial result on my computer.

Yes, there are more issues. But I must know, how you implemented the SoftwareSerial solution before I can give you an answer. I don't know which problems you has been solved with that solution.

I fixed the problem. My baud rates were mismatched. Thanks for the help.


text:
Nesting loops - if statement in a while loop
I have been trying many variations of code like this, cannot seem to get this to work with how I logically would think it would work.  Am I missing something with syntax or breaking some rules?  Everything works independently but not jointly.
int switchS = 0;
int var = 1;

void setup() {
    pinMode(1,INPUT);
    pinMode(7,OUTPUT);
    digitalWrite(7,LOW);
}

void loop() {
    switchS = digitalRead(1);
    while(var == 1)
    {
        digitalWrite(7,HIGH);
        delay(100);
        digitalWrite(7,LOW);
        delay(100);
        if(switchS == HIGH)
        {
            var = 0;
        }
    }
    delay(5000);
    var = 1;
}

I wrote an answer to what I think you are asking, but please be more specific in your question. "work with how I logically would think it would work" We cannot see in your head, so we don't know, what you are thinking how it should work. In every "does not work" question, you should clearly state, what you expected the code to do and what it actually does. That way we can provide way better answers.

I guess you want the while loop to exit, when the switch goes to HIGH. (You didn't explain this in your question)
Currently the variable switchS cannot ever change while the code is in the while loop. The variable var only changes, when switchS is HIGH. So, if switchS is LOW at the start of the while loop, you have an infinite loop.
Instead, you can actually read the switch state inside the while loop, not outside of it. The variable switchS will not automatically track the state of the switch. You have to explicitly read it. Like this variant of your code:
int switchS = 0;
int var = 1;

void setup() {
    pinMode(1,INPUT);
    pinMode(7,OUTPUT);
    digitalWrite(7,LOW);
}

void loop() {
    while(var == 1)
    {
        digitalWrite(7,HIGH);
        delay(100);
        digitalWrite(7,LOW);
        delay(100);
        switchS = digitalRead(1);  // I moved this line in the while loop, to read the switch on every loop iteration
        if(switchS == HIGH)
        {
            var = 0;
        }
    }
    delay(5000);
    var = 1;
}

Note: You are using pin 1 as input pin. On the Uno this is a Serial (UART) pin, which is used to communicate with the PC. If you have enough pins, that are free, you should not use pins 0 and 1, so that you don't block the serial communication, unless you really need it and know, what you are doing.

Yes that is what I was trying to do, I was just about to clarify but you already you answered.  Thank you so much, can't believe I missed that.

@eatsmypasta Please mark the answer.


text:
24v LED strip with common anode?
I have a 5m strip of 24v tunable white LEDs and I'm trying to figure out what I need set it up. There's a pad for V+ and then one for brightness and one for warmth. If I plug the V+ in V+ on a 24v supply and the two others to V-, the whole thing lights up full intensity. The strip draws 16 Watts per meter (80 for the whole thing). As I understand it, you vary the two anodes by varying the resistance to ground. I've seen some instructions that this can be done with PWM pins, but I'm assuming that given the voltage and current, no arduino or similar can handle that much. Do I need transistors then? What specs do I look for to understand the limitations?

please post a link to the product datasheet

I linked the product. It doesn't actually have a straightforward data sheet but it has all the specs.

There's a pad for V+ and then one for brightness and one for warmth. ... that is not quite correct ... the pads are V+, W and C ... W controls the warm color LEDs and C controls the cold color LEDs ... you will need a transistor to drive each of the two channels ... find a tutorial about driving RGB LED strips ... instead of three colors, you have only two colors

Your strip has 2 LEDs with different color temperature directly besides at the same spot for every element of the strip. So the adjusting of the overall color temperature is done by changing the relative brightness of both LEDs. If the LED with the warmer light is brighter, the overall color temperature will also be warmer. Common Anode means, that V+ is the connected to the positive pin (anode) of both LEDs, so it has to be connected to +24V. The electrical circuit is completed by connecting the pins W and C (Warm and Cold) to ground. To control the individual brightness of the warm and cold LED groups, you have to use PWM.
You are right, that an Arduino cannot handle currents this big. You need a transistor for this. I would suggest using a MOSFET, since this is the easiest and most efficient possibility. By one MOSFET for every channel (Warm and Cold), which is capable of handling the needed power (Important! Or you will fry the MOSFET). Also it should be a logic level MOSFET, that is well in saturation of the gate voltage for the output voltage of your Arduino. Connect the MOSFETs Drain pin to the channel on the strip, the Source pin to ground of your power supply and the Gate pin to a PWM pin of the Arduino. Also connect the ground of the power supply with the ground of the Arduino.
Now you can control the brightness of the Warm and of the Cold LEDs by adjusting the PWM duty cycle with the Arduino.

Or rather, by adjusting the ratio of the duty cycles between the warm and cool LED sets. If you set the cool pin to 100% and the warm pin to 0%, you'll get all cool light (100:0) If you set both to 100%, you'll get a 50/50 mix of warm and cool light (ratio of 1:1 between duty cycles)

So, presumably if I tie warm straight to ground and just air gap cool, I'd get warm

@jiggy Yes, thats correct


text:
Arduino I can't make this statement work
int val1 = 0;
byte val2 = 10;
int buttonPin = A0;
byte result = 0;

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

void loop() {
    val1 = digitalRead(buttonPin);

    if (buttonPin == HIGH) {
        result = result + val2;
        result = result + 10;
    }
    else
    {
        digitalWrite(val1, LOW);
    }

    Serial.print("STATE   ");
    Serial.print(val1);
    Serial.print("    ");
    Serial.print(result);
    Serial.println();

    delay(100);
}

why did you post the code? ... what does the title of your post mean?

I trying to increase the value of result by 10 every time when the button is high

you have not said what is the problem ... it is like taking your automobile to a mechanic and saying "it has a problem" ... what do you think that the mechanic would repair?

what does button is high mean?

Please [edit] your question instead of putting additional information in a comment. You don't want to waste our time, do you? You hope that we think about your problem. BTW, what is your question?

One problem of your code is  that you are comparing the pin number of the button to HIGH, instead of the read button state. Will write an answer, when you made your question more clear, since I think this will not solve your problem completely

I'm sorry to say that your code is a complete train wreck. I know, you're still learning, but there's so many errors there that even a novice who had spent just a few minutes reading the documentation and examples would have avoided that it's just completely unrecoverable.

I appears you want to increment the result by val2 each time the button is pressed.  If you want to wire it up this way you can but there are potential issues with this, such as not catching each time you press the button, or thinking you pressed the button twice when you accidentally held it down for more than 100ms.  The code for this method is below:
const int buttonPin = A0;
bool buttonState = LOW;
int val = 10;
int result = 0;

void setup()
{
  pinMode(buttonPin,INPUT);
  Serial.begin(115200);
}

void loop()
{
    buttonState = digitalRead(buttonPin);

    if (buttonState == HIGH)
    {
        result = result + val;
    }

    Serial.print("STATE:   ");
    Serial.print(buttonState);
    Serial.print("\t");
    Serial.print("RESULT:  ");
    Serial.print(result);
    Serial.println();

    delay(100);
}

The way to prevent double counts or missing counts would be to use interrupts.  Later I may write that one up if you need that instead.
Good Luck!

I use void function to increase value. Thanks for you guys help