text:
USB disconnects when using a capacitor
I'm currently working with some WS2812B LEDs and tried out adding a capacitor to be safe from voltage spikes (was recommended by Adafruit). I noticed that a soon as I connect a capacitor between 5V and ground that the USB is disconnect from the PC (Windows Usb disconnect sound plays). I wondered why and tried another setup. This time just the capacitor between 5V and ground. Nothing else. According to my knownledge this isn't a short (capacitor is intact) and therefor this setup should be valid. Again the same thing happens: USB disconnects...
I really don't know why this happens but want to understand it. The capacitor I use is rated 16V 1000 mF (electrolytic in case this is relevant). The capacitor is also connected the right polarity. What forces the USB to disconnect (and let Windows play the USB disconnect sound). Am I may damaging the USB Port somehow and therefor a disconnect is forced as a security measurement?
Oh yeah... Using an Arduino Uno R3 made by Elegoo.
Hope you can help me out,
Tmirror

put the capacitor on the other end of the LED strip; it does more good there anyway by smoothing the borderline low voltage situations at the end (possibly buying you several more stable pixels), and it uses the strip's intrinsic resistance to limit inrush current spikes. That said, you still might need a smaller capacitor if you want to power over USB and avoid the protection mechanisms. You might also try a powered USB hub; those are often a lot more forgiving than built-in ports, which are better protected because blowing a built-in really sucks...

The USB specifications allow a maximum of 10uF total capacitance on the USB power lines. By putting 1000uF you have given it 100x more than is allowed.
This causes a massive inrush current and the USB host (your computer) sees it as a short circuit, so it shuts off the power in a panic to protect itself.
A capacitor does have a role to play in helping to remove power supply noise caused by power-hungry and noisy devices like WS2812B LEDs, but just slapping it across the power supply pins isn't going to really help.
Instead you should increase the impedance of the power supply to the noisy device(s) and use a capacitor to reduce the impedance again. This will help to preferentially draw current from the capacitor to supply the LEDs while smoothing out the draw from the main supply over time.
A simple circuit is to use a resistor with a capacitor:

simulate this circuit – Schematic created using CircuitLab
The values I show there for the resistor and capacitor are pretty random. The smaller the resistor the more demand will be put on the power supply. The bigger the resistor the more demand will be put on the capacitor. If the resistor is too big the capacitor won't be able to store enough power to run the LEDs, and too much voltage will be dropped across  it. If the capacitor is too small it won't be able to store enough power to run the LEDs. Tuning those values depends very much on the amount of noise there is and the current draw of the LEDs.
You must also make sure the resistor can handle the amount of power dissipated by the current flowing through it.

If we'd need a 10R (or greater) to limit current to the official 500ma @5v, we can only fully turn on 2 rgb LEDs before 1.2v is lost through the resistor and the blue LEDs and ws2812b start having issues with undervoltage...

@dandavis Like I said, the values I show are random. Choose suitable values depending on the situation.

Sure, but unless the situation is "power a strip of 2 LEDs", there's no values that work...

If you draw 400mA through a 0.25Ω resistor it will drop just 0.1V. https://uk.farnell.com/multicomp/mcknp0w2j025ka10/res-0r25-5-500mw-axial-wirewound/dp/1903673


text:
Faster TimerOne with Teensy 4.0 (600MHz)
I have a teensy 4.0 which runs at 600MHz, and is double superscaler (i.e. can execute two instructions per clock cycle, sometimes). I need an interrupt to happen faster than every microsecond. I've calculated that it's possible for the processor to run the my code at that speed with some reasonable overhead. Can TimerOne (or similar) be set to produce an interrupt more than once per microsecond?
Thanks in advance.

Are you talking about the library TimerOne or about the timer itself?

@chrisl well I've been using the TimerOne library but if the only way to get a faster interrupt is to not use that library then that's OK with me.

https://forum.pjrc.com/

You can use the TeensyTimerTool for this. It provides a generic interface to the hardware timers (TMR, GPT, PIT) and 20 software timers. Since the coupling of the timer peripherals to the ARM core is rather inefficient, the software timers might be a better fit for sub micro second interrupts.
If you prefer the hardware timers I suggest to use a GPT timer (also supported by the lib). You can configure it to use a 150MHz clock instead of the standard 24MHz clock. So something like 2MHz interrupt rate should be feasible.
Documentation can be found here: https://github.com/luni64/TeensyTimerTool/wiki

I had a similar problem with the Teensy 3.5.
I found that using the "Periodic Interrupt Timer (PIT)" let me generate interrupt every 300 ns.
I imagine that with a Teensy 4.0, it must be possible to generate an interrupt every 100 ns.
Here is the code which works for me on my Teensy 3.5,
with comments in french and some references in the comments.
I test the signal on an oscilloscope.
// ex00305_Timer_pit0_isr_rapide.ino
/*

FONCTIONNE TRES BIEN

Le signal n'est pas très stable, mais acceptable.
J'imagine que d'autres routines d'interruption perturbe la précision, comme la routine millis()

L'instruction suivante améliore la stabilité. visiblement.
NVIC_SET_PRIORITY(IRQ_PIT_CH0, 0);

Le but est de tester l'utilisation du Timer1 .c.f
/home/bg/Arduino/Teensy/Teensy_3_5_manual_K64P144M120SF5RM.pdf
Page 1083, Chapter 41 : "Periodic Interrupt Timer (PIT)"

Pour la gestion des timers PIT, c.f.
====================================
https://github.com/loglow/PITimer/blob/master/PITimer.cpp

********************************************************************************** */

#define PINOUT1 34
#define LEDRED  24
#define LEDYELLOW  25
#define LEDGREEN  26

volatile byte bEtat = 0;

void setup() {
    //============
    pinMode(PINOUT1, OUTPUT);
    digitalWriteFast(PINOUT1, HIGH);

    pinMode(33, OUTPUT);
    pinMode(34, OUTPUT);
    pinMode(LEDRED, OUTPUT);  digitalWriteFast(LEDRED, LOW);
    pinMode(LEDYELLOW, OUTPUT);  digitalWriteFast(LEDYELLOW, LOW);
    pinMode(LEDGREEN, OUTPUT);  digitalWriteFast(LEDGREEN, LOW);

    //if (SIM_SCGC6_PIT == 0b100000000000000000000000) digitalWriteFast(LEDYELLOW, HIGH);
    SIM_SCGC6 |= SIM_SCGC6_PIT; // C.f. page 317.  PIT Clock Gate Control   SIM_SCGC6_PIT == 0b100000000000000000000000

    // C.f. : /home/bg/.arduino15/packages/teensy/hardware/avr/1.58.1/cores/teensy3/kinetis.h
    // #define NVIC_ENABLE_IRQ(n) (*((volatile uint32_t *)0xE000E100 + ((n) >> 5)) = (1 << ((n) & 31)))
    // enable IRQ Interrupt
    NVIC_SET_PRIORITY(IRQ_PIT_CH0, 0); // Haute priorité, pour ne pas être perturbé par d'autres interrupt. Amélioration visible !
    NVIC_ENABLE_IRQ(IRQ_PIT_CH0);
    PIT_TCTRL0 = 3; // 0b011;  // enable Timer 0 interrupts ; start Timer 0   IRQ_PIT_CH0 == 48  Dans #elif defined(__MK64FX512__)
    //if (IRQ_PIT_CH0 == 48) digitalWriteFast(LEDGREEN,  HIGH);

    // Efface le flag du timer, pour permettre d'autres interruptions, nécessaire au départ
    PIT_TFLG0 = 1;

    // L'ordre des instruction a de l'importance !
    //""""""""""""""""""""""""""""""""""""""""""""
    PIT_MCR = 0;  // turn on PIT
    //PIT_LDVAL0 = 600-1;  // == 10 micro secondes setup timer 0 for xxx cycles Fréqu = 60 MHz  dt = 16.666 ns
    //PIT_LDVAL0 = 120-1;  // == 2 micros second
    //PIT_LDVAL0 = 60-1;   // == 1 micros second
    //PIT_LDVAL0 = 30-1;   // == 500 ns
    //PIT_LDVAL0 = 24-1;   // == 400 ns
    //PIT_LDVAL0 = 21-1;   // == 350 ns
    //PIT_LDVAL0 = 20-1;   // == 333 ns
    //PIT_LDVAL0 = 18-1;   // == 300 ns
    PIT_LDVAL0 = 120-1;
} // setup

void loop() {
    //===========
} // loop

void pit0_isr() {  // C.f. mk20dx128.c
    //===============
    // J'espère pouvoir gérer un temps

    // Efface le flag du timer, pour permettre d'autres interruptions
    // Doit être mis en début de routine !!!
    PIT_TFLG0 = 1;

    if (bEtat) {
        digitalWriteFast(PINOUT1, HIGH);
        //digitalWriteFast(LEDRED,  HIGH);
        bEtat = 0;
    }
    else {
        bEtat = 1;
        digitalWriteFast(PINOUT1, LOW);
        //digitalWriteFast(LEDRED,  LOW);
    }

} // pit0_isr

source: Stack Exchange

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

sort: votes


text:
What is the equivilent of PORTx for Teensy (4.0)?
I've seen people use code like PORTB |= 0x1 << 6 to set the sixth bit of PORTB in arduino. I understand that this is significantly faster than using digitalWrite. How can this be done using a modern Teensy (i.e. 3.6 or 4.0) if at all?

Step one: Read the datasheet for the chip on the board. Step two: implement what you have learned from step 1. Step three: profit.

@Majenko one slight problem with that: how do I know which pins correspond to which ports? Also, I find the datasheets like that very confusing so there's no guarantee that I'd be able to figure out exactly what's going on.

You need to relate the information in the datasheet to the source code for the core and board definition.

For the Teensy 3.6 you need to get to grips with section 63.3 of https://www.nxp.com/docs/en/reference-manual/K66P144M180SF5RMV2.pdf

DDRA is equivalent to GPIOA_PDDR. PORTA is GPIOA_PDOR, PINA is GPIOA_PDIR

@Majenko alright thanks very much I'll read up about that.

For those chips there are particular memory addresses that correspond to particular bits and the setting or clearing operations. Rather than a read, or, write three-instruction cycle, you can set or clear the bit with a single write instruction at a special bit-specific address. There's some mention of it in "5.2.1 Aliased bit-band regions" in the manual @Majenko listed.  Also, look into Teensy's digitalWriteFast(pin,val) instruction which optimizes into the equivalent code per the 63.3 section @Majenko referenced.

All Teensies support digitalWriteFast out of the box. digitalWriteFast compiles to just setting the bit in the right port register. You can not do that faster by direct register manipulation.
However, if for some reason you do want to manipulate the registers directly here the pin/gpio relation for the T4. (Generated by the sketch described here: https://github.com/luni64/TeensyTimerTool/wiki/Avoid-PWM-timer-clashes")
Pin |  GPIO Reg  |  PWM timer
----|------------|-------------
00  |  GPIO6_03  |  FLEX_PWM1
01  |  GPIO6_02  |  FLEX_PWM1
02  |  GPIO9_04  |  FLEX_PWM4
03  |  GPIO9_05  |  FLEX_PWM4
04  |  GPIO9_06  |  FLEX_PWM2
05  |  GPIO9_08  |  FLEX_PWM2
06  |  GPIO7_10  |  FLEX_PWM2
07  |  GPIO7_17  |  FLEX_PWM1
08  |  GPIO7_16  |  FLEX_PWM1
09  |  GPIO7_11  |  FLEX_PWM2
10  |  GPIO7_00  |  QUAD1
11  |  GPIO7_02  |  QUAD1
12  |  GPIO7_01  |  QUAD1
13  |  GPIO7_03  |  QUAD2
14  |  GPIO6_18  |  QUAD3
15  |  GPIO6_19  |  QUAD3
16  |  GPIO6_23  |  no pwm
17  |  GPIO6_22  |  no pwm
18  |  GPIO6_17  |  QUAD3
19  |  GPIO6_16  |  QUAD3
20  |  GPIO6_26  |  no pwm
21  |  GPIO6_27  |  no pwm
22  |  GPIO6_24  |  FLEX_PWM4
23  |  GPIO6_25  |  FLEX_PWM4
24  |  GPIO6_12  |  FLEX_PWM1
25  |  GPIO6_13  |  FLEX_PWM1
26  |  GPIO6_30  |  no pwm
27  |  GPIO6_31  |  no pwm
28  |  GPIO8_18  |  FLEX_PWM3
29  |  GPIO9_31  |  FLEX_PWM3
30  |  GPIO8_23  |  no pwm
31  |  GPIO8_22  |  no pwm
32  |  GPIO7_12  |  no pwm
33  |  GPIO9_07  |  FLEX_PWM2
34  |  GPIO8_15  |  FLEX_PWM1
35  |  GPIO8_14  |  FLEX_PWM1
36  |  GPIO8_13  |  FLEX_PWM1
37  |  GPIO8_12  |  FLEX_PWM1
38  |  GPIO8_17  |  FLEX_PWM1
39  |  GPIO8_16  |  FLEX_PWM1

#### Sorted by PWM timer
Pin |  GPIO Reg  |  PWM timer
----|------------|-------------
12  |  GPIO7_01  |  QUAD1
11  |  GPIO7_02  |  QUAD1
10  |  GPIO7_00  |  QUAD1
13  |  GPIO7_03  |  QUAD2
18  |  GPIO6_17  |  QUAD3
15  |  GPIO6_19  |  QUAD3
14  |  GPIO6_18  |  QUAD3
19  |  GPIO6_16  |  QUAD3
24  |  GPIO6_12  |  FLEX_PWM1
01  |  GPIO6_02  |  FLEX_PWM1
25  |  GPIO6_13  |  FLEX_PWM1
34  |  GPIO8_15  |  FLEX_PWM1
35  |  GPIO8_14  |  FLEX_PWM1
36  |  GPIO8_13  |  FLEX_PWM1
37  |  GPIO8_12  |  FLEX_PWM1
38  |  GPIO8_17  |  FLEX_PWM1
39  |  GPIO8_16  |  FLEX_PWM1
00  |  GPIO6_03  |  FLEX_PWM1
08  |  GPIO7_16  |  FLEX_PWM1
07  |  GPIO7_17  |  FLEX_PWM1
09  |  GPIO7_11  |  FLEX_PWM2
04  |  GPIO9_06  |  FLEX_PWM2
05  |  GPIO9_08  |  FLEX_PWM2
06  |  GPIO7_10  |  FLEX_PWM2
33  |  GPIO9_07  |  FLEX_PWM2
28  |  GPIO8_18  |  FLEX_PWM3
29  |  GPIO9_31  |  FLEX_PWM3
23  |  GPIO6_25  |  FLEX_PWM4
22  |  GPIO6_24  |  FLEX_PWM4
03  |  GPIO9_05  |  FLEX_PWM4
02  |  GPIO9_04  |  FLEX_PWM4
27  |  GPIO6_31  |  no pwm
17  |  GPIO6_22  |  no pwm
26  |  GPIO6_30  |  no pwm
30  |  GPIO8_23  |  no pwm
31  |  GPIO8_22  |  no pwm
32  |  GPIO7_12  |  no pwm
21  |  GPIO6_27  |  no pwm
20  |  GPIO6_26  |  no pwm
16  |  GPIO6_23  |  no pwm

#### Sorted by GPIO register:
Pin |  GPIO Reg  |  PWM timer
----|------------|-------------
01  |  GPIO6_02  |  FLEX_PWM1
00  |  GPIO6_03  |  FLEX_PWM1
24  |  GPIO6_12  |  FLEX_PWM1
25  |  GPIO6_13  |  FLEX_PWM1
19  |  GPIO6_16  |  QUAD3
18  |  GPIO6_17  |  QUAD3
14  |  GPIO6_18  |  QUAD3
15  |  GPIO6_19  |  QUAD3
17  |  GPIO6_22  |  no pwm
16  |  GPIO6_23  |  no pwm
22  |  GPIO6_24  |  FLEX_PWM4
23  |  GPIO6_25  |  FLEX_PWM4
20  |  GPIO6_26  |  no pwm
21  |  GPIO6_27  |  no pwm
26  |  GPIO6_30  |  no pwm
27  |  GPIO6_31  |  no pwm
10  |  GPIO7_00  |  QUAD1
12  |  GPIO7_01  |  QUAD1
11  |  GPIO7_02  |  QUAD1
13  |  GPIO7_03  |  QUAD2
06  |  GPIO7_10  |  FLEX_PWM2
09  |  GPIO7_11  |  FLEX_PWM2
32  |  GPIO7_12  |  no pwm
08  |  GPIO7_16  |  FLEX_PWM1
07  |  GPIO7_17  |  FLEX_PWM1
37  |  GPIO8_12  |  FLEX_PWM1
36  |  GPIO8_13  |  FLEX_PWM1
35  |  GPIO8_14  |  FLEX_PWM1
34  |  GPIO8_15  |  FLEX_PWM1
39  |  GPIO8_16  |  FLEX_PWM1
38  |  GPIO8_17  |  FLEX_PWM1
28  |  GPIO8_18  |  FLEX_PWM3
31  |  GPIO8_22  |  no pwm
30  |  GPIO8_23  |  no pwm
02  |  GPIO9_04  |  FLEX_PWM4
03  |  GPIO9_05  |  FLEX_PWM4
04  |  GPIO9_06  |  FLEX_PWM2
33  |  GPIO9_07  |  FLEX_PWM2
05  |  GPIO9_08  |  FLEX_PWM2
29  |  GPIO9_31  |  FLEX_PWM3

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


text:
Error compiling to teensy 3.6
Problem:
In short, the Arduino IDE won't compile a sketch for the Teensy 3.6. It gives the error:
exec: "A:\\arduino-1.8.5\\hardware\\teensy/../tools/teensy_post_compile": file does not exist
Error compiling for board Teensy 3.6.

What I have tried
-Re-installing teensyduino (And yes, I have it installed, along with a compatible Arduino IDE (version 1.8.5))
-completely wiping the IDE and re-installing
-using a different USB cable
Other information
The OS I'm using is Windows 10
A broken Teensy is not out of the question, as I have been doing some soldering on it and I may have slipped or something, although I don't think that's the problem
Thanks in advance.

are you running the IDE from a floppy disk? .... A: is the disk name for the floppy disk

It's my USB stick, I assigned it the letter A: so that it's easy to remember

Also so other programs that reference it (e.g. my python programs) don't have to be changed on the whim of windows

I found a fix, it's not elegant or easy to use, but it works.
Steps to take
-Install a fresh version of teensyduino
-Make a copy of [arduino directory]/hardware/tools and save it anywhere as a backup (sometimes weird, buggy things happen)
-Make a copy of teensy.exe from the tools folder, and put it in the same directory as arduino.exe
-every time you run arduino.exe (don't double-click on a .ino file), first start teensy.exe and everything should work.
Sometimes, the tools directory gets deleted (It just seems a bit buggy), if that happens copy the backup and paste it where it should be ([arduino directory]/hardware/tools)
Also occasionally teensy.exe gets deleted, so make sure to have a backup of that as well.


text:
VS2019CE/VisualMicro project won't compile without specific reference
I have a small project to test a Sparkfun MPU9250 breakout board.  'Class_MPU9250BasicAHRS_t3.h', 'MPU9250BasicAHRS_t3.h' and 'Class_MPU9250BasicAHRS_t3.cpp' are all in the local project folder. Compile fails with an 'undefined reference' error at any reference to the Class_MPU9250BasicAHRS myIMU object  unless I add 'Class_MPU9250BasicAHRS_t3.cpp' to the project as a 'Source File' in the Solution Explorer window.
Why is this?  I thought the compiler was smart enough to look for a .cpp file with the same name as an #include'd header file.
TIA,
Code attached:
/*
    Name:       Teensy_MPU9250_Test.ino
    Created:    9/15/2019 11:46:10 AM
    Author:     FRANKWIN10\Frank
*/

/*  All this program does is display heading values from a Sparkfun MPU9250
    breakout board at the default (0x68) I2C address
*/

#include "Class_MPU9250BasicAHRS_t3.h" //extracted all #defines from MPU9250BasicAHRS_t3.ino
#include <i2c_t3.h>
#include <elapsedMillis.h>

elapsedMillis sinceLastPrint;
Class_MPU9250BasicAHRS myIMU;

int pulsePin = LED_BUILTIN;//04/10/18 added per-step pulse pin parameter
bool bFirstTime = true;
const long MSEC_PER_PRINT = 100;

void setup()
{
    Serial.begin(115200);
    delay(3000); //delay required to wait for Serial object creation
    //Wire.begin();

    pinMode(LED_BUILTIN, OUTPUT);
    Wire.begin(I2C_MASTER, 0x00, I2C_PINS_18_19, I2C_PULLUP_EXT, 400000);
    Wire.setDefaultTimeout(200000); // 200ms

    //IMU init & test
    Serial.println("Starting program...");
    Serial.println("Initializing 9250 IMU...");
    myIMU.init9250IMU();
    Serial.println("Done...");
}

void loop()
{
    float hdg_deg = myIMU.GetIMUHeadingDeg();
    if (bFirstTime)
    {
        bFirstTime = false;
        Serial.printf("Msec\tHdg\n");
    }

    if (sinceLastPrint > MSEC_PER_PRINT)
    {
        Serial.printf("%lu\t%4.2f\n", millis(), hdg_deg);
        sinceLastPrint -= MSEC_PER_PRINT;
    }
}

it is probably by design, so that you could have files in the same folder that would not be processed by the compiler .... useful if you are testing different versions of the same file

Hmm, hadn't thought of that angle....


text:
How does this MPU6050 Example Code Work?
I'm trying to understand the logic for one of the example Arduino programs for the MPU6050 IMU module. The entire program can be found here.  There is an if() statement inside a while() loop inside the normal Arduiono sketch loop() function, and I'm having real trouble figuring out the logic.  The ISR and relevant code section is shown below:
volatile bool mpuInterrupt = false;     // indicates whether MPU interrupt pin has gone high
void dmpDataReady()
{
    mpuInterrupt = true;

}

    void loop()
    {
        // if programming failed, don't try to do anything
        if (!dmpReady) return;

        // wait for MPU interrupt or extra packet(s) available
        while (!mpuInterrupt && fifoCount < packetSize)
        {
            if (mpuInterrupt && fifoCount < packetSize)
            {
                // try to get out of the infinite loop
                fifoCount = mpu.getFIFOCount();

                //pulse the pin
                digitalWrite(Loop_While_Section_Pin, HIGH);
                delay(1);
                digitalWrite(Loop_While_Section_Pin, LOW);
            }
            // other program behavior stuff here
        }

        // reset interrupt flag and get INT_STATUS byte
        mpuInterrupt = false;
        mpuIntStatus = mpu.getIntStatus();

        // get current FIFO count
        fifoCount = mpu.getFIFOCount();
        if (fifoCount < packetSize)
        {
            //Lets go back and wait for another interrupt. We shouldn't be here, we got an interrupt from another event
            // This is blocking so don't do it   while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();
        }
        // check for overflow (this should never happen unless our code is too inefficient)
        else if ((mpuIntStatus & _BV(MPU6050_INTERRUPT_FIFO_OFLOW_BIT)) || fifoCount >= 1024) {
            // reset so we can continue cleanly
            mpu.resetFIFO();
            //  fifoCount = mpu.getFIFOCount();  // will be zero after reset no need to ask
            Serial.println(F("FIFO overflow!"));

            // otherwise, check for DMP data ready interrupt (this should happen frequently)
        }
        else if (mpuIntStatus & _BV(MPU6050_INTERRUPT_DMP_INT_BIT))
        {
            // read all available packets from FIFO
            while (fifoCount >= packetSize) // Lets catch up to NOW, in case someone is using the dreaded delay()!
            {
                mpu.getFIFOBytes(fifoBuffer, packetSize);
                // track FIFO count here in case there is > 1 packet available
                // (this lets us immediately read more without waiting for an interrupt)
                fifoCount -= packetSize;
                //digitalWrite(Loop_ReadBytesSection_Pin, !digitalRead(Loop_ReadBytesSection_Pin)); //toggle the pin

                //pulse the pin
                digitalWrite(Loop_ReadBytesSection_Pin, HIGH);
                delay(10);
                digitalWrite(Loop_ReadBytesSection_Pin, LOW);
            }

    #ifdef OUTPUT_READABLE_YAWPITCHROLL
            // display Euler angles in degrees
            mpu.dmpGetQuaternion(&q, fifoBuffer);
            mpu.dmpGetGravity(&gravity, &q);
            mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
            Serial.print("ypr\t");
            Serial.print(ypr[0] * 180 / M_PI);
            Serial.print("\t");
            Serial.print(ypr[1] * 180 / M_PI);
            Serial.print("\t");
            Serial.println(ypr[2] * 180 / M_PI);
    #endif

    // blink LED to indicate activity
            blinkState = !blinkState;
            digitalWrite(LED_PIN, blinkState);
        }
    }

It appears that the only way the 'if()' condition can be met is if the 'mpuInterrupt' variable managed by the ISR changes from FALSE to TRUE between the 'while()' condition evaluation and the 'if()' condition evaluation, which doesn't make a whole lot of sense to me.  In addition, the 'fifoCount' variable is only incremented inside the 'if()' section, which makes the second half of both the 'while()' and 'if()' conditions a little strange too.
I do want to note that this example program DOES WORK, and if I instrument the 'if()' section to pulse a hardware pin whenever it executes, I do see pulses following many (but not all) hardware interrupt occurrences.  So I know for sure the 'if()' statement DOES execute - but this seems a very 'Rube Goldbergian' way to go about it.
Any illumination would be appreciated ;-).

at first glance, it looks like the first while statement has a misplaced closing brace ... i think that the closing brace should be placed right after the opening brace

@jsotola That does not make sense either, because fifoCount will also be read shortly after that. I would say, this is simply wrong code and that the case "extra packets available" is not actually covered here. I guess this does not happen often either.


text:
How do I synch the Arduino PID library with an external timer for turn-rate control?
I have been trying to use the Arduino PID library for controlling the rate of turn (in deg/sec) of a wall-following robot.
The robot's operating system uses TIMER5 on an Arduino MEGA2560 to update a number of time-sensitive parameters (heading, front/back/left/right distances, etc) which are used throughout the code. For turn rate control, the difference between the current and previous headings (appropriately modified for 0/180 transitions) is multiplied by 10 to get deg/sec, and then this value is the 'input' to a PID. The PID output is a speed control to the wheels to achieve the desired turn rate setpoint.
Unfortunately, the current Arduino PID library has an internal timer (that can be changed, but not disabled) which has it's own idea of time.  In addition, the PID library's internal timer isn't available to the outside world - it is only used in PID::Compute().
The typical code configuration for using a PID is something like the following:
loop()
{
    //lots of other stuff
    if(TIMER5 ISR has been triggered)
    {
        //compute turn rate = 10*delta_heading
    }

    if(myPID.Compute()) //the internal timer is used inside this function
    {
       //use the PID output to control something (like wheel speeds)
    }
}

loop() runs at max speed, but myPID.Compute() only generates a new output when the internal PID timer elapses (otherwise it returns immediately without doing anything).  However, the turn rate input is being computed on a different schedule, leading to unpredictable behavior.
A possible solution is:
loop()
{
    //lots of other stuff

    if(myPID.Compute()) //the internal timer is used inside this function
    {
        New_Hdg_Val = GetNewHdgVal();
        turn_rate = ComputeTurnRate(New_Hdg_Val, Prev_Hdg_Val);
        Prev_Hdg_Val = New_Hdg_Val;

       //use the PID output to control something (like wheel speeds)
    }
}

So now the turn rate is computed on the same time intervals as PID::Compute(), which looks OK, as long as the timer value being used by the PID is the same as the TIMER5 ISR value being used by the rest of the program; clunky, inelegant, but maybe OK.
Unfortunately, because the PID computes a new output value inside PID::Compute(), the new value computation comes BEFORE the turn rate computation, which means the turn rate being used to produce the new output uses turn rate information that is AT LEAST 100mSec out of date (assuming the default 100mSec PID sample time setting) - ouch!!
So, how do others use the Arduino PID library in systems with an external (to the PID library) timing source?

I don't know how others use the PID Lib ;-). Without having thougt much about the problem: How about computing the turn rate in each loop cycle? Outside of the  the if(myPID.Compute()) block. Does it cause a problem, if it is computed before every myPID.Compute call? You waste a small amount of computing time, but you got the most actual values for the turn rate.

Peter, I certainly could do that. The computation is trivial, but getting the heading measurement from the MPU6050 is not, and there isn't any guarantee that a (blocking) MPU6050 measurement won't start just before the PID's internal timer would have elapsed, meaning that now the PID::Compute() cycles aren't periodic anymore.  This is a big problem because the internal PID math assumes periodicity.

I don't think reading the MPU is a problem. Even if you read all values from it (I don't know if that's the case) you can reach a sampling rate of 100 HZ. That means max. 10 ms per read out. And if you need the value for the compute() you have to read the MPU before the PID executes, so it blocks the PID in any way.  The Compute Method of the PID works with millis() and a sample interval of 100 msec by default. If that starts max. 10  msec later, who cares? And, you do "lots of other stuff" in the loop function before it. How much time does that need?  ;-)

I looked into the code of the compute method, and honestly I  am not very impressed of it. The author needs constant time intervals, because he uses a trick to save a division and a multiplication (derivative, integral). But now every delay in the loop can result in errors in the integral and derivative.  He claims that industrial controller run best within constant intervals.  But an industrial controller runs  on a real time systems that garantees fix intervals. And the Arduino loop  provides no real time feature. Especially, if there is a lot of other stuff performed.

If I would need a PID controller, I would write my own version. The author links to a piece of code I would prefer to use.  http://brettbeauregard.com/blog/2011/04/improving-the-beginners-pid-introduction/  (but without the "time interval"  improvements)

You sync it by calling the myPID.Compute() function in your external timer handler function.  If your loop function is lengthy, move your time-critical functions to a timer handler.

I use TIMER5 on the Mega 2560 to run everything that is time-sensitive, including PID calculations.  I use a custom PID_calcs function that mimics the internal workings of PID.Compute(), and PID_calcs is called each time TIMER5 is fired, guaranteeing equal time intervals.


text:
ShieldBuddy TC275 as a drop-in replacement for MEGA 2560?
I have an autonomous wall-following robot based on a Mega2560, that is just about maxed out in terms of memory usage and speed.  I'm starting to have weird intermittent failures with previously working code; a function will work fine in isolation (same hardware, but only the minimum required code to run just that one function), but not when used with the full program running, and other issues.
I ran across this article about the ShieldBuddy TC275, which purports to be pin-compatible with the Due (which I believe is pin-compatible with the Mega 2560, but I can't use the Due due to 5V compatibility issues), and MUCH faster, even if only Core0 is used.
I realize it is quite costly relative to other Arduino projects, but that's not a factor here.  Anyone have experience with this board as a replacement for a Mega2560?
TIA,
Frank

If it was mostly-working on a 2560 this would be overkill (but entertaining overkill). Level-shifters eliminate 3.3/5V issues, though, or split processing between multiple boards, like using an Arm-based board for computational chores and one or more 5V Arduinos for IO. But the ShieldBuddy's base-level support looks solid--only question would be regarding third-party library support. I'll know more in a week ;)

Ah, would you keep us posted on your progress then?  I spent some time on the ShieldBuddy forum, and there appear to be some problems with 'free entry tool chain' licenses expiring. (https://aurduino.boards.net/thread/251/free-entry-chain-license-expired)

Oooo no; ok, I'll keep an eye out and see what can be figured out.


text:
How do I temporarily disable TIMER5 Interrupts?
I have a fairly complex autonomous robot program that is getting into trouble when executing controlled turns.  I constructed a very small program to test just the turns, and this works fine.  When I port the turn algorithm into the main program, however, it behaves erratically, and I suspect the culprit is a TIMER5 interrupt ISR that is in the main program but not in the test program.
To troubleshoot, I added the TIMER5 ISR code to the test program, and I want to be able to enable and disable the ISR using keyboard commands, to see if I can cause the anomalous behavior with the ISR enabled, and prevent it by disabling the ISR.
From reading about TIMER interrupts, it appears that setting TIMSKx (TIMSK5 in my case) to 0 will disable the ISR, and setting bit 0 to 1 (using TIMSKx |= OCIExA) will enable it. I have a 'CheckForUserInput()' routine which allows me to input commands from the keyboard, so I added a 'T' command, as follows:
switch (incomingByte)
{
case 0x54: //ASCII 'T'
case 0x74: //ASCII 's'
    Serial.println(F("Toggle TIMER5 Enable/Disable"));
    if (TIMSK5 == 0)
    {
        Serial.println(F("Enable TIMER5"));
        TIMSK5 |= OCIE5A;
        mySerial.printf("TIMSK5 = %x\n", TIMSK5);
    }
    else
    {
        Serial.println(F("Disable TIMER5"));
        TIMSK5 = 0;
        mySerial.printf("TIMSK5 = %x\n", TIMSK5);
    }
    break;

I have an LED set up to blink each time the ISR fires, and I can see that I can stop the ISR from firing reliably with the first 'T' input, but I can't reliably restart it with the second 'T' command, even though I can tell from the printouts that the proper piece of code executed, like in the following output
Opening port
Port open

Checking for MPU6050 IMU at I2C Addr 0x69
MPU6050 connection successful
Initializing DMP...
Enabling DMP...
DMP ready! Waiting for MPU6050 drift rate to settle...
MPU6050 Ready at 0.52 Sec
End of test - Stopping!
I received: 63
ENTERING COMMAND MODE:
0 = 180 deg CCW Turn
1 = 180 deg CW Turn
A = Back to Auto Mode
S = Stop
F = Forward
R = Reverse

       Faster
    8
Left 4  5  6 Right
    2
       Slower
Got D
Got A
Got 74
Toggle TIMER5 Enable/Disable
Disable TIMER5
TIMSK5 = 0
Got D
Got A
Got 74
TEnabling DMP...
DMP ready! Waiting for MPU6050 drift rate to settle...
MPU6050 Ready at 0.52 Sec
End of test - Stopping!
I received: 63
ENTERING COMMAND MODE:
0 = 180 deg CCW Turn
1 = 180 deg CW Turn
A = Back to Auto Mode
S = Stop
F = Forward
R = Reverse

       Faster
    8
Left 4  5  6 Right
    2
       Slower
Got D
Got A
Got 74
Toggle TIMER5 Enable/Disable
Disable TIMER5
TIMSK5 = 0
Got D
Got A
Got 74
Toggle TIMER5 Enable/Disable
Enable TIMER5
TIMSK5 = 1
Got D
Got A

I'm sure I'm doing something wrong in the way I am attempting to re-enable the TIMER5 ISR, but I really can't see it.  Anyone have a clue?
TIA,
Frank

You wrote:

TIMSK5 |= OCIE5A;

You mean
TIMSK5 |= _BV(OCIE5A);

or, equivalently,
TIMSK5 |= 1 << OCIE5A;

Hmm, not sure I understand.  The 'TIMSK5 |= OCIE5A' line comes directly from my currently-working code as the last line of the TIMER5 interrupt setup block, so I'm pretty sure it's correct.  The 'TIMSK5 = 0' line will reliably stop the ISR from firing, so I'm pretty sure it is correct as well.

Do you mean that the 'TIMSK5 |= _BV(OCIE5A);' should be used to re-enable the ISR, instead of 'TIMSK5 |= OCIE5A'

@user3765883, OCIE5A is just #define OCIE5A  1.  That is, it is the index or place number of the bit within TIMSK5 and not the mask value that you need for use with |=.

Aw, rats!  I mis-read the TIMERx setup code.  What I thought was 'TMSK5 |= OCIE5A;' was actually 'TMSK5 |= (1 << OCIE5A);' which (I think) is the equivalent of 'TIMSK5 |= _BV(OCIE5A);'  Sorry for wasting your time :(


text:
How to control Neopixel LEDs in parallel?
Imagine a collection of LEDs (Neopixel or otherwise) labeled 2 through 12. There may be more than 11 LEDs, so repeat numberings are allowed. I want a simple way to control them from a single Arduino based on their label. So e.g. I should be able to implement a function whose arguments are a label value and an RGB value, and which turns all LEDs of that label value to the given RGB value. Most importantly, the solution has to be order-independent; that is, I should be able to re-wire the LEDs (or equivalently, scramble around the hex labels) in any manner, and still have everything work without rewriting any code. (For context, my goal is to make a custom Settlers of Catan edition, where the labels on each hex light up when their die value is rolled.)
I know I can't just use Neopixels out of the box, since the addressing depends on the order in which they're wired. So I assume I need to hack together a way for each LED to "know" its label, wire them all in parallel, and then write a custom library to . But I have no idea how to get each LED to know its label without having an entire Arduino for each LED, which would take up way too much space. (I'd like to fit everything in roughly the volume of a typical Catan hex label; think 2-3 quarters stacked together.)
I'm fairly comfortable with Arduinos, but I'm an electronics noob. Is it possible to reprogram the Neopixel controller? Or is there a tiny logic board I can hook up to a Neopixel or dumb LED that would do the job? Anything else I'm missing?

Neopixels are generally wired in a sequence. Can you please clarify how you are planning to wire these ones up?

How do you plan on connecting the tiles (electrically)?  You could just have a 12 pin connector on each of the sides of the tiles (actually 14 as you’d need Vcc and Gnd too). Or have a small micro controller, like an attiny85 on each tile and a regular rgb led. And control them over for example I2C.

what does this mean? based on their label

each LED to "know" its label .... they do not know .... the LEDs accept the first 24 bits after it is reset, and passes any other bits to the next LED ... after a reset, the second LED does not get any data until the first LED has "absorbed" the first 24 bits .... it is like a bunch of people and a deck of colored cards where each person takes a card from the top of the deck (each card represents a 24bit color)

Nick, that's part of the question. They need to be swappable in the way that regular Neopixels aren't. So e.g. wired in parallel.

jsotola, yes, I know. That's why I said "I know I can't just use Neopixels out of the box".

@Gerben, thanks, that's super helpful -- I didn't know about the ATTiny85, and that sounds like the tiny logic board I was looking for. If you want to write that as an answer (with any other tips or thoughts you have), I'd be happy to mark it as the solution.

it makes no real sense to do a hardware solution to a software problem ......  scramble around the hex labels you can do that in an array with the LEDs connected in series ..... i think that you will still have to do that with each LED separated ......... please draw two or three diagrams of the iterations of the LED labels (how they change from one roll of the dice to the next roll)

It will not be easy to “re-wire the LEDs [...] and still have everything
work without rewriting any code.” Those LEDs are not that smart, and the
only way to address them is by the order in which the color data is sent
through the data line.
What you can do, however, is write the code is such a way that rewiring
requires only a minimal change in the code. I would use an array to
map the LED indices to their labels. Something like this:
const uint16_t LED_COUNT = ...;

// Map LED indices along the strip to hex labels.
const uint8_t ledLabels[LED_COUNT] = {
    2, 2, 2, 2,  // LEDs 0 to 3 are labeled "2"
    8, 8, 8, 8,  // LEDs 4 to 7 are labeled "8"
    // etc...
};

Then, assuming your LED strip is declared as follows:
const uint8_t LED_STRIP_PIN = ...;
Adafruit_NeoPixel ledStrip(LED_COUNT, LED_STRIP_PIN);

the “function whose arguments are a label value and an RGB value, and
which turns all LEDs of that label value to the given RGB value” can be
quite easily written:
// Turn all the LEDs sharing that hex label to the given color.
void setHexColor(uint8_t label, uint32_t color)
{
    for (uint16_t n = 0; n < LED_COUNT; n++)
        if (ledLabels[n] == label)
            ledStrip.setPixelColor(n, color);
    ledStrip.show();
}

Now, if you rewire the strip, you just need to update the ledLabels
array and recompile. If you can manage to send that information to your
Arduino while it's running (a serial connection, an IR link, an SD card
inserted in an appropriate socket, whatever...), then you could even
have a procedure where the Arduino updates the array itself. Obviously
the const qualifier should then be removed. But you now have to devise
a way to “tell” the Arduino about your wiring.

The data wires of individually addressable LEDs of various descriptions are typically wired as a daisy chain, with each LED driver having input and output for the data (and clock). Each LED driver will then manipulate the signal it sends onward to trick the next LED into thinking it is the first in the chain.
Most libraries to drive them can easily have a few 100 LEDs it can driver at a time depending on available RAM.


text:
The Capacitive Sensor library on a D1 Mini
I want to set up a hand-made capacitive sensor on a D1 Mini, as in this tutorial, so that I can get specific capacitive readings. But I couldn't get the CapacitiveSensor library to work with the D1 Mini. Just to make sure I wasn't crazy, I fired up an Arduino Nano knockoff, and the library worked just fine.
I found a thread from early 2017 on this topic, which had various suggestions, none of which worked.
Does anyone know either how to make this library work with a D1 Mini, or another efficient way of getting capacitive readings on digital pins on a D1 Mini?

which pins are you using?

I've tried every combo I could think of. I know to avoid D0 / D3 / D4 / D8 (but tried them anyway).

Actually it looks like the answer was in the early 2017 thread all along. I switched to a 400k resistor and it works! (I've only verified this just for pins 5 -> 6, although I'd expect it works for any combination of pins not including D0 / D3 / D4 / D8.)
However, a caveat here -- it doesn't work well. With an Arduino and a ~6m resistor, you can sense a change in capacitance from several inches away, with a nice continuous increase in capacitance as you get closer. At least for me, the 400k resistor had very low operational range, only maybe 1/2 in. or so, and even then the differences were subtle. But increasing to a 600k resistor replicated the initial problem -- I just got the "-2" error message consistently. And going down to a 200k resistor just decreased the range as you'd expect. So there seems to be a very narrow operational range of resistance for the D1 Mini, with less utility than the Arduino.


text:
Can Arduino uno adjust input square wave duty, phase and frequency with just timer-counter?
Requirement:

I have input 4KHz pulse input
Divide it's frequency in half
Arbitrarily adjust phase
Arbitrarily adjust duty
Out put the modified pulse

My solution (CPU):
uint8_t cnt = 0;
uint16_t t1 = 235;
uint16_t t2 = 5;
String cmd;

void setup() {
  pinMode(3, OUTPUT);
  pinMode(2, INPUT);

  Serial.begin(9600);
  delay(500);
  attachInterrupt(digitalPinToInterrupt(2), rising_edge, RISING);
  Serial.println("PWM init");
}

void loop() {
  if (Serial.available() > 0) {
    cmd = Serial.readString();

    if (cmd.substring(0,8) == "setdelay"){
      t1 = cmd.substring(9).toInt();
      Serial.print("setting delay to ");
      Serial.print(t1);
      Serial.println(" us");
    }
    else if (cmd.substring(0,7) == "sethigh"){
      t2 = cmd.substring(8).toInt();
      Serial.print("setting high time to ");
      Serial.print(t2);
      Serial.println(" us");
    }
  Serial.flush();
  }
}
void rising_edge() {
  cnt = cnt + 1;
  if (cnt >= 2) {                           //divide by 2
    delayMicroseconds(t1);
    digitalWrite(3,HIGH);
    delayMicroseconds(t2);
    digitalWrite(3,LOW);
    cnt = 0;
  }
}

However this makes heavy use of CPU, and I need to use CPU for something else.Is it possible to implement all this with TC ?
Thanks in Advance !

You could use the incoming clock pulses as an external (asynchronous) clock source for timer2. See the ASSR register in the datasheet, for starters. You can't change the duty cycle with only this method. Though you use use an additional timer in "one-shot mode", but that would still require interrupts.

this makes heavy use of CPU, and I need to use CPU for something else

The issue with this code is that is heavily uses the CPU for busy
waiting rather than for doing useful work. You should try to get rid of
those waiting loops:

Serial.readString(): see Majenko's blog post Reading Serial on the
Arduino

delayMicroseconds(): for this, you can indeed use a timer.

For the pulse generation, you can keep roughly the same logic as your
existing code: output a single pulse every other time a rising edge is
sensed on the input. This pulse can be conveniently generated by
Timer 1 on pin 9 by using a PWM mode and stopping the timer
after a single cycle. I would use inverting PWM mode, with the timer
starting at zero on the input pulse:

at t1 microseconds, a compare match sets the output HIGH

at t1+t2 microseconds, the timer overflow sets the output LOW, and
the overflow interrupt stops and resets the timer

Here is a tentative, untested implementation:
// Set the pulse timings. To be called from loop() on user's request.
void set_timings(uint16_t t1, uint16_t t2)
{
    uint16_t ocr1a = t1 * 16 - 1;        // initial time in LOW state
    uint16_t icr1 = (t1 + t2) * 16 - 1;  // timer period
    noInterrupts();  // protect critical section
    OCR1A = ocr1a;
    ICR1 = icr1;
    interrupts();
}

// Configure Timer 1. To be called from setup().
void setup_timer() {
    DDRB  |= _BV(PB1);    // set pin digital 9 = PB1 = OC1A as output
    TCCR1A = _BV(COM1A0)  // PWM on OC1A, inverting mode
           | _BV(COM1A1)  // ditto
           | _BV(WGM11);  // mode 14: fast PWM, top = ICR1
    TCCR1B = _BV(WGM12)   // ditto
           | _BV(WGM13)   // ditto
           | 0;           // stopped
    TCNT1  = 0;           // reset
    TIFR1  = _BV(TOV1);   // clear overflow flag
    TIMSK1 = _BV(TOIE1);  // enable overflow interrupt
    set_timings(235, 5);  // initial timings
}

// Interrupt triggered by a rising edge of the input.
void on_rising_edge() {
    static uint8_t count;
    if (++count % 2) return;   // divide by 2
    TCCR1B |= _BV(CS10);       // start timer, clock @ F_CPU
}

// Stop and reset the timer when it overflows.
ISR(TIMER1_OVF_vect) {
    TCCR1B = 0;  // stop
    TCNT1  = 0;  // reset
}


text:
Size limitation on char Array on ESP8266
I'm creating a log of events, stored as a txt file. If it matters, I'm using ESP8266.
To display the log of each IOT, I'm publishing the txt file to a disgnated MQTT topic for all my IOT devices (later on to Telegram ). For sorting ( new first and old last ) I read each line into char array, post it to MQTT, and save it back to txt file.
Currently char array is defined as: char log_array[20][200] - meaning I'm keeping a log of 20 records, of 200 chars long.
Is it the right way ( declare a char array ) ? are there any limitation for size of array ( say 200 records )
Guy

That method looks fine to me. Are you having a specific problem with it, or are you just sanity checking?

@Majenko both. Since I do not initiate the char array, but only define it I'm worry that define it to 200 entries ( or more ) will cause sporadic crashes, ones which I will not be able to track

If you initialize it as a global then it will go in the BSS. That gets initialized to 0, so your array will be filled with 0. Since 0 is the "End Of String" marker you just end up with 20 empty strings of length 0.  If it's a local variable it'll be on the stack, and then will be filled with who knows what. In that case initializing it to 0 with memset(log_array, 0, 20*200); will do the same job.

@Majenko it will be defined as part of my iot library - an instance which is defined globally ( does it mean' defined globally ? )

In that case it should be in the BSS in which case it should be all 0. You can force that by adding the memset into the constructor of your class (I assume you're using a class?).

@Majenko yes, it is a class

Then I can't see a problem. You're using <4kB on a chip with 80kB of RAM (though not contiguous blocks), which is nothing really.


text:
Selecting the Right GPIOs
I've bought this 4 relay ESP8266 board to active lights and window shades.
In an odd way - its relays are not pre-connected to a certain IO's but let you choose which IOs will operate relays (by jumpering desired IOs). See Item below.
.
To operate my design, 4 inputs and 4 outputs are needed.
Exposed IOs are: io0,io2,io4,io5,io12,io13,io14,io15,io16.
while 9 IOs available only 8 are needed. I use randomnerdtutorials.
Misfits:

io0 and io2 can not serve as inputs since switch will fail boot (designed inputs are toggles),
io16 and io2 as outputs, are HIGH on boot, causing it to turn on for a fraction of second every boot (which turns on light or sliding window shades) - which I want to avoid.

which leaves:

Inputs: io16, io5,io4,io13
Outputs: io0,io14,io12,io15

Questions:

Is pins selection is OK ?
Why io15 is colored yellow and will it affect its use as an output?

3.io16 the only will be OK as input ?
4.io0 as an output (Relay)? since at reset all relays are powered off (want to be sure).

For Question 2, I guess GPIO15 is yellow because the pin must be low at boot time. It would be OK, for example, to power a led which is wired on the LOW side but not to sink one wired on the HIGH side.
Question 3 is not very clear.

why is "misfit 1" an issue? If you write your own code, you can ignore inputs during startup and choose the startup condition yourself.

@6v6gt Question2: Will it /Can it affect an output ? I guess not ( so why is it yellow ? ), Question 3 - table does not say if IO16 if it will fail on boot ( assigning it as input, can be toggled LOW).

@hennep you are not correct. Boot will fail, no mater what the code will be.

@guyd, most modern embedded processors can configure pins in software for multiple purposes. So, if you need the I2C serial bus to talk to an external chip you couldn't use GPIO 5 and 4.  But if you don't need to use the I2C bus you can use GPIO 5 and 4.  Is this the type of Answer you were looking for?  Let us know and someone can write up a more complete Answer.

@guyd A pin is not defined as an output (using pinMode() ) until the boot activity has finished and the sketch begins to run. Important only is that you don't connect anything to the pin which may violate its required startup condition. Hence, for GPIO15, it would be OK to connect a LED between it and the GND power rail because the pin would be LOW at boot time. It would not be OK to connect a LED between the 3.3v rail and GPIO15.

@st2000 Perhaps I'm not explaining my self correctly. I know io5 or io4 can be used as inputs or output, in addition to their I2C role. Never the less, certain IOs as io0 and io2 will fail boot if they are set to LOW (as in my case - Toggle switches), regardless if they were defined or not later in code using pinMode. Now - all 9 gpios I've got, some fit to be an input (or output) and some are not.

Since you only need 4 for the relays it does not matter as long as they are not predefined. You can use the A/D and a resistor array as inputs for the buttons. I generally use a I2C an external chip for I/0 such as an PCF8574. The PCF8574 defaults to INPUT on startup which is turning  all the outputs on. My designs use them as active low. That Way during reset etc no glitches. It only sources a very small amount of current but will sink several mills. There are many other devices you can use as well.


text:
Sketch does not run right when uploaded via Arduino IDE vs PlatfomIO
I try to upload Adafruit's example sketch (Wemos mini 8266 + Lolin TFT-2.4" touch screen).
When complied and uploaded via Arduino IDE v1.8.19, sketch runs OK (including TFT), but when uploading via platformIO, exact same sketch (with no compilation errors), screen stays "white" (uninitialized). Placing a Serial.println(millis()); in loop shows that MCU is running OK.
I even verified and took the same Arduino's IDE lib's version and updated platformIO.ini file.
EXAMPLE CODE:
/***************************************************

1. !!!Make sure you using lastest ESP8266 core for Arduino, otherwise it may not work properly.
  https://github.com/esp8266/Arduino

  (The pin D0(GPIO16) will be not work when you use older version ESP8266 core for Arduino,
  because the older version ESP8266 core for Arduino's digitalPinToBitMask(), portOutputRegister(),
  portInputRegister() and portModeRegister() fuction have some bugs which Adafruit_ILI9341 Library will use.
  This bug was fixed after commit:  https://github.com/esp8266/Arduino/commit/799193888a553de8876052019842538396f92194 )

2. Setup latest Adafruit_GFX, Adafruit_ILI9341 and XPT2046_Touchscreen Library first:

    https://github.com/adafruit/Adafruit-GFX-Library

    https://github.com/adafruit/Adafruit_ILI9341

    https://github.com/PaulStoffregen/XPT2046_Touchscreen

****************************************************/
#include <Arduino.h>
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#include <XPT2046_Touchscreen.h>

#define TFT_CS D0  //for D1 mini or TFT I2C Connector Shield (V1.1.0 or later)
#define TFT_DC D8  //for D1 mini or TFT I2C Connector Shield (V1.1.0 or later)
#define TFT_RST -1 //for D1 mini or TFT I2C Connector Shield (V1.1.0 or later)
#define TS_CS D3   //for D1 mini or TFT I2C Connector Shield (V1.1.0 or later)

// #define TFT_CS 14  //for D32 Pro
// #define TFT_DC 27  //for D32 Pro
// #define TFT_RST 33 //for D32 Pro
// #define TS_CS  12 //for D32 Pro

Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);
XPT2046_Touchscreen ts(TS_CS);

void setup()
{
  Serial.begin(115200);
  ts.begin();
  ts.setRotation(1);

  tft.begin();
  tft.setRotation(3);
  tft.fillScreen(ILI9341_BLACK);
  tft.setTextColor(ILI9341_WHITE);
  tft.setTextSize(3);
  tft.println("Touch Test");

  while (!Serial && (millis() <= 1000))
    ;
}

void loop()
{
  if (ts.touched())
  {
    TS_Point p = ts.getPoint();

    tft.fillScreen(ILI9341_BLACK);
    tft.setCursor(0, 0);

    tft.print("Pressure = ");
    tft.println(p.z);
    tft.print("X = ");
    tft.println(p.x);
    tft.print("Y = ");
    tft.println(p.y);
  }
}

platformIO.ini:
; PlatformIO Project Configuration File
;
;   Build options: build flags, source filter
;   Upload options: custom upload port, speed and extra flags
;   Library options: dependencies, extra library storages
;   Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html

[env:d1]
platform = espressif8266
board = d1
framework = arduino
lib_deps =
    adafruit/Adafruit GFX Library@1.11.5
    adafruit/Adafruit ILI9341@1.5.12
    paulstoffregen/XPT2046_Touchscreen


text:
Send same telemetry data to two different serial ports?
I'm using a Teensy 3.5 to control a wall-following robot. The robot sends telemetry to my PC via two independent ports - Serial1 & Serial.  Serial is the normal USB port, used when I direct-connect to the robot for troubleshooting, etc. Serial1 is tied to an HC-05 Bluetooth transceiver and it is used to acquire telemetry remotely.
I have to send telemetry to both ports, because I never know which (or either, or both) port(s) are actually active at any one time, so I wind up with lines like the following all over my code:
Serial.printf("\nChecking for MPU6050 IMU at I2C Addr 0x%x\n", MPU6050_I2C_ADDR);
Serial1.printf("\nChecking for MPU6050 IMU at I2C Addr 0x%x\n", MPU6050_I2C_ADDR);

needless to say this gets old after a while, and is error prone (I might edit one line and forget to copy/paste it to the other one).  What I would really like to do is create a function that would accept a printf-style string and send it to both ports, but I'm having trouble figuring out how to do that.
I have tried playing around with strcpy and strcat without much success:
  char quotestr[] = "\"";
  char hellostr[] = "hello";
  char instr[] = "%s\n, hellostr";
  char deststr[40];
  memset(deststr, 0, sizeof(deststr));
  strcat(deststr, quotestr);
  strcat(deststr, instr);
  strcat(deststr, quotestr);
  Serial.printf("quotestr = %s\n", quotestr);
  Serial.printf("instr = %s\n", instr);
  Serial.printf("deststr = %s\n", deststr);
  Serial.printf(deststr);

But the output is wrong because the '\n' gets interpreted as a CRLF pair even though it is in a string with double-quotes.
quotestr = "
instr = %s
, hellostr
deststr = "%s
, hellostr"
"
, hellostr"

It seems like there ought to be a way to do this easily, but I can't figure it out.  Any help would be appreciated.
TIA,
Frank

The \n gets interpreted as a newline, just as it is normal for Linux based OS. I would say it is doing exactly what you told it to do. Where are you looking at this? Why is this a problem? And have you thought about using sprintf() to build the string into a char array, which you can then print on both Serial interfaces?

if you don't want a new line, then remove the \n from the string

Using \\n instead of \n should do the trick.

you can write a simple T output using the base class Print. The standard Arduino Print class doesn't have printf but from your code it looks like the Teense core has printf in Print.
class TeePrint: public Print {

  Print &out1;
  Print &out2;

public:

  TeePrint(Print &_out1, Print &_out2) : out1(_out1), out2(_out2) {}

  virtual size_t write(uint8_t b) {
    out1.write(b);
    out2.write(b);
    return 1;
  }

};

TeePrint log(Serial, Serial1);

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

  log.printf("abcd %d %s", 1234, "xyz");
}

void loop() {

}

Thanks - your TeePrint class is very elegant.  One minor nit - it refused to compile for T3.2 because 'log' was declared in math.h.  When I changed from 'log' to 'myTee', everything worked fine

The simplest method is a variadic macro:
#define PRINTF(...) do { Serial.printf(__VA_ARGS__); Serial1.printf(__VA_ARGS__); } while(0)

Then you can just use PRINTF("foo: %d", bar); and it will expand it out to the two printfs for you.

This will fail on if (bar) PRINTF("foo: %d", bar);. That's why people use the do {...} while (0) idiom.

@EdgarBonet I did consider adding the {} but didn't bother. I should have. I have now. The do and while aren't needed.

The do and while (0) are needed for if (bar) PRINTF(...); else ... to work as expected.

@EdgarBonet No, you only need the {} for that.

That's incorrect. Try it!

Wouldn't that render the output string twice? Might make a huge difference if the user wants to print complicated stuff especially if floats are involved.

@EdgarBonet I do, regularly. I have never used, nor even seen, the do while construct.

@luni64 yes it would, but on a teensy it won't be noticeable as they are so much faster than an Arduino.

Without the do and while (0), if (bar) PRINTF(...); else ... gives error: ‘else’ without a previous ‘if’. Try it, seriously! The do {…} while (0) construct is the standard fix for this problem, and it is a very common idiom.

@EdgarBonet Ah, that'll be the fact that you added a ; after the macro when you used it. Don't do that?

If you remember to not add a trailing semicolon after the macro, then it works. But that is confusing, as the macro looks superficially like a function, yet it has to be used with a different syntax. Would you refrain to add a semicolon after getc() because it may be implemented as a macro?

@EdgarBonet The fact it's all in capitals is a dead giveaway that it's a macro. That's the convention. Sure, if you want to add a do while around it then do (while). It's not in my coding style, so I don't. I write my macro names in all caps so I remember they're macros, and don't need a ; after them. Everyone's coding style is unique.

“Everyone's coding style is unique” is not an excuse for being confusing. You fell in your own trap, as you accidentally added a semicolon in the first two versions of this answer. Imagine how easily someone else using a macro defined by you may fall in this trap.

@EdgarBonet If it'll shut you up I'll add it. I still don't use it personally though.


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:
MPU6050 with Arduino I2C Unreliable with Motor Noise
I have an autonomous wall-tracking robot that uses relative angle changes from a I2C-connected MPU6050 module along with ultrasonic 'ping' sensors for motor speed control to acquire and then track a specific wall offset distance.  The problem I'm having is that occasionally the MPU6U050's DMP module will stop loading new data into its FIFO.  This can take 2 minutes or 5 hours, but eventually it will happen.  Here's what I know (or think I know)

AFAICT, I have to have the motors running to get it to fail.
Installing bypasses on the motor terminals per Pololu guidance for their D20 metal-geared motors significantly improved the situation (i.e. much longer times between failures), but did not completely solve the problem.
The Arduino I2C bus and at least part of the MPU6050 appears to remain functional after a failure; at least, I can still call mpu.testConnection() and get a positive response.
Resetting the mpu, the FIFO, the DMP or any combination thereof does not seem to help. Resetting the Arduino DOES restore MPU6050 functionality (after all the setup stuff, including mpu.Initialize()).

As I write this question, I just had another long-term test fail at a little over 3 hours (198 minutes).
Has anyone else experienced this sort of problem with the MPU6050 in a motor-driven system?  Any ideas about how to really track down the failure mechanism?
TIA,
Frank

check that the bus cable lengths are short and have the proper pull-ups. i had some long-term i2c problems in a data logger that i worked around with something like Wire.reset();delay(20);Wire.begin();SYS.fixes++;ina219.begin();

I2C Bus length is zero (MPU6050 module plugged directly into UNO header).  I did try resetting the I2C bus with no effect.  Pullups are on the MPU6050 module.


text:
Generating Externally Triggered Complimentary PWM with Arduino Due

I need a 2KHz complimentary PWM waves with adjustable duty and phase that is triggered by an external 4KHz source.
After reading the datasheet I think there might be 2 way to do this:

Use a TC unit in capture mode, and somehow generate an interrupt when the count reaches 2. Use another TC unit in waveform mode to output phase-correct PWM. Use yet another TC unit to implement dead-time and generate the complimentary PWM.

Use the PWM controller, which already have complimentary PWM with dead-time build-in, but I'm not sure if it accepts external trigger.

If either of them is possible, could you please provide and example code ?
Thanks in advance !


text:
Register writing by compound assignment and pointer in Arduino due
I'm confused with register wrting method by compound assignment and/or pointer because I don't know where are some of the values come from.
Example 1
REG_PMC_PCER1 |= PMC_PCER1_PID36;  // Enable PWM - Peripheral Identifiers 36

This works the same as REG_PMC_PCER1 = (1<<4)
REG_PMC_PCER1 is not readable, so |= operator shouldn't work.
What is PMC_PCER1_PID36 ? Is the some sort of bit mask defined in the IDE ?

Example 2
PMC->PMC_PCER0 |= PMC_PCER0_PID13;   // PWM controller power ON

This works the same as REG_PMC_PCER0 = (1<<13)
This is similar to Example 1 but there is pointer PMC. Why it's needed ? If PMC_PCER0_PID13 is a bit mask then REG_PMC_PCER0 need not indexing.

So my questions are:

Why compound assignment works on write-only registers ?
Where are those constants (PMC_PCER1_PID36,PMC,etc.) defined ?

Thanks in advance !

Why compound assignment works on write-only registers ?

Probably out of force of habit more than anything.  People are used to having to set bits in registers where the other bits can be read and they want them to stay the same, in which case |= makes sense.
I'd considered that |= might be generating a more efficient instruction, but at least with your REG_PMC_PCER1 |= PMC_PCER1_PID36 example objdump indicates that this is not the case.

Where are those constants (PMC_PCER1_PID36,PMC,etc.) defined ?

Code-wise, they're defined in the ATMEL's (now Microchip's) CMSIS files.  These are header files whose existence is somewhat standardized by ARM for these ARM Cortex processors.  Much of their content isn't however.  E.g., you may see a few things related Cortex M3 that are the same between this ATMEL device in an STM32 counterpart, but GPIO registers may be completely different.
My broadly, they're defined by ATMEL in their datasheets.

I haven't found a statement that explains flatly that a write-only register will appear to be all zero bits when attempting to be read, but that is likely the case.  If I find a simple statement to that effect I'll call it out.


text:
Arduino pro micro crashing
My arduino pro micro started behaving weird. I noticed it had crashed with very simple code on it (basically just two lines of fastled code followed by a delay. Then it didn't appear as a USB device on my macbook anymore. I reset it (pulling the rst pin to gnd) and that then allowed me to upload smaller sketches but not bigger ones. The smaller sketch only works for a short period of time. then the arduino just stalls. (Serial output also stops). Any idea what i can do? Or do i just have to toss the board and get myself a new one?

Could you explain what happens if you try to upload bigger sketches? PS.
please note that the fastLED library is a few hundred lines of code. So that fact that your code is only two lines doesn't actually mean your program is simple or small.

the board doesn't appear via usb anymore. two LEDs on the board light up during the upload process and the board is lost Couldn't find a Board on the selected port. Check that you have the correct port selected.  If it is correct, try pressing the board's reset button after initiating the upload. Board at /dev/cu.usbmodem14101 is not available - Started to happen with smaller sketches too, so i just assume the board is fried.

You could try reflashing the bootloader, but I'm doubtful that would help. Have your tried a different USB port?


text:
Translating WS2812-LED-Strip-IDs when cutting up a strip to multiple parallel ones
Lets say i have 1 meter of WS2812 Strip at 60 LEDs per meter. Now i cut the strip up in to 6 single strips but keep the wiring the same and lay them out in parallel. So it would look something like this
1   |  11  |  21 ...
2   |  12  |  22 ...
3   |  13  |  23 ...
...
10   | 20   | 30 ...
Is there any library that would allow me to easily translate this? If i for example want to work with rows, turn a certain row in a certain color, treat certain sub-strips as if they were an individual one, etc etc...
I'm sure i can't be the first one who had this problem?

No, there is no library.
It's just simple maths.
If all your strips are the same, then you just multiply the strip number by the number of LEDs per strip, and add the number of the LED you want in that strip.
So, assuming 10 LEDs per strip:
lednumber = 10 * strip + led;

You can make a little macro to do it for you if you like:
#define STRIP2LED(S, L) (((S) * 10) + (L))

Then you can use such things as:
// Set all LEDs on strip 3 to red
for (uint8_t i = 0; i< 10; i++) {
    leds[STRIP2LED(3, i)] = CRGB::Red;
}