text:
Issue using Arduino Mega Timer2 with PinChange Interrupt
I was working on a program to measure the pulse width , for that I thought of using Timer 2 in Arduino mega along with pin change interrupt,
The program I have written is as follows
volatile float ovfCount = 0;

typedef struct{
  float curr_ovfCount,prev_ovfCount;
  uint8_t curr_tcnt2, prev_tcnt2;
  uint16_t width;
  bool stateHigh = true;
}Pulse;

Pulse ch1, ch2, ch3, ch4, ch5, ch6;

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

  /*
   * Pin Change Interupt for
   * measuring the pulse width
   * from the receiver
   *
   */

  DDRK = 0; // A8:A15 -> direction as Input
  PORTK = B00111111; // A8:A15 -> pullupResistor

  PCICR = B00000100; // activating 2 nd PCINT
  PCIFR = 0; // resetting the flags
  PCMSK2 = B00111111; // activating from A8:21 :: 6

  /*
   * 8 bit timer setup for counting
   * timer 2 is used
   */
   TCCR2B=0x00;
   TCCR2A = 0x00; // wave generation is normal:: all zeros
   TCNT2 = 0x00;
   TIFR2 = 0x00; // resetting all flags
   TIMSK2 = 0x01; //timer overflow enable
   TCCR2B = 0x01; // no prescaling

}

ISR(TIMER2_OVF_vect){
  ovfCount++;
}

ISR(PCINT2_vect){
  float ovf_count = ovfCount;
  uint8_t tcnt2 = TCNT2;

  if( (PINK & 1 << PINK0) & ch1.stateHigh ){
    //Low-High
    ch1.prev_ovfCount = ovf_count;
    ch1.prev_tcnt2 = tcnt2;
    ch1.stateHigh = false;
  } else if( ! ((PINK & 1 << PINK0) & ch1.stateHigh)){
//    High-Low
    ch1.curr_ovfCount = ovf_count;
    ch1.curr_tcnt2 = tcnt2;
    ch1.width = (256.0*(ch1.curr_ovfCount - ch1.prev_ovfCount) + (ch1.curr_tcnt2 - ch1.prev_tcnt2) ) * 1000 / 16e6;
    ch1.stateHigh = true;
  }

}

void loop() {
  Serial.println(ch1.width);
  pinMode(13, OUTPUT);
  digitalWrite(13,!digitalRead(13));
  delay(1000);

}

and the output I am getting is ,
16:22:05.667 -> 0
16:22:05.847 -> 927
16:22:06.826 -> 927
16:22:07.820 -> 1001
16:22:08.847 -> 1001
16:22:09.837 -> 1001
16:22:10.843 -> 1001
16:22:11.835 -> 1002
16:22:12.863 -> 1002
16:22:13.871 -> 1002
16:22:14.854 -> 1002
16:22:15.873 -> 1003
16:22:16.875 -> 1003
16:22:17.887 -> 1003
16:22:18.860 -> 1003
16:22:19.875 -> 1003
16:22:20.867 -> 1003
16:22:21.907 -> 1003
16:22:22.895 -> 1003
16:22:23.922 -> 1008
16:22:24.921 -> 1008
16:22:25.938 -> 1008
16:22:26.922 -> 1008
16:22:27.939 -> 1008
16:22:28.961 -> 1008
16:22:29.946 -> 1008
16:22:30.971 -> 1008
16:22:31.993 -> 1008
16:22:32.974 -> 1008
16:22:34.011 -> 1008
16:22:35.016 -> 1008
16:22:36.026 -> 1008
16:22:37.012 -> 1008
16:22:38.024 -> 1008
16:22:38.939 -> 1008
16:22:39.802 -> 906
16:22:40.638 -> 906
16:22:41.508 -> 844
16:22:42.345 -> 844
16:22:43.189 -> 842
16:22:44.059 -> 842
16:22:44.905 -> 843
16:22:45.750 -> 843
16:22:46.593 -> 842
16:22:47.428 -> 842
16:22:48.305 -> 842
16:22:49.139 -> 842
16:22:50.011 -> 845
16:22:50.839 -> 845
16:22:51.707 -> 842
16:22:52.539 -> 842
16:22:53.419 -> 842
16:22:54.260 -> 842
16:22:55.111 -> 842
16:22:55.975 -> 842
16:22:56.791 -> 842
16:22:57.642 -> 842
16:22:58.492 -> 842
16:22:59.372 -> 842
16:23:00.212 -> 842
16:23:01.046 -> 842
16:23:01.918 -> 842
16:23:02.775 -> 842
16:23:03.600 -> 849
16:23:04.473 -> 849
16:23:05.329 -> 842
16:23:06.159 -> 842
16:23:07.022 -> 842
16:23:07.862 -> 842
16:23:08.709 -> 842
16:23:09.574 -> 842
16:23:10.412 -> 843
16:23:11.292 -> 843
16:23:12.116 -> 848
16:23:12.996 -> 848
16:23:13.899 -> 848
16:23:14.779 -> 848

The output I am expecting is 1000 as the connection to the PCINT is directly form the digital pin13 of the Arduino and it is made to blink at that interval
I want to know

What mistake I am making here in measuring the counts
How can I generalise this method for measuring width of 6 channels simultaneously.

===== Edit after input from Edgar Bonet ===========
I have written a program , can you please tell me is this a good way to accomplish my requirement
volatile uint32_t ovfCount = 0;

struct Pulse {
  uint32_t last_toggle;
  uint32_t width;
  bool stateHigh;
  bool input_is_high;
  uint32_t get_width() {
    noInterrupts();
    uint32_t width_copy = width;
    interrupts();
    return width_copy;
  }
};

Pulse ch1, ch2, ch3, ch4, ch5, ch6;

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

  /*
     Pin Change Interupt for
     measuring the pulse width
     from the receiver

  */

  DDRK = 0; // A8:A15 -> direction as Input
  PORTK = B00111111; // A8:A15 -> pullupResistor

  PCIFR = 0; // resetting the flags
  PCMSK2 = B00111111; // activating from A8:21 :: 6
  PCICR = B00000100; // activating 2 nd PCINT

  /*
     8 bit timer setup for counting
     timer 2 is used
  */
  TCCR2B = 0x00;
  TCCR2A = 0x00; // wave generation is normal:: all zeros
  TCNT2 = 0x00;
  TIFR2 = 0x00; // resetting all flags
  TIMSK2 = 0x01; //timer overflow enable
  TCCR2B = 0x01; // no prescaling

  DDRH = B00111000;
  fastPWM_init();

}

void fastPWM_init() {
  //    clearing
  TCCR4A = 0; TCCR4B = 0; TCCR4C = 0;
  //    Initializing
  TCCR4A = B10101010; // OC4A, OC4B, OC4C : ICR-WGM
  TCCR4B = B00011010; // ICR-WGM prescalar : 8
  //    Setting frequency
  ICR4 = 39999;
  //    Setting PWM
  OCR4A = 2000; OCR4B = 2000; OCR4C = 2000;
}

ISR(TIMER2_OVF_vect) {
  ovfCount++;
}

ISR(PCINT2_vect) {
  uint8_t tcnt2 = TCNT2;
  uint32_t ovf_count = ovfCount;

  if ( bit_is_set(TIFR2, TOV2) && tcnt2 < 128 ) {
    ovf_count ++;
  }

  uint32_t time = ovf_count << 8 | tcnt2;

  pinChangeFunction(&ch1, time, PK0);
  pinChangeFunction(&ch2, time, PK1);
  pinChangeFunction(&ch3, time, PK2);
  pinChangeFunction(&ch4, time, PK3);
  pinChangeFunction(&ch5, time, PK4);
  pinChangeFunction(&ch6, time, PK5);

}

void pinChangeFunction(Pulse *channel, uint32_t time, uint8_t pin){
  channel->input_is_high = bit_is_set(PINK, pin);
  if (channel->input_is_high && !channel->stateHigh) {
    channel->stateHigh = true;
  } else if (! channel->input_is_high && channel->stateHigh) {
    channel->width = time - channel->last_toggle;
    channel->stateHigh = false;
  }
  channel->last_toggle = time;
}

void loop() {

  if(Serial.available() > 0){
    OCR4A = Serial.parseInt();
  }

  Serial.print(ch1.get_width() / 16e3);Serial.print("\t");
  Serial.println(ch6.get_width() / 16e3);

}

The PWM is only used for testing.

This program is doing floating point calculations (which are super-slow on AVR) within an ISR that is triggered every 16 µs. I am surprised it works at all.

thanks for the suggestion , so what datatype should I use for overFlow count .?

Pin change interrupts are slower than normal interrupts. Also, for the resolution you are working with, just use millis() or micros() to get the current timestamp instead of messing with timers.

There are quite a few issues with this program. The most obvious is the
use of floating point calculations in interrupt context. Interrupts
should be served as fast as possible, and floating point is really slow
on the AVR.
Some other issues:

Interrupt flags should be cleared by writing a logic 1 to them,
however silly it may sound.

A couple if & operators in ISR(PCINT2_vect) are probably meant to
be &&.

The logic for detecting rising and falling edges is all wrong.

There is no need to store so much data in the Pulse objects.

ch1.width should be read with interrupts disabled in order to avoid
a data race.

There is a subtle race condition when reading ovfCount and TCNT2:
if the timer overflows right when ISR(PCINT2_vect) starts running,
that overflow will not be counted.

Here is a version of the program that attempts to fix all these points.
I also changed it for running on an Uno (with pin 13 = PB5 =
PCINT5), so that I could test it:
/*
 * Pulse width via PCINT.
 *
 * https://arduino.stackexchange.com/questions/81688
 */

volatile uint32_t ovfCount = 0;

struct Pulse {
    uint32_t last_toggle;
    uint32_t width;
    bool stateHigh;
    uint32_t get_width() {
        noInterrupts();
        uint32_t width_copy = width;
        interrupts();
        return width_copy;
    }
};

Pulse ch1, ch2, ch3, ch4, ch5, ch6;

void setup() {
    Serial.begin(115200);
    pinMode(13, OUTPUT);

    /* Setup Pin Change Interrupt for detecting pulses. */
    PCMSK0 = _BV(PCINT5);  // sense change on pin 13 = PB5 = PCINT5
    PCIFR  = _BV(PCIF0);   // reset interrupt flag
    PCICR  = _BV(PCIE0);   // enable PCINT0_vect: pins PCINT[7:0]

    /* Setup Timer 2 for counting. */
    TCCR2B = 0;           // stop
    TCCR2A = 0;           // normal mode
    TCNT2  = 0;           // reset timer
    TIFR2  = _BV(TOV2);   // reset interrupt flag
    TIMSK2 = _BV(TOIE2);  // enable timer overflow interrupt
    TCCR2B = _BV(CS20);   // count at F_CPU/1
}

ISR(TIMER2_OVF_vect) {
    ovfCount++;
}

ISR(PCINT0_vect) {
    uint8_t tcnt2 = TCNT2;
    uint32_t ovf_count = ovfCount;

    // Was there an overflow that has not yet been accounted for?
    if (bit_is_set(TIFR2, TOV2) && tcnt2 < 128) {
        ovf_count++;
    }

    uint32_t time = ovf_count << 8 | tcnt2;

    bool input_is_high = bit_is_set(PINB, PB5);
    if (input_is_high && !ch1.stateHigh) {  // low -> high
        ch1.stateHigh = true;
    } else if (!input_is_high && ch1.stateHigh) {  // high -> low
        ch1.width = time - ch1.last_toggle;
        ch1.stateHigh = false;
    }
    ch1.last_toggle = time;
}

void loop() {
    digitalWrite(13, HIGH);
    delay(1000);
    digitalWrite(13, LOW);
    delay(200);
    Serial.println(ch1.get_width() / 16e3, 5);
}

And here is the output:
1000.02349
1000.01959
1000.01916
1000.02496
1000.01959
1000.02032
1000.01947
1000.02795
1000.02642
1000.01855
1000.01916
1000.02105
1000.02490
1000.01782
1000.03033
1000.01898
...

The printed values are larger than 1000 because of the time needed to
execute digitalWrite().
Also note that an 8-bit timer running at the full CPU speed overflows
every 16 µs. That's quite a lot of pressure on the CPU, and many
operations will take longer that expected because of these interrupts.
If I wanted to time something with single-cycle resolution, I would
reach for a 16-bit timer. And I would prefer using input capture,
although sadly only two input capture channels are available on the Mega
(on pins 48 and 49).

Edit: Answering the questions in the comments.

please have a look at my question edits and please advice.

I did not test it, but it seems to me this code should work. I would
prefer, however, having a different interrupt for each channel.
Otherwise, the successive calls to pinChangeFunction() can make the
execution of this ISR quite long.
Also note that Pulse::input_is_high serves no useful purpose. Storing
this value in the object slows down the ISR, as it has to access memory,
whereas a local variable would be kept in a (much faster) internal CPU
register.

what will we do if we have 8 channels as in the radio receiver?

You could use 6 external interrupts and 2 pin change
interrupts.

Why did you take tcnt2 < 128 when tcnt2 max is 256?

This one is tricky. I'll try to explain the whole logic of the test.
Consider the following naive version of the ISR:
ISR(PCINT0_vect) {
    // ← A
    uint8_t tcnt2 = TCNT2;
    uint32_t ovf_count = ovfCount;
    uint32_t time = ovf_count << 8 | tcnt2;
    // ...
}

There is a small chance that Timer 2 overflows at point A, i.e.
while this ISR is executing its prologue and has not yet read TCNT2.
If this happens, the TIMER2_OVF ISR will not run immediately, because
we are already executing an ISR, and ISRs do not nest. Then, ovfCount
is not updated. If this happens, we then read a value of TCNT2
affected by the overflow, and a value of ovfCount that does not
account for that overflow. We then combine together those inconsistent
values into a time value that misses 256 timer ticks.
We can detect this situation by reading the TOV2 flag in TIFR2. This
flag is set only when there is a pending interrupt request for
TIMER2_OVF, i.e. if the counter has overflowed and that overflow has
not yet been accounted for in ovfCount. Thus the “fixed” ISR looks
like this:
ISR(PCINT0_vect) {
    // ← A
    uint8_t tcnt2 = TCNT2;
    // ← B
    uint32_t ovf_count = ovfCount;
    // ← B
    if (bit_is_set(TIFR2, TOV2)) {
        ovf_count++;
    }
    uint32_t time = ovf_count << 8 | tcnt2;
    // ...
}

With this, if the overflow happens at point A, we manage to compute the
proper time. But consider now what would happen if the timer overflows
at either of the points marked B, i.e. after reading TCNT2 but before
reading TOV2. If this happens, we read the pre-interrupt values of
both TCNT2 and ovfCount. No correction is thus needed for computing
a consistent time. Yet, TOV2 is raised when we test it: we then
apply an unneeded correction, and we end up with a time that is too
large by 256 ticks.
In order to fix this problem, we have to make sure the correction is
applied if the overflow happens at point A, but not if it happens at
point B. How can we tell apart those two situations? The answer is: by
looking at the value recorded in tcnt2. In case A, the counter was
read right after the overflow, so it had a very small value (close
to 0) when it was copied to tcnt2. In case B, the counter was
read when it was just about to reach the overflow, so it had a very
large value (close to 255). If TOV2 is set when we read it, this
means an overflow happened during the very beginning of the current ISR,
very close to the point where we read TCNT2. So the value recorded in
tcnt2 has to be either very small or very large. It cannot be in the
middle (close to 128).
So we have to decide whether tcnt2 is very small or very large. There
are many possible values that could be used as a threshold. The most
natural is the mid range: 128. It is also the most efficient to compute,
as the compiler can optimize the comparison into a simple test of the
most significant bit. Thus the final version of the test:
    if (bit_is_set(TIFR2, TOV2) && tcnt2 < 128) {
        ovf_count++;
    }

How to modify the same for using with 6 channels .? sorry but  I am getting confused ..

@Lawliet: You have only 3 pin change interrupts. Reading 6 channels would make the ISRs more complex, as they would need to find out which channels triggered the interrupt. I would rather use regular external interrupts, as there are 6 of them available on the Mega (INT0–INT5). You could use a template to void repeating code.

please have a look at my question edits and please advice.

Also what will we do if we have 8 channels as in the radio receiver. ?

Doubt1: Why did you take tcnt2 < 128  when tcnt2 max is 256 . ?

@Lawliet: See amended answer.

with your advices I tried to write a program with 16bit timer and I am getting some sort of error in the consistency of measuring the clock tick . please have a look . link

The reason why I'm using PCINT is I have to use one IMU- which is I2C :: for that I have to access scl and sda pins , Then I have 4 in one setup and 8 servos in another setup that also have to be used , and finally I have to measure the rpm of 4/8 motors also .
So for this which all pin combination will you suggest.
(1.) Receiver :: 6/8 channels - width to be calculated
(2.) I2C ::
(3.) 4/8 :: servos
(4.) 4/8 :: speed measuring sensors

Please help me with this issue @edgar-bonet  . QuestionLink


text:
Using MPU6050 with ESP32 Cam- MPU Not Detected
Hi I'm trying to build a self balancing robot using my esp32 cam, but so far I haven't been able to setup my mpu6050 with it.I'm using the adafruit libraries with the given example sketches.
The only thing I've done different is using two different SDA , SCL pins. So to get that done in the software I have made the following change to the Adafruit_I2CDevice.cpp file, where the TwoWire.begin() happens.

This is the tutorial I'm following, Click Here
So Far this is What the Serial Monitor shows me
Adafruit MPU6050 test!
Failed to find MPU6050 chip

Any help to get my ESP32 to work with the MPU6050 is highly appreciated.
Also note I managed to read the bare values from the MPU using only the Wire.h library.The reson I want to use the Adafruit library is because it makes use of the DMP on the MPU6050.

source: Stack Exchange

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

sort: votes


text:
Is it possible to change and save I2C address programatically?
I want to drive 3 i2c devices on a single i2c line. Is it possible to achieve this without using A0,A1,A2 pins?
I thought the address of i2c devices should be programmatically changeable.
2 mcp23017 and si5351 chips I use.

Some I2C devices can have their addresses changed programatically, most can't. The datasheet will tell you. You could drive the Ax pins from the Arduino to change them at will, but to what end?

Why don't you want to use the address configuration pins? That's exactly what they are there for.

@Mat bc hw designer forget to connect these pins to mcu :(
If it was OK to change programmatically, this would make my life easier.

If the pins are not connected in hardware (left open floating), the MCP23017 will show undefined behavior. It may randomly change addresses (even during operation), which is useless. These pins must be connected properly.

@projecti2c: you don't connect these pins to the MCU (in usual settings). You look at the datasheet and tie them e.g. to ground or VCC depeding on what address you want. The address selection pins don't change during normal operations.

As far as I can see in the datasheets of the 2 mentioned chips, they don't provide a way to change the address programmatically over the I2C bus. They only have address pins, which have to be tied to Vcc or ground for setting the address. Most ready to use boards with such chips already have pullup or pulldown resistors for this. If you use the blank chips, you absolutely need to tie the address pins to a fixed value. Normally this is done semi-permanently.
You can also connect the address pins to Arduino output pins to dynamically change the addresses.
There is no other way to change the addresses but to use the address pins.

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


text:
Change character sequence
I turn on the transmission of one key that works to open the door, but after a certain time I need to close the door, and for this I need to use the second key. I want to do without additional buttons, so it is required to emit key 1 when power is applied, and after 20 seconds, for example, switch and emit key 2. What is the most simple and correct way to do this?
Apply a timer or emit key 1, for example 1000 times, and after overflow 1000, start emitting key 2.
This sketch only constantly sends the first key to the digital pin, without switching to the second.
You need to figure out how you can switch to the second key.
const int KEY_LEN = 54; //Number of characters in the key
const char key1[KEY_LEN] = {"SSSSSS001101001001110001000000000000000000000011001010"}; // Open
const char key2[KEY_LEN] = {"SSSSSS001010111010000000000001000000000000010000000000"}; // Close

int Preamble = 1000; // Preamble duration in microseconds
int zero= 200; // Duration of zero in microseconds
int One= 440; // Duration of a unit in microseconds

const int LED_PIN = 13; // Used digital pin 13 of the arduino to connect the transmitter
void setup()
{
  pinMode(13, OUTPUT);
}

void loop()
{

    for (int n = 0; n < KEY_LEN; n++)
    {
      if (key1[n] == '1') //execute if bit value == 1
      {
        sendSignal(One);
      }

      else if (key1[n] == '0')//execute if bit value == 0
      {
        sendSignal(zero);
      }
      else
      {
        sendSignal(Preamble); // Стартовый импульс
      }

    }
  }

void sendSignal(int duration)
{
  digitalWrite(LED_PIN, HIGH);
  delayMicroseconds(duration);
  digitalWrite(LED_PIN, LOW);
  delayMicroseconds(duration);
}

I usually recommend against using delay()s, but if this system will only ever have to do what you've described, using delay()s is the simplest way to implement it.
I would suggest sending key-1, possibly several times, maybe a half second apart, delay for the 20 seconds you suggested, then send key-2, definitely several times for security.


text:
digitalRead() function of Arduino doesn't read Input value sent by sensor after detecting the object
I'm trying to turn ON the LED(inbuilt/PIN13) when photoelectric proximity sensor(12v) senses any object. Sensor is connected on pin 2. Assigned pin 2 as INPUT, I've got a 12v spdt relay for switching. 12v output from sensor is fed to coil, on the other end 5v supplied to COM pin and "Normally Open"(NO) pin to Arduino (with pull-down resistor). When 'NO' connected to loose LED it works properly (shows 5V on voltmeter when object is detected). But when connected to Arduino digitalRead(), it always returns LOW/0.
//code
int a=0;
void setup() {
  pinMode(2,INPUT);
  pinMode(13,OUTPUT);
  Serial.begin(9600);
}

void loop() {
  a ==  digitalRead(2);
  Serial.println(a);
  if(a==HIGH){
    Serial.println("Object Detected");
    digitalWrite(13,HIGH);
  }else{
    Serial.println("There's no object");
    digitalWrite(13,LOW);
  }
  delay(1000);
}

it is difficult to visualize what you are describing ... please draw a schematic diagram or a wiring diagram ... also include the code that you are using

To read that detector: get rid of the relay and replace it with an ordinary voltage divider.

I tried using 7805 to get 5v output. It did not work, @SimSon

@jsotola yes. sure. I'm uploading a schematic and code.

use 1kOhm resistor for pulldown

@Juraj I used 1K resistor for pulldown, it did not work.

I'm not talking about a voltage regulator, but a simple voltage divider consisting of two resistors. The sensor is probably (do you have a datasheet?) not able to provide sufficient current to activate the relay without harm. Just don't use the relay, it's a poor design this way.

And are you sure the relay pinout is correct? Relays usually have primary contacts on one side and secondary on the other side.

@SimSon Right now I don't have appropriate value resistors to make voltage divider. It's just a relay not a relay module hence the relay pinout is correct. The sensor must be providing sufficient current(I have no datasheet) because relay switches when object is detected also on the other side of relay gets 4.96 volts (measured by multi-meter) when object is detected. But Arduino pin does not recognize change in voltage (i.e.0 to 4.96). All other stuff works absolutely fine but digitalRead() function associated with Arduino input pin returns LOW even after detecting 4.96 V.

Thank you all for replying. The problem is solved it was silly mistake.

a == digitalRead(2) must be a = digitalRead(2). You also better change the if clause to if(a) to avoid true/HIGH/1 confusions.
If you had formatted the code properly, you'd have safed some time (you just need to select the code and press the {} button).
You also better replace the relay with a voltage divider (as I mentioned in my comment), because as long as you don't have a datasheet for the sensor you can't be sure that the sensor is designed to source that much current. If the sensor is supposed to drive a TTL logic, it will eventually fail, just like you don't drive relays with GPIOs directly. And beside that you need a freewheeling diode across the relay coil to deal with back EMF which will also harm the sensor.

I can't forgive myself for this. I have wasted like 3 days on this stupidest syntax typo. Thank you for drawing my attention to it. Thank you for suggestions.

oh! I'll give it a try. The freewheeling diode stuff is really helpful for me. thanks.


text:
Is there a way to convert between arduino and raspberry pi pins
I have a robot that I have brought that is designed for raspberry pi (it comes with a raspberry pi HAT), and I am terrible at using my raspberry pi. So I was thinking what if there is some sort of way that I could use the digital pins on the arduino and the pins on the GPIO pins on the raspberry pi.
My idea is currently this (I actually have not tried it out yet just in case something goes wrong):

Connect an arduino digital pin to the bottom of one of the female
pins on the raspberry pi HAT (which would be typically used on a
raspberry pi rather than an arduino)

Would this be possible?

of course it is possibke ... use dupont jumpers with male connector at one end and a female connector at the other end

The Pi is 3.3V, Depending on what is on that "hat" you may need 5V <-> 3.3V logic level conversion.

@jsotola So could it be possible to connect digital pin 10 (just a random one for example), to GPIO pin 26 on the raspberry pi HAT and then use this digital input going through GPIO pin 26 on the raspberry pi somehow to control a motor?

@Majenko That makes thing a whole lot more difficult, would is simply be just most reasonable to supply the raspberry pi HAT with 3.3V?

@DigitalRookie4 No, you're thinking backwards. The "simplest" option would be to use a 3.3V Arduino.

@Majenko So you are meaning supplying the raspberry pi HAT with 3.3V from the arduino's 3.3V pin?

No. You either (depending of course on what is actually on that "hat" - RTFDS...) need to convert the Arduino's 5V GPIO signals to 3.3V or use an Arduino that runs at 3.3V so that it already outputs 3.3V GPIO signals.


text:
How can I use GPIO pins on an esp12e UART?
I've bought an esp12e UART that unfortunately had some issues, but I was able to fix them.

This is how I connected it to the arduino. With this setup, I was able to host a simple web server and it worked, the code uploaded and everything worked fine as it should. However, then I tried to make it light the led up by declaring it as on pin 13, but it didn't work, so I don't really know how should I declare my pins for the code to work as it should. By the way, the board is selected as nodemcu 1.0 (esp-12e module) in the arduino IDE if that helps. Thank you in advance

please remove the esp12e UART and try again ... the arduino uno probably already has an LED on pin 13

the shields headers are Uno headers, not esp8266 headers

@jsotola I can't remove the esp12e UART, I want to use it with the arduino.

@Juraj I understand, so how can I use the Uno headers when programming the esp8266?

it is a WiFi shield. put a firmware into esp8266 and use in Uno a WiFi library for that firmware

@Juraj thanks for the help, I've tried that way, but it didn't work, i guess i gotta try more methods for it to make it work if it's the only way.

you can write two sketch and code the communication but working with WiFi library is simpler.  https://github.com/jandrassy/WiFiEspAT/blob/master/README.md


text:
Pullup on compatible Arduino Mega
I've got an Arduino mega compatible board, called Ethermega, from Freetronics (ATmega2560).
Schematic here.
In setup, I've written this code:
Serial.begin(9600);
  pinMode(4, INPUT_PULLUP);
  digitalWrite(4, HIGH); // Optional, I tried with and without
  while (1)
  {
    if (digitalRead(4) == HIGH)
    {
      Serial.write("Up!\n");
    }
  }

(Don't worry about the fact I'm not using loop)
When I connect input 4 with 5V, I see "Up!". Rest of the time, I see nothing.
Considering I have enabled the internal pull-up, I'm expecting it should be up/high by default, and I would have to connect it to GND to get it low...
Another thing that puzzles me is I can find heaps of examples that use a tactile switch and no pullup/pulldown at all...
So what am I missing or doing wrong? Seems like whatever I do, I've got some kind of pulldown enabled...

pin 4 is CS pin for SD card an it has a voltage divider in the schematics

Generally you should not use digitalWrite on an input pin, it might not do what you think it does. If I remember correctly, the register that is used to set high/low in output mode us the same that sets the pullups in input mode. I don't know how the arduino core handles this, though. Just FYI...

@SimSon On AVR: pinMode(x, INPUT); digitalWrite(x, HIGH); is the same as pinMode(x, INPUT_PULLUP);. In general most cores will emulate that for you (I know chipKIT does) but you're right, it's best not to rely on it.

@SimSon Yes, I much prefer INPUT_PULLUP or writing the register, it was mostly out of desperation...

As @Juraj mentions, pin 4 is the CS pin for the SD card. That pin has a volage divider of 1kΩ + 2.2kΩ on it (a total of 3.2kΩ) to ground. So yes, you do have a pulldown on that pin. 3.2kΩ is about 1/10th of the value of the typical pullup resistor internal to the chip, so pulls the output low enough to be seen as LOW unless you manually override it.
You can't use that pin as an active low input on that board - choose another, or use it as active high.


text:
need to use jp2 because need extra pins
i clearly understand jp2 is the extra leftover pins of atmega16u2 . but how to access it ? i find my arduino has less pins and jp2 are the only ones left . but if it is not accessable , why do they have it ?
and also , if it requires seperate programing of the atmega16u2 , i'd like to know how . i completely dunno a thing about atmega16u2 . only thing i understand is that it makes the arduino more compatible with the usb input ...
thanks alot !

What exactly are you trying to achieve? Do you just need more IO pins? Then you should either switch to a bigger Arduino, or use extensions chips or other pin-saving principles.

i just try my best to go on with arduino uno because others are a bit expensive ... i tried to find whether i can make my own ic but a can't .that question's link >>> https://arduino.stackexchange.com/questions/81762/need-a-custom-ic-to-be-paired-with-arduino . (i hope you remember adding a comment)

If cost is the limiting factor, and you cannot use pin-saving principles (like arranging buttons or LEDs in matrixes, or doing some kind of multiplexing otherwise) (that highly depends on your actual circuit and what you are trying to drive, so I cannot go in detail here), you might wanna look at some of the Arduino clones. You can purchase them directly from china (for example at aliexpress) or at amazon from a reseller. They don't have the same quality, but most are very good to use. The original Nano for example costs 20€, while a clone is about 2€.

I indicated this sort of thing in the answer I gave, but I addressed it as a more or less direct answer to the question.  Otherwise, like @chrisl says regarding clones. Dig around for questions on here about getting "more pins", "sharing" pins, etc.

if it requires seperate programing of the atmega16u2,

It does.  Often an ATMega8U2 is used here instead though.

i'd like to know how.

You might start by having a look at HoodLoader2 and NicoHood's related projects.
This involves replacing the normal Xu2 transceiver firmware with HoodLoader.  There are different ways to do that outlined in the installation instructions.  If you don't have an ISP programmer or a second Arduino to behave as one, there's a method that involved burning an installer-sketch to the 328P which turns around and reprograms the Xu2 chip.
Once you have that done you can use their board definitions for put sketches onto the ATMegaXU2 itself.
Apparently, JP2's layout is flipped on some boards. So, beware of that.  In any case, the header it makes the ATMegaXU2's PB4, PB4, PB6, and PB7 available.  Sketches on the XU2 would use the Hoodloader pin mapping of these:

Arduino Pin No.
AVR GPIO PIN

D4
PB4

D5
PB5

D6
PB6

D7
PB7

Or course, now you need to find some way to coordinate what happens on the ATMegaXU2 with the ATMega328P.

i find my arduino has less pins and jp2 are the only ones left.

There are clever ways to reuse pins on microcontrollers.  For example, it is possible to put an LED and a switch on the same GPIO pin.  And there are GPIO expanders, SPI/I2C ADCs, etc.
Messing with JP2 and programming the ATMegaXU2 and having it coordinate with the 328P may be more trouble than you like just to get a couple extra pins.

but if it is not accessable, why do they have it ?

Just added capability.  Usually that header is unpopulated, so there's no part cost there.

and also , i completely dunno a thing about atmega16u2 . only thing i understand is that it makes the arduino more compatible with the usb input ...

It serves the role of a USB to logic-level-serial converter for connecting to the USART of the otherwise non-USB-aware ATMega328P (you have tagged UNO).  But, it can be made to run sketches.  Usually if you're doing this, it's to get native USB support on an UNO (or Mega, or..), e.g. so you can have your board act as a keyboard, like you might with a Leonardo or Micro or any other board that has native-USB in normal use.  And that's a large part of what NicoHood's project is about.

The Nano has two extra A/Ds available, will that do it? Same micro almost the same code.


text:
Hardware interrupt calling two ISRs
I've spent three days on this, and either I'm blind to something, or something just ain't right.
Doorbell. Front door switch and back door switch. Two interrupt service routines, one attached to each pin. Rudimentary debouncing in the ISR seems to work.
But for some reason, both interrupt routines are firing off when either of the switches is pressed. I've tried RISING, FALLING, LOW, CHANGE, and it all works the same. I tried INPUT_PULLUP and INPUT_PULLDOWN and changed the polarity on the switches. No change. I've tried different pins, digital, analog. Nothing seems to keep both ISRs from firing.
Pressing front door button, it should print:
front door high
Releasing front door button
front door low
Pressing back door button
back door high
Releasing back door button
back door low
But for some reason, both interrupt service routines are called when pushing either button. Here's what I actually get:
Pressing front door button:
back door low
front door high
Releasing front door button
front door low
Pressing back door button
front door WTF?
back door high
Releasing back door button
front door WTF?
back door low
Here's the code. I hope someone can see something I can't:
#include <Arduino.h>

#define FRONT_DOOR_SWITCH A2
#define BACK_DOOR_SWITCH A3

volatile int frontDoorStatus = 0;
volatile int backDoorStatus = 0;

void frontDoorIsr()
{
    static unsigned long last_interrupt_time = 0;
    unsigned long interrupt_time = millis();
    // If interrupts come faster than 200ms, assume it's a bounce and ignore
    if (interrupt_time - last_interrupt_time > 200) {
        if (digitalRead(FRONT_DOOR_SWITCH) == HIGH) {
            frontDoorStatus = 1;
        }
        else if (digitalRead(FRONT_DOOR_SWITCH) == LOW) {
            frontDoorStatus = 2;
        }
        else {
            frontDoorStatus = -1;
        }
    }
    last_interrupt_time = interrupt_time;
}

void backDoorIsr()
{
    static unsigned long last_interrupt_time = 0;
    unsigned long interrupt_time = millis();
    // If interrupts come faster than 200ms, assume it's a bounce and ignore
    if (interrupt_time - last_interrupt_time > 200) {
        if (digitalRead(BACK_DOOR_SWITCH) == HIGH) {
            backDoorStatus = 1;
        }
        else if (digitalRead(BACK_DOOR_SWITCH) == LOW) {
            backDoorStatus = 2;
        }
        else {
            backDoorStatus = -1;
        }
    }
    last_interrupt_time = interrupt_time;
}

void setup() {
    pinMode(FRONT_DOOR_SWITCH, INPUT_PULLDOWN);
    pinMode(BACK_DOOR_SWITCH, INPUT_PULLDOWN);

    attachInterrupt(digitalPinToInterrupt(FRONT_DOOR_SWITCH), frontDoorIsr, CHANGE);
    attachInterrupt(digitalPinToInterrupt(BACK_DOOR_SWITCH), backDoorIsr, CHANGE);
}

void loop()
{
    switch (frontDoorStatus) {
        case 0:
            break;
        case -1:
            Serial.println("front door WTF?");
            frontDoorStatus = 0;
            break;
        case 1:
            Serial.println("front door high");
            frontDoorStatus = 0;
            break;
        case 2:
            Serial.println("front door low");
            frontDoorStatus = 0;
            break;
    }

    switch (backDoorStatus) {
        case 0:
            break;
        case -1:
            Serial.println("back door WTF?");
            backDoorStatus = 0;
            break;
        case 1:
            Serial.println("back door high");
            backDoorStatus = 0;
            break;
        case 2:
            Serial.println("back door low");
            backDoorStatus = 0;
            break;
    }
}

Board is Adafruit Feather Express M4 (SAMD51)

So far the only way I can think to explain the interrupts being called the way you describe depends on there being more code than you're showing.  Is this, in fact, the entire sketch being tested?

Yes, that's what I first thought. I reduced it down to see if something else could have been causing it, but what I posted runs and fires off both ISRs.

Unfortunately I have no SAMD51 devices at all.  And I'm not sure I want to put my wild guess as an "answer." without any confidence.  As a diagnostic test, what I've have you try is using your same code with #define FRONT_DOOR_SWITCH 21 and #define BACK_DOOR_SWITCH 22 and hooking your signals to those pins labeled on the board as SCL and SDA.  If this improves things, I'll give you an answer as to why I think it may have.

Sorry to say, no improvement with SCL and SDA. Both ISRs are still being called. What's your theory?

Not sure what I was thinking rises to "theory" level. And what you did sort of disproves it.  Pins don't have dedicated interrupts.  They share the same interrupt with a handful of other pins.  In particular your Arduino pin A3 shares an interrupt with one of the onboard SPI chip lines.  SDA and SCL seem to not be sharing with anything else, at least nothing else broken out on the board, so no other pin can be triggering their external interrupt routine.  So, like I said, not that.

I am using SPI to hook an ESP32 up. I wonder if that's causing interference. To rule out a bad board, I swapped out with a brand new Feather M4 Express. Same exact problem. Now I'll disconnect the SPI and see what up.

Turns out that, in the Cortex Mx processors, interrupts don't work the same way as older 8- and 16-bit Arduino-style chips work.
As far as I can tell, there's only one ISR that's connected to the pins. In that routine, you've gotta check the status of the pins you are monitoring and set a global variable accordingly.
I'm not sure this is the only way to do it (seems kludgy), but it does work and it looks like it can scale to any number of pins. I'm using only two.
Here's my demonstration code if anyone is having the same problem. I put the debouncing code in the ISR. I know that's probably not best practice, but it doesn't take a lot of cycles and it's a lot easier than putting it in the loop.
#include <Arduino.h>

#define FRONT_DOOR_SWITCH A2
#define BACK_DOOR_SWITCH A3

volatile bool frontDoor = LOW;
volatile bool backDoor = LOW;

void isr()
{
    static unsigned long last_interrupt_time = 0;
    unsigned long interrupt_time = millis();
    // If interrupts come faster than 200ms, assume it's a bounce and ignore
    if (interrupt_time - last_interrupt_time > 50)
    {
        int fds = digitalRead(FRONT_DOOR_SWITCH);
        int bds = digitalRead(BACK_DOOR_SWITCH);
        if (fds == HIGH) frontDoor = HIGH;
        if (fds == LOW) frontDoor = LOW;
        if (bds == HIGH) backDoor = HIGH;
        if (bds == LOW) backDoor = LOW;
        last_interrupt_time = interrupt_time;
    }
}

void setup()
{
    Serial.begin(115200);
    while (!Serial);
    Serial.println("in setup...");
    pinMode(FRONT_DOOR_SWITCH, INPUT_PULLDOWN);
    pinMode(BACK_DOOR_SWITCH, INPUT_PULLDOWN);

    attachInterrupt(digitalPinToInterrupt(FRONT_DOOR_SWITCH), isr, CHANGE);
    attachInterrupt(digitalPinToInterrupt(BACK_DOOR_SWITCH), isr, CHANGE);
}

bool lastFrontDoor = LOW;
bool lastBackDoor = LOW;

void loop()
{
    if ((frontDoor == HIGH) && (lastFrontDoor == LOW))
    {
        Serial.print("fd+");
        lastFrontDoor = HIGH;
    }
    if ((frontDoor == LOW) && (lastFrontDoor == HIGH))
    {
        Serial.println("fd-");
        lastFrontDoor = LOW;
    }
    if ((backDoor == HIGH) && (lastBackDoor == LOW))
    {
        Serial.print("bd+");
        lastBackDoor = HIGH;
    }
    if ((backDoor == LOW) && (lastBackDoor == HIGH))
    {
        Serial.println("bd-");
        lastBackDoor = LOW;
    }
}


text:
send and recieve analog data from one arduino to another arduino via web/ethernet
i am able to send audio signal through mic and send it via arduino and receive it on speaker.
i need two things
1.) The voice i am hearing on speaker has on speaker has lots of noise with it. i need to reduce it
2.) I need to send that analog signal received  from the mic via Ethernet/web to another arduino. i have Ethernet shield i am able data from switch but not from mic.
let me start from the beginning, i have attached mic to the audio amplifier and have attached output of the amplifier to the a0 pin of the arduino. The arduino is connected to the DAC(PCF8519) with a5 and a4 pin of the aurdino. The output of the dac is connected to the LM386 audio amplifier module and its output is connected speaker. when i speak via mic i am able to hear it on speaker but it has has some noise attached to it. IF you can suggest solution for that it will be great.
now i want to send the data of the mic to another arduino via web/Ethernet. i am able to get the data of the switch but not been able to get proper data from the mic.So pls help out with that.
here is my audio amplifier circuit:

here is my code for one arduino code that worked
`#include "Wire.h"`
 #define PCF8591 (0x90 >> 1)
 void setup()
  {
    Wire.begin();
    pinMode(0,INPUT);
   }
 void loop()
   {
     Wire.beginTransmission(PCF8591);
     Wire.write(0x40);
     Wire.write(analogRead(0));
     Wire.endTransmission();
   }

I need to reduce the noise on the speaker and i want to send the data of the mic via web/Ethernet to another arduino.

do you get the noise if the arduino is not in the circuit?

"i need two things".  Unless you have reason to think the two problems are interrelated to the point where one can't be solved without solving the other, pick one and make your question about that.

Streaming audio over ethernet or (heaven forbid) the web is a very hard thing to do. Not something we can help you with on here. Also the Arduino really cannot do audio, and an I2C DAC is probably the second worst idea for audio ever.

Isn't this the same question as here? https://arduino.stackexchange.com/questions/81780/generate-a-true-analog-signal-using-arduino See my answer there, same solution, the sample rate and the output capacitor, C4.

Dorian, their is no error with c4 capacitor

@sanketjain It is in any configuration you have. Again the same explanation, the ADC works only with positive voltages. C4 is removing the the DC component and your mic signal is just floating between -0.7V and 5.7V limited only by the input clamping diodes. If you use the default 5V reference for  ADC just short C4. That will give ADC input a clean and stable signal around 2.5V

@dorian I have already done that that's why I said there's no error with c4

I don't understand, in this moment C4 is still there or not? You shorted C4, nothing happened and after that you removed the short or not?

ADC input has 100Mohm impedance. By placing C4 the signal at the ADC input has no DC path, is just floating between -0.7v and 5.7v , limited only by the input clamping diodes.
ADC can convert only voltages between 0 and the voltage reference, I suppose you use the default 5V reference.
But your signal is floating, and the ADC will cut any peaks outside of the conversion area giving the noise you hear.
Another issue I see here is that the data sheet of LM386 specifies a load between 4ohm and 32ohm. There is no warrantee that it will work without a load as in your case. Most likely not.
So you might want to connect C4 to a proper load and take the signal for ADC straight from pin 5 of LM386 which is auto balanced at half of the voltage supply.

simulate this circuit – Schematic created using CircuitLab
Later edit after I found the source of the schematic, there are also comments there that the schematic will never work with Arduino with the capacitor connected, the only working application was a sound detector where the signal distortion does not matter.
Please do not trust the content of any unknown website published by an anonymous just because it looks like a tutorial made by somebody who knows something.
Edit to add some info on how to debug the issue.
First, in the above schematic replace the resistor with a speaker and see if the sound is good. If not than see what is wrong with your amplifier.
If it's good and loud without any distortion then put the resistor back.
Use a binary mode serial monitor like Realterm to see how your data looks, the Arduino serial monitor works only in Ascii mode which turns a byte into three ascii chars which is slow.
Something like that
void setup() {
    Serial.begin(230400); // opens serial port, sets data rate to or maximum supported by your board to minimize latency
}

void loop()
   {
     unsigned int temp;
     temp = analogRead(0);
     temp = temp>>4; //strip low bits to fit in a single byte
     Serial.write(temp);
   }

Then see how your data looks, if you have to many 00 or to many FF than you know that your data us upper or lower limited or what is wrong with your signal.
I hope you are aware that the ADC conversion takes 100us and the wire transmission also around 200us the maximum sample rate you can expect is around 3khz and a maximum bandwidth of the audio signal of 1.5kHz which is half of the telephony bandwidth, you might want to use a faster DAC and use some non blocking ADC reading to use the time while ADC is working like in this article


text:
LEDs always dim with arduino nano
so I'm making an animated LED brake light using arduino nano, similar to this: https://www.youtube.com/watch?v=d5Ohzg3JKq0&ab_channel=IMEEMADE
I have 18 channels, with differet amount of series LEDs and resistor. All LED + are wired together, intended for 14.5V input, with individual resistor after the last LED cathode:
14.5V -> + LED - -> R -> GND
I have some channels with 1 LED, 2 LED and 4 LED, all tuned with different resistors so that each channel "pulls" ~20mA at 14.5V. 12V works fine as well just ever so slightly dimmer. On a power supply, I can ground any channel without cross talk, or ground all and all LEDs light up evenly (from what my eyes can tell).
I had originally planned on providing 5V input to the arduino using a buck converter and sinking each channel to a digital output pin (D2-D19 or D2-D13 + A0-A5). I ended up providing 12V to Vin and 12V to the LEDs as well as the arduino did not work at all as expected with 14.5V to the LEDs and 12V to the Vin.
My problem is that with this setup, no matter what I do in code, when the arduino is connected to Vin and ground, some LEDs are always lit dimly (D2-D13 oddly). They do indeed get brighter when pinMode is set to OUTPUT and digitalWrite({pin}, LOW) is called. But writing HIGH or setting pinMode to INPUT doesn't turn them off, just leaves them dim. I've tried adjusting Vin between 7-12V, setting the regulator to 5V and connecting directly to 5V. No change in behavior. Only thing that gets the LEDs to stop lighting dimly is lowering input voltage to the LEDs themselves. But then I don't have enough to drive the 4 series LED channels...
I know this can work because in the video I linked, there are 4 series LEDs driven in the same manner (though red, I'm using white), but not much is explained with the use of the arduino.
What am I doing wrong or how can I make this work? I need at least 12V to the LED board to ensure the 4 series channels light up properly. I've already maxed out the digital channels on the arduino nano from what I've read, so I can't use one as input (instead of Vin or 5V) if that matters or split the 4 series into 2 channels, etc...
Thanks in advance!

please draw a schematic diagram of the circuit ... the description is unclear

It sounds like you're using a 5V push-pull output as an open-drain one in a 12V circuit. So... yes you will get LEDs lighting up. You'll also get a dead Arduino if you're not careful.

This is basically how I have things wired up currently: https://www.circuit-diagram.org/circuits/de34ef54ab094db8b650731add9c1615

@Majenko I'm not quite sure tbh. I believe I only want to "pull" output from the LEDs. I don't fully understand the electronics behind the arduino, but they're cheap and don't require a special programmer, so I decided to use it as my controller.

Essentially what I'm trying to do is power the LEDs with the original voltage source (12-14.5V), and simply use the arduino to control when to ground each channel. I was not intending to put 12V through the arduino nor do I see why the voltage used to the power the arduino should matter in this case (aside from burning it out with too much on input).
And yeah, I'm pretty sure I killed one by trying to put >5V to pin A7 as an input instead of Vin :(

You can't drive LEDs from a source greater than 5V as a low-side switch with an Arduino directly. To do so you need an "open drain" output.
You can create them on the Arduino by adding a single transistor (N-channel MOSFET with "logic level" threshold, or NPN BJT) which the Arduino switches:

simulate this circuit – Schematic created using CircuitLab
R2 just exists to keep M1 turned off when the Arduino's not actively driving it (i.e., while the bootloader runs, etc).

Thanks @Majenko! I assume I need a separate resistor for each mosfet to ground otherwise if the gate pins are connected in parallel with one resistor I assume switching one output pin on the arduino will trigger signal all of mosfets?

For what to do see Majenko's answer.
This is regarding why you're seeing what you're seeing, or the nature of "What am I doing wrong" part of your question, and so why you need do something like what Majenko is suggesting.
Internal to the microcontroller, are diodes that protect it from voltage transients seen at the GPIO pin.  One of these connects from the GPIO pin to the VCC ("5V") pin(s) of the MCU.  This is pretty much the case with about any MCU, and so just about any Arduino's pins, with variations for things like 5V tolerant 3.3V parts.  The RESET pin on AVR-based Arduinos has an external diode on it for reasons that have to do with (not) wanting to enter high voltage programming.
When the GPIO is not OUTPUT-and-LOW, that is if it's HIGH, or INPUT, or INPUT_PULLUP, the current is going from your 12V nominal source, down through your load (LED and current limiting), into your GPIO pin, and through the protection diode onto the 5V rail of your Arduino.  From there it will compete with your 5V regulator (or USB host's regulator) to try to power everything on the Arduino, e.g. your "L" LED, the the serial transceiver, the 3.3v regulator, the AVR itself, etc. and whatever else you have connected to "5V".
So, your GPIO pins are only rated to whatever-VCC-is plus about a diode drop; somewhere around 5.5V in this case.  Above that voltage, the protection diode begins conducting and the GPIO doesn't appear high impedance to whatever is connected to it.
When you're lucky, there's enough resistance in your load to limit the current through the protection diode to:

less current than the continuous current rating of the protection diode, which is quite low, often under 1mA.  Otherwise, while this is going on you are likely trying to kill the protection diode and whatever else it can take out with it.

less current than the Arduino can make use of.  Otherwise the voltage at the "5V" well climb to the point of frying things.  It will be backfeeding whatever is supposed to be regulating the 5V on the Arduino, which may or may not be a problem depending on the design of whatever regulator that is.

If you'd done this with a larger load, it probably would have just popped things on your Arduino.  On the other end of the spectrum, putting a sufficiently large resistor in series with a GPIO pin is a common method of crudely accepting higher voltage input signals.
The circuit in Majenko's answer doesn't provide path would allow any current to speak of to travel from the 12V source into the GPIO pin.

Thanks for the explanation!


text:
How to get a stable LED lighting without scintillation over I2C bus
I built an 8x8 led matrix using white 5mm LEDs. I drive the LEDs using the MCP23017 connected to an Arduino over the I2C bus. The wiring of the LEDs in the matrix is such that a row is made up of 8 LEDs whose cathodes are wired together, and a column is made up of 8 LEDs whose anodes are wired together. The end of each row and each column is connected to a GPIO pin of the MCP23017.
The size of the pixel is 4cmx4cm which means that a row is 32 cm long (the same for a column).
I cannot get the light to be "stable", it keeps scintillating. I increased the clock frequency of the I2C bus from 100kHz to 400kHz, the light is more stable now, but not enough since the scintillation persists. Before that, I set the I2C clock frequency to 1700kH and the lighting became even slower..., I tried increasing the values of the pullup resistors of the GPIO pins of the MCP23017 to have a quicker response on its GPIO pins, but it had no effects.

I am thinking of 2 potential reasons:

The wires are too long for the I2C protocol to handle (a side of the led matrix is 32cm long).
the current reaching every column (the anodes) is not enough since there are so many leds to light up.

What do you think is causing this bad lighting? should I change the MCP23017 with another type of expander/protocol?
Here's the code:
#include <Wire.h>
#include <Adafruit_MCP23017.h>

bool four[3][5] = {{1, 1, 1, 0, 0}, {0, 0, 1, 0, 0}, {1, 1, 1, 1, 1}};
Adafruit_MCP23017 mcp;

void setup() {
  mcp.begin();
  for(int i=0; i<16; i++){
    mcp.pinMode(i, OUTPUT);
    }
}

void set_column(uint8_t col_idx, bool pixels[]){

  for(uint8_t i=0; i<8; i++)
    mcp.digitalWrite(i, HIGH);

  for(uint8_t i=8; i<16; i++) //Anodes are connected to Bank B of the MCP23O17
    if(i!=col_idx+8)
      mcp.digitalWrite(i, LOW);
    else
      mcp.digitalWrite(i, HIGH);

  for(uint8_t i=0; i<8; i++) //Cathodes are connected to Bank A of the MCP23O17
    if(pixels[i])
      mcp.digitalWrite(i, LOW);
}

void display_character(bool character[3][5]){
  bool pixels[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  for(int col=0; col<3; col++){
    for(int i=0; i<5; i++){
      pixels[i+3] = character[col][i];
      }
    set_column(7-col, pixels);
    }
}

void loop() {

  uint32_t time = millis();
  while(millis() - time < 1000)
    display_character(four);
}

The problem is that you're using I2C. It's just not fast enough.

What library are you using? It seems to do one transmission to set one pin. That would result in up to 24 transmissions. Also you write pins 0 to 7 twice, which is unnecessary. Instead it should be possible to write all 16 pins with one transmission. That would be way faster

MAX7219 would be much better driver for 8x8 matrix than bitbandig over extender. And as noted, you should write whole colum at once. However row outputs can drive only about 30mA, so I hope you don't have resistors for the colums too small

@Majenko, Even 400k Hz as clock frequency of I2C is not enough? why is that?

@chrisl I am using the library Adafruit_MCP23017 (I updated the code snippet in the question). Yes each pin of the MCP23017 setting takes a transmission... I realize I can set them much fewer transmissions. Thanks for the suggestion.

@KIIV I put a 20ohm resistor for each column, I chose this value to get as a brighter light as possible. Am I wrong on this point?

@S.E.K. "Absolute Maximum" sink or source current is 25mA per pin and 150mA for Vss / 125mA Vdd. If the forward voltage of LEDs is about 3V and Vcc for MCP 5V then you have  2V on 20R resistor -> 100mA (theoretically) for a single led. Basically it'll burn soon or later

@KIIV if the current per pin is 25mA, then the voltage through the 20R resistor according to Ohm's law is 20*0.025=0.5V, how did you find that I have 2V on 20R? (My electronics knowledge is kind of shaky...)

Led has for example nonlinear characteristic where at 3.1V there will be 20mA (depends on color and other params. After that point voltage raises slowly but current shoots up rapidly. 3.5v might be easily over 100mA.

Personally I would either use a dedicated LED matrix drive chip, or a dedicated Arduino to drive the display matrix directly.


text:
What would be the best way of dynamically 'change' instances regarding dynamic memory?
Since I'm very used to object oriented programming, I would like to use this into my design.
My application will have 4 led strips and each led strip will have a 'pattern' running on it. For this I like to create a base class and for each pattern a derived class. So this means I have 4 instances to a pattern. However, the pattern can change dynamically (based on music MIDI input). Each pattern has between 10-16 parameters.
I know dynamic memory allocation is mostly not a good idea in an Arduino. I'm using a Mega which has 8 KB. I found several 'solutions' but neither one I'm sure about. The first is not the solution but the way I should do it when I have 'plenty' of SRAM available (and simplified):
class Pattern
{
   public:
      virtual void Process();
}

class PatternA: Pattern
{
   public:
      void Process();

      // In example I only use 2 out of 10-16 parameters
      uint8_t SetColor(uint8_t colorIndex);
      uint8_t SetSpeed(uint8_t speed);

   private:
      uint8_t _colorIndex;
      uint8_t _speed;
}

// In this example I only use 2 out of 24 patterns
class PatternB: Pattern
(like PatternA but with its own implementation)

class LedStrip
{
   public:
       void SetPattern(Pattern* pattern);

   private:
       Pattern* _pattern;
}

Other derived classes may have other (named) parameters.
When changing instances, I would get something like this:
LedStrip::SetPattern(Pattern* pattern)
{
    delete _pattern;
    _pattern = pattern;
}

pattern* pattern = new PatternA(...);
ledStrip1.SetPattern(pattern);

However, since the new pattern may use more memory then the deleted pattern, there will be a memory gap. So this is not suitable for the Arduino to be used I assume.
Solutions:
1. Create all possible patterns beforehand.
Assume I would implement 24 patterns, and create any possible combination, I would have 4 (led strips) * 24 (patterns) * 13.5 (average number of parameters) = 1,296 bytes. This seems a bit much as only 4 are 'active'.
class LedStrip
{
   public:
      enum EPattern {A, B}

      void SetPattern(EPattern pattern);

   private:
      PatternA* _patternA;
      PatternB* _patternB;

      Pattern* _pattern;
}

To change pattern:
void LedStrip::SetPattern(EPatternpattern)
{
case EPatternA: _pattern = _patternA; break;
case EPatternB: _pattern = _patternB; break;
}

ledStrip1.SetPattern(EPattern::A);

Of course I could also pass a pattern where the patterns are created globally but this is does not matter for this example. The idea is to create 4 (led strips) * 24 (patterns) instances beforehand and never use delete. This means out of the 4 * 24 patterns, only 4 are used, 1 per led strip.
Of course this causes a lot of unused memory.
2. New/Delete
I create the 4 correct derived instances and when one pattern (instance) change, I delete the instance and create the new. When I put no (instance) variables in the derived class, this could work, but I have some specific questions regarding this solution:
I make sure all the max. parameters are in the base class and I 'cast' 4 instances of the base class to a derived class. This seems a bit of 'tricky' solution.
class Pattern
{
   public:
      SetParameter(uint8_t parameter, uint8_t parameterValue);
      uint8_t parameter GetParameter(uint8_t parameter);

   private:
      uint8_t _parameters[16];
}

class PatternA: Pattern
... (does not have any variables)

To change pattern:
delete ledStrip1.pattern;
ledStrip1.pattern = new PatternA();

Question: can I assume the deleted memory of the old pattern will be replaced by the new pattern as the memory usage is equal?
The downside of this way is that each pattern will have the worst-case amount of parameters in each instance, but this is not a problem (I only have 4 led strips).

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

I don't know what you'll make of this, but:
If you can set aside a properly aligned and sufficiently large memory block you can use the placement form of the new operator.
Placement new is essentially new without the the part that behaves like (and typically is) malloc.  Or put differently, it lets you construct an object inside of already allocated memory.  By "already allocated" I don't mean already allocated on the heap; the memory can come from whereever you want.  This more or less lets you make your own custom allocator with predictable behaviour that you don't get from generic heap allocator like malloc.
So you can set aside memory however you want.  It can be an array of unsigned char in static storage duration (global, static local, static member).  And placement new can put an object into it, or importantly, into part of it.  Basically you're making your own arena for your allocator.
It's up to you to align the memory correctly.  There are compiler keywords that can help with that.  You can also resort to an older technique oversizing the block just large enough so that a properly aligned sub-block exists and can be found within it.  However, on an 8-bit microcontroller like the AVR, there are no alignment requirements to speak of.
When it comes to using delete, well, you don't.  You just call the destructor on the object directly.  There are ways you could try to clean that up also.
If I become awake enough to completely understand your specific usage, I may try to make an example.  But that is the basic technique I'd consider.

Regarding avoiding new/malloc: the case against them it is often slightly overstated.  For example, doing a set of malloc / new at the beginning, and only the beginning, of your program and not thereafter is normally fairly stable and predictable.  For example, you can read a configuration out of eeprom in setup() and use that information to allocate say three "dynamic" "arrays" with malloc, that you know they won't total more than some testable maximum.  Maybe a slightly more accurate warning for them is something like: you will get into trouble if you don't have a reasonable understanding of your maximum heap usage and if your usage pattern requires that you free/delete/remalloc.
I mention this in part also because it's not completely unreasonable to malloc/new once, early in your execution, to acquire an arena to use with placement new calls.

Thanks for all this info ... I also need to go through a few times through it (not heard of placement new before).

If you've ever wondered what something like std::vector is doing when you resize() to larger than current size, size() well, that's basically it.   For the new elements where the vector was extended, it's placement new-ing with T's the default constructor into memory it basically realloc()d.  Where the vector is resized smaller, it is manually calling the destructors of those elements that go away.

If you can tightly nail down what you want to do at runtime, you may find your design approaching something vaguely like a container, only fixed capacity (not necessarily size) and handles containment of two or three types as opposed to just one.

I knew about reallocating/keeping the size for bigger/smaller vector, but not about the placement new. About the container, that's indeed true. I could make it easily workable with a big switch statement, but I'm planning to create more patterns (derived classes) to chose from, and like to keep them isolated (thus using derivation instead of some switches.

Yeah, I read something in your question that indicated an understanding of heap usage patterns.  But it's something I wanted to spell out for anyone reading the answer.  I might have left that part out entirely except for wanting to mention that reserving your own arena through the general heap allocator is not unreasonable, in my opinion anyway.

Regarding "vaguely like a container", I was more speaking of how it manages its own memory.  Not so much what the interface looks like.

Yes I understand ... I will check this evening some ideas to see what works.

I tried the placement new and it works. I use a Max(sizeof(...), sizeof(...), sizeof(...)) for each derived type so I only have the derived classes in one place, which is part of the factory to create the different derived instances.
Tip for others: don't forget to #include <new>

Good deal.  If I understand correctly the way you've chosen to employ this is roughly like what I expect the internals of an std::variant do.  That was the sort of example I'd thought to make for you, but I wasn't quite sure whether or not you were willing to accept the overhead of sizing items to the largest type and therefore would have needed something more complicated but otherwise using placement new.

Let us continue this discussion in chat.

Pattern classes are code and variables for the current set of parameters. The code doesn't take SRAM it is executed from flash. I would instance all 24 patterns for all 4 LED strips using global two dimensional array.
Advanced version could be a pool of pattern instances allocated with 'new' but never deleted, only reused. You would only create a new pattern class instance of requested type, if there is no free pattern instance of that type in the pool.
The parameters sets could be stored in PROGMEM or in EEPROM and loaded as needed into the variables of the corresponding pattern class instance.

For the advanced version idea, I doubt that will work to be honest. In worst case I need 4 of each (pattern class) instances, running out of memory (or using a lot of it).
Maybe it was not clear, but the parameters are flexible, meaning I could have 20 pattern class instances for a single pattern, with all different parameters. The parameter sets can be stored in EEPROM/PROGMEM, but the parameters need to be copied to memory (to four instances). But maybe my question is not really clear.

@MichelKeijzers, can't you load the parameters in an existing unused pattern class instance? as I understand there are only 4 active patterns. so in worst case the pool would contain 4 x 24 pattern objects

Yes, but that's too much ... 4 * 24 patterns * 16 (parameters) = 1,536 bytes which is quite a bit. Especially since there will be needed some other values to be stored as well.

When I need dynamically allocate memory, I generally pre-allocate a pool of memory blocks, each sufficiently large for the maximum size request I'll handle. Then, Whether the app requests 1 byte or MAXSIZE bytes, it gets a pointer to the first available one of those MAXSIZE blocks in the pool. free()ing such a block works just as you'd expect. Since all allocations are the same size, and no more memory is ever taken from the real heap, the pool doesn't have to (and can't, in my implementation) grow.
If this is the only dynamically allocated memory for your application, you can re-write new() and delete() to use your pool-allocator, or, if new() and delete() are implemented as wrappers around malloc() and free(), just replace those more primitive ones with the pool-based malloc() and free().

Thanks for the answer, I used placement new which works great in my case. In my case I only have 4 fixed elements (which will now be 'new'ed all the time and destructed, but not deleted).

Since you only need four objects at any given time, it would be wasteful
to statically allocate 4×24 objects, as you only really need four times
the size of the largest object. You can still use static allocation by
using an array of unions: each cell of the array will then be large
enough to store the largest possible pattern.
There may be more elegant solutions, but the simple approach is to use a
tagged union, i.e. a struct holding both a union and an extra variable
telling you what data type the union is actually holding. Beware that
there are limitations on what type of objects you can put in an
union. You should be safe if the actual classes have trivial
do-nothing constructors.
Below is a simplified example with two classes that each hold only a
number, either an uint8_t or a uint16_t:
class Pattern
{
public:
    virtual void process();
};

class Pattern8 : public Pattern
{
public:
    void process() { Serial.println(8000 + param); }
    void set_param(uint8_t param8) { param = param8; }
private:
    uint8_t param;
};

class Pattern16 : public Pattern
{
public:
    void process() { Serial.println(16000 + param); }
    void set_param(uint8_t param16) { param = param16; }
private:
    uint16_t param;
};

// This is the tagged union.
struct AnyPattern : public Pattern
{
    AnyPattern() {}  // must be explicitly defined
    void process() {
        switch (type) {
            case TYPE8: pattern8.process(); break;
            case TYPE16: pattern16.process(); break;
        }
    }
    enum { TYPE8, TYPE16 } type;
    union {
        Pattern8 pattern8;
        Pattern16 pattern16;
    };
};

void setup() {
    AnyPattern patterns[2];
    patterns[0].type = AnyPattern::TYPE8;
    patterns[0].pattern8.set_param(21);
    patterns[1].type = AnyPattern::TYPE16;
    patterns[1].pattern16.set_param(42);
    Serial.begin(9600);
    patterns[0].process();
    patterns[1].process();
}

void loop(){}

I upvoted, although I don't like the union solution that much to be honest, although it works. I used the placement new method which works great for me.


text:
Arduino FFT results of "beautiful" signal seem inconsistent
I have a BEAUTIFUL doppler radar signal here from a 24.050-24.250 GHZ sensor measuring a very small object at 143 fps speed (speed from another 10 GHZ radar) in a measuring area of about 300mm-500mm in front of the sensor(s). The signal was limited to around 3V with a zener diode.
I took several measurements (at this speed and object size and distance from the sensors) and there were about 8-20 wave peaks on the average above the trigger threshold level (2.58V) until the end of the trigger threshold level box where the peaks start falling off.
Looking at the graph, one can discard the first 3 peaks and the last 2-3 peaks above the trigger threshold which leaves a decent area (orange box) for sampling of the peaks for frequency/period. So in this case we have about 17 "good" peaks inside the orange box to be measured. In this case the orange box (measuring sample area) is 5 x 500 us = 2500 us in length.
I know that an FFT would be the best way to measure, but the one FFT program I used with Arduino gave me inconsistent results. Not sure how to set the sample size (must be in power of 2 increment from 2 to 256). And the maximum sampling frequency is 10kHz (hardware limitations).
I set sample sizes to 4 and 16 and 128 at 10Khz frequency, but get inconsistent results. I suspect logarithmic results, but even those do not add up. At times I get within 2-3% but at times it's off by 30% with no apparent correlation.
What I know:

with this 24 GHZ radar (no angles) the speed = frequency / 44 to arrive to km/h  (km/h x 1.097 = fps)
in this case the o-scope measured 6613 Hz with a 151.2 us period, but that was for the entire area above the 2.58V trigger threshold. But it also had some much more varying readings as noticeable in the first 2-3 peaks after the trigger and the last 2-3 peaks that are falling off to below the trigger threshold. I excluded these from the orange box.

How do I set up this FFT, or another FFT, or similar method, that would determine the dominant frequency from data inside the orange box?  The orange box sample size will always seems to be between the 8-20 number of peaks range. I measured frequency and periods from "positive rising edge to positive rising edge".
I tried with an Adafruit nRF52840 Express (16 Mhz clock) and an Adafruit 32u4 Bluefruit  (8 Mhz clock).
I am using this Arduino FFT library:  https://github.com/kosme/arduinoFFT
Some broad info about this FFT itself: https://www.norwegiancreations.com/2017/08/what-is-fft-and-how-can-you-implement-it-on-an-arduino/
Thank you.
    #include "arduinoFFT.h"

#define SAMPLES 4         //Must be a power of 2     128, 256?
#define SAMPLING_FREQUENCY 10000 //Hz, must be less than 10000 due to ADC

arduinoFFT FFT = arduinoFFT();

unsigned int sampling_period_us;
unsigned long microseconds;

double vReal[SAMPLES];
double vImag[SAMPLES];

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

    sampling_period_us = round(1000000*(1.0/SAMPLING_FREQUENCY));
}

void loop() {

  if (analogRead(A0) >600) {

    /*SAMPLING*/
    for(int i=0; i<SAMPLES; i++)
    {
        microseconds = micros();    //Overflows after around 70 minutes!

        vReal[i] = analogRead(A0);
        vImag[i] = 0;

        while(micros() < (microseconds + sampling_period_us)){
        }
    }

    /*FFT*/
    FFT.Windowing(vReal, SAMPLES, FFT_WIN_TYP_HAMMING, FFT_FORWARD);
    FFT.Compute(vReal, vImag, SAMPLES, FFT_FORWARD);
    FFT.ComplexToMagnitude(vReal, vImag, SAMPLES);
    double peak = FFT.MajorPeak(vReal, SAMPLES, SAMPLING_FREQUENCY);

    /*PRINT RESULTS*/
    Serial.println(peak);     //Print out what frequency is the most dominant.

  //  for(int i=0; i<(SAMPLES/2); i++)
   // {
        /*View all these three lines in serial terminal to see which frequencies has which amplitudes*/

        //Serial.print((i * 1.0 * SAMPLING_FREQUENCY) / SAMPLES, 1);
        //Serial.print(" ");
      // Serial.println(vReal[i], 1);    //View only this line in serial plotter to visualize the bins
  //  }

 }

    //delay(1000);  //Repeat the process every second OR:
   // while(1);       //Run code once
}

EDIT:
@Dorian  After several days of tribulations and frustrations, I read and re-read your additional info and helped me clarify things better. I think I have some hardware limitations.  By the way...yes I do have a 27pf capacitor to the GND with a 3.3K resistor and a 3V zener in parallel at the OP AMP's outlet.
But let me explain first: I decided to add a comparator after the sensor and OP AMP.  Now I have a baseline voltage at HIGH (3.1V).  Previously, as I posted, the OP AMP had baseline of 1.65V and when motion is detected the voltage bounces between HIGHs (2.5V-3.1V)  and LOWs (1V-0V) for about 10-20 times until it settles at the 1.65V baseline again.  I suspected that the HIGH and LOW thresholds were not that clear. In order to get a clear HIGH or LOW I added the comparator.  These readings go to an MCU's digital Capture pin capable of 62.5ns ticks (16 MHZ). The Arduino program that counts the pulses is verified to work.  In the specs the MCU at 3.3V has 1V and below as LOW and 2.5V and above as HIGH.
See the new oscope reading (attached).  I get accurate pulse captures (matching the oscope), but I only get about 3 or 4 pulse readings instead of the 10-20 showing on the scope.    I used LOW capture (below 1V).  But even if I switch to TOGGLE capture (double) I seems to be getting only the last 3-4 complete waves (1/3rd) and seem to be missing the first 2/3rds. Or may getting every 2nd or 3rd?
My OP AMP is fast at 50 MHZ and I used to measure 100us-800us pulses with it accurately. And my comparator (after the OP AMP) is a MAX 9052 with a 400ns propagation delay. 40-80ns rise/fall time.  So I should not be missing any pulses.  The Arduino program cannot be that slow either.
EDIT #2:
//the best resolution you can achieve is 1/16us.

#include <Arduino.h>

#define FREQ_MEASURE_PIN 8  // actual 6 is PIN D11 and 8 is PIN D12 on Adafruit Feather Express nRF52840 LE, pin 11 is D12 itsybitsy 52840
#define PPI_CHANNEL 1u
#define GPIOTE_CHANNEL 1   //just picked channel #1

volatile int pulseCount = 0;
volatile unsigned long duration; //Pulse2 - Pulse1 = count of time ticks at 62.5 ns each tick (16 Mhz clock scaled at 0)     (expected value example: 792.5620  => 7925620)
volatile unsigned long pulseTime;   // first signal reading
volatile unsigned long lastTime;   //  most current signal reading

void setup() {

    Serial.begin(115200);

  initCounter();
}

void loop()
{

  if  ((pulseCount == 2) && (duration>0))  {

    Serial.println(duration);   //

   }

}

//must use extern "C" because IRQ will not compile since it's "C" coded
extern "C"
{
void GPIOTE_IRQHandler(void)
{

  lastTime = pulseTime;

  if (NRF_GPIOTE->EVENTS_IN[GPIOTE_CHANNEL] == 1)    //if an input pulse is detected on pin 6 then...
  {
    NRF_GPIOTE->EVENTS_IN[GPIOTE_CHANNEL] = 0;     //  reset event detection to zero to ready for next event detection?
    pulseTime = NRF_TIMER2->CC[0];                     // save Timer value at same time when signal was read on pin 6

    //pulseCounter
    pulseCount++;
    duration =(((pulseTime*10000) - (lastTime*10000))/16); //multiply by 10000 to avoid float, and divide by 16 for 16 Mhz clock tick = 62.5 ns per tick

   // goes from here to Loop if pulse = 2 (complete PULSE) so a reading can be sent
    }
  }
}

void initCounter()
{
  NRF_P0->PIN_CNF[FREQ_MEASURE_PIN] = GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos |        //sets up PIN 6 for event read
                                      GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos |  //pos going signal
                                    //  GPIO_PIN_CNF_PULL_Pulldown << GPIO_PIN_CNF_PULL_Pos |   //pulldown LOW so no floating of pin voltage
                                   //   GPIO_PIN_CNF_SENSE_High << GPIO_PIN_CNF_SENSE_Pos;      //a HIGH POS signal is the trigger

                                      GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos |   //Pullup or Pulldown LOW so no floating of pin voltage
                                      GPIO_PIN_CNF_SENSE_Low << GPIO_PIN_CNF_SENSE_Pos;      //a HIGH POS signal is the trigger .... or a LOW POS

  NRF_PPI->CHEN |= 1 << PPI_CHANNEL;
  NRF_PPI->CH[PPI_CHANNEL].EEP = (uint32_t)&NRF_GPIOTE->EVENTS_IN[GPIOTE_CHANNEL];
  NRF_PPI->CH[PPI_CHANNEL].TEP = (uint32_t)&NRF_TIMER2->TASKS_CAPTURE[0];   //sets up Timer channel

  NRF_GPIOTE->CONFIG[GPIOTE_CHANNEL] = GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos |         //sets up pin for event capture
                                    FREQ_MEASURE_PIN << GPIOTE_CONFIG_PSEL_Pos |                   //sets up event capture on pin 6
                                    GPIOTE_CONFIG_POLARITY_HiToLo << GPIOTE_CONFIG_POLARITY_Pos;   //sets event capture signal trigger type:  LoToHi   or HiToLo or  Toggle
  NRF_GPIOTE->INTENSET = (1 << GPIOTE_CHANNEL);    //  Interrupt routine setup on a pin
  NVIC_EnableIRQ(GPIOTE_IRQn);                     //  Interrupt routine setup if signal detected on pin 6

  NRF_TIMER2->TASKS_STOP = 1;    //stops timer
  NRF_TIMER2->TASKS_CLEAR = 1;    //clear timer to zero
  NRF_TIMER2->MODE = TIMER_MODE_MODE_Timer << TIMER_MODE_MODE_Pos;   //sets up TIMEr mode as "Timer"
  NRF_TIMER2->BITMODE = TIMER_BITMODE_BITMODE_32Bit << TIMER_BITMODE_BITMODE_Pos;    // sets values for Timer input
  NRF_TIMER2->PRESCALER = 0;       //read at max resolution (at MCU speed)
  NRF_TIMER2->TASKS_START = 1;      // starts the Timer
}

EDIT #3:  ================================================
I added the OP AMP circuit below. This circuit worked fine with an inductive sensor using eddy-currents. I measured @ 700-800us single-shot pulses very accurately, but did not have the R1 (22k) resistor. Added the R1 resistor and the GND immediately after it when replaced the inductive sensor with the 24 GHZ radar sensor because I was not getting readings. This circuit provides the first graph I posted, centered at around 1.6V. I took the comparator after the OP AMP off as not to complicate the circuit, and also it had some artifacts.
In summary:  the suspicion is that the Arduino program I posted for the nRF52 is not fast enough to capture 100us pulses in fast succession.  I tried to use BLE only and uncommented the SerialPrint and SerialBegin, etc....but even with BLE I got the same limited pulse readings.  For example: there were 10-20 pulses, I was only able to capture the last 1/3 of the pulses (3-4).  I tried HIGH and LOW (HiToLo/LoToHi/Toggle) as well.
The radar sensor is:  3.3V supply. IF out (signal read) is between 60mV-250mV.  60mv being the zero signal state.
Here are some sample period (wave pulse) readings in micro seconds:

97.0000
53.2500
45.2500
42.0625
40.8125
**40.9375**

And the actual period that it should read based on reference measurement:  **38.4435**us

==========================
Another set of period (wave pulse) readings in micro seconds:

95.6875
55.0000
46.7500
41.7500
**40.2500**

And the actual period that it should read based on reference measurement: **39.1703**us

So the last reading is quite close, but not proportionally close where I can "estimate" the actual value reliably.  So it's not for example off by 5.13% every time, but it's off by 3-6%.
Graph of example wave pulses (smaller means shorter pulse):

The ZENER at the output is there to clip the waves from going over 3.3V which can damage the MCU's input capture pin.

Thank you for your assistance!
For information only: THESE WERE THE OSCOPE READINGS WITH THE COMPARATOR CIRCUIT ADDED ON TO THE OP AMP'S OUTPUT BUT I SINCE REMOVED THE COMPARATOR CIRCUIT:

EDIT #4:   It's been quite a delay as I needed to do something else after not getting anywhere with this project.  Then today as I was struggling again I think I arrived to the solution.  It requires more work, but at least I have a cobbled together version that seems to work well.
The problem seem to have been with the signal itself being a sine-wave or a quasi-square wave.   Using an Arduino AVR sketch for the internal comparator that is being assisted by the comparator's ISR to "square" the incoming signal with timers and interrupts by toggling another pin into the Ref pin of the comparator, I was able to get reliable readings.   I actually ended up using an external comparator with the AVR and an nRF52 to count to periods.  This is the program and looks another person also went through hell:
https://electronics.stackexchange.com/questions/357131/random-and-unpredictable-analog-comparator-behaviour/566974#566974
I prefer to use the nRF52 because of the BLE integration, but I think I can make the AVR work first stand-alone by figuring out how to edit the library to reverse the interrupt from Low to High to High to Low...since the output of the comparator is opposite of my signal input.
Of course I still need to process the readings to sort out the dominant frequency, but manually I was able to calculate 5 out of 5 events within 2-5% of the valid value.
However, it seems that the key in the input signal being read reliably is the additional pin that is used to "convert" the sine wave into a square as part of the comparator's interrupt routine.
I still need to wrap my head around how the AVR program's additional pin toggled LOW/HIGH connected to VREF of the comparator "shapes" the sine wave and acts as a feedback for hysteresis.  I believe that which ever way I arrive to a "nice" square wave for the AVR's or nRF52's input counter to read will be a winner.  But I will open an new topic if I get stuck.  Thank you for your help and any inputs suggestions are welcomed.
EDIT #5: Based on a suggestion in another post I decided to use a 74xx14 Schmitt Trigger at the output of the op amp and it worked really well.  The square pulses were well defined (4ns rise time in specs) that I was able to identify every one of the pulses (usually between 5-20) in the software.  Manual calculations lead to accurate frequencies too.
Now I need to figure a way to identify the dominant frequency that has to be done on software.  I tried several FFT/FHT and ADC averaging programs, but none of them worked right.  Will bring this up in a separate question.  Thank you all for your help. Seems like the root problem was signal conditioning on my part.

I would suggest FFT is not the way you want to go. Since you only care about the dominant frequency, and you essentially have a square wave there, you can use the input-capture peripheral present in most MCUs to measure the time between leading edges, and calculate the frequency from that.

Thank you. I was wondering about that too.   I actually have a program for the freq/period at 62.5 ns resolution.  But I was expecting some FFT magic.  However, I think you are right, I need to do some legwork and try to extract the dominant freq from these 8-17 readings.I do not know statistics, but I can read up on it.  Any suggestions on what to apply?  Average, deviation, etc?  These is a sample period reading after I took out the outliers from beginning/end/zeros/duplicates: 2703750
2603125
2326250
2391250
2426250
2335625
2090625
2046875
2239375
2145000
2763750
2685625

I have no idea what those numbers represent. If you measure the time between successive rising edges and discard the first X results you can then take a simple average. That would give you the average speed across that sample set. Or you could take the mode (most common result) or median (middle value) or whatever you like. It all depends what you want to do with the data. A simple mean average is probably simplest.

Thank you.  Those numbers are the period values between consecutive rising edges.  They need to be divided by 10,000 to get 239.125 us , 242.625 us , etc  Pretty consistent AFTER I took out the outliers" by hand".   Will work on a formula for automating the taking out the outliers.

Maybe a "mode" average would do it for you.

Reading up on the "mode" average, I think you are correct, as this would give the best representation of the "dominant" frequency.  Will try that.

Using analogRead() in a loop gives a minimum sampling period of 112 µs (i.e. 8.929 kS/s). At this sampling rate, an input signal at 6.613 kHz is aliased to 2.316 kHz. But with only 4 samples, the spectral resolution is f_samp/4 = 2.232 kHz.

@Edgar Bonet   Thank you for your repeat assistance.  The first couple of Arduino programs I used were Nick Gammon's AVR register-level digital input-pin capture mixed with AnalogRead() as the threshold.  But then when using the hardware comparator I switched to an nRF52 with Arduino register-level TOGGLE and LOW interrupt-based input capture (16 MHZ) without analogRead().   The Oscope has the near correct freq/period readings once I zoom in to a sample of 2-3 waves. With the same program I can capture a single pulse of around 780 us (or even down to 100us.- have not tried yet)

@ Edgar Bonet continued: with doppler I get 50-250us pulses as LOW to LOW signal (half wave?)    Added the new nRF52 Arduino program above under EDIT #2.

The graph looks pretty bad. Post the schematic please. But the missed pulses might be due the serial.print() taking to much time. It's 8 us x 10 bits  x at least two bytes = 160us, vrey close to the pulse width.

@Dorian  Thank you for the reply/tip.  I was thinking about the SerialPrint as a possible problem but dismissed it.  Now that you mention it I will switch over to BLE which is what the final program will use anyway.  I need to revise the schematic with the comparator added and a resistor by the Op AMP inputs...and then post it.  But let me try the BLE first because I suspect that may be the issue.  I changed the SerialPrint from 115200 to 500000 during a couple of my tests but can't recall any huge difference.  So BLE first and will report back!  Thank you.

@Dorian Added EDIT #3. Reconfigured Arduino program with BLE but same results, with only about last 1/3 of pulses registering only. Uncommented all "Serial" lines. Posted OP AMP circuit but took off the comparator add-on to make it simpler. Please, note that R1 (22k) resistor and GND after that are my "improvisations" when switched from an inductive sensor (worked great) to the current 24GHZ radar sensor. This circuit provided the "beautiful" graph (1st one) in my original post.  Also, the OSCOPE does give correct freq/period after I focus down to a full wave near the end of the pulse train.

I have a simple frequency generator and will set it for a steady pulse of 700us to feed into the OP AMP instead of the sensor.   Will gradually start reducing the period (pulse) from 700us to 20us and see how the input capture program and Arduino BLE and/or Serial readings turn out..  Maybe able to determine if there is a software limitation.

Using the freq generator it seems that the program hangs at around 500us and below with a 10% duty-cycle wave of around 1.9khz.  I made some temporary modifications to the program where it just splits out raw data...and was able to go down to 15us pulses.  Still checking...

All specifications for the speed of the opamp are given assuming the linear region of the opamp which is not the case here, the opamp output as you see is limited to 0v and 3.3v which also makes the zenner useless. Try to replace R27 with a higher value until you get a clean, not limited output then use the comparator or just use only the comparator without opamp.

Also something is really weird with the comparator output, certainly something is wrong in the way you use the comparator. This comparator has hysteresis, I can't figure how you got to these graphs.

To have a meaningful result from the Fourier transform the input signal must filtered to a bandwidth at most half of the sample rate.
Your 10khz maximum sample rate which I suppose is given by the maximum sample rate of the ADC is less than double of 6.61 kHz , the base frequency of your signal.
Even more, you limit the signal adding high frequency components to the signal that already doesn't fit into the required bandwidth.
You better stick to zero cross detection using both rising and falling edges to have more data to average.
You might also check which part of the signal has the correct speed data against the real speed or to check  for a pattern, I see the middle period is lower then at the beginning and the end of the signal.
Later edit. Some things you should check and explanation on why is pointless to use FFT on this.
First, I see you have a clean middle centered signal between -0.7 and 3V.  Maybe there is an output capacitor on the sensor that auto limits itself between Zener voltage and the lower clamp diode. The middle is somewhere at 1.5V.  But the middle of the logic voltage is somewhere at half VDD, 2.5V.
Maybe that's why you have variations of pulse length from the beginning to the end of the train pulse because the decision line is above the middle line.
Of course setting the decision around the middle line might give a lot of noise but you can either use an envelope detector to see when the pulse begins or a Schmidt trigger so only signal above the hysteresis will pass.
I think that truly detecting the passes around the middle point will give you more reliable and consistent results.
About using discrete Fourier transform (fast or not) for finding the base frequency of the signal, there is no way to obtain a reasonable resolution using such a short signal.
The DFT is discreete not only in time but in frequency to. Anybody who has some basic knowledge about DFT knows that the maximum resolution in frequency that you can obtain in a t timeframe is 1/t, here for 2.5ms the frequency will be in steps of 400Hz, if you have maximum 8kHz signal you will have 20 fixed frequency values from 0 to 8kHz no matter how many samples you take, no matter on what software you make the processing or platform. It's a dead end.

Thank you @ Dorian.  I spent hours yesterday on Arduino and with a reference doppler radar (for actual speed) trying to extract data patterns that are repeatable and match the real speed at least remotely.  My test conditions are ideal, but getting considerable variances that should not be the case.  I need to re-visit the theory/etc behind doppler and also read up on signal-processing.  I need to take a 30,000 feet view because I think I am running down rabbit holes.

@ Dorian   Please see my edits above in the original post.  I added a comparator to get a clear LOW instead of zero-crossing.  When I pick apart my oscope readings and manually examine each wave they do match up with the pulses captured by the MCU.  But seem to be missing the first 2/3 and the last wave or two.

Posted above that I need to setup from scratch an OP AMP ob breadboard and revise my comparator also, because the current OP AMP is on a soldered PCB and can only do so much for "re-arranging" the two inputs.   Will report back.  Will make sure that the Op AMP and comparators are fast enough for a 50us period signal (double freq minimum).

I understand that it's difficult to unsolder R27. You might also use a smaller R23 to reduce the gain by piggybacking with a parallel resistor.

Unfortunately, I have most of the op amp entombed in hot glue.  I am making a new one and carefully selecting the bandwidth, etc. Also a comparator chip to get clear High/Lows.  Should get it this weekend.  At times frustrating (because I have huge gaps in my knowledge) but small victories make up for it! :)

Any reason for cowardly silent downvote? - See Why isn't providing feedback mandatory on downvotes, and why are ideas suggesting such negatively received?. Comments are not required on downvotes, and the absence of a comment is not cowardly. Read the link to see why. If you had to comment on downvotes, then surely upvotes without a comment are also cowardly? Don't let it worry you. I get downvotes on my posts and just ignore them. :)

@NickGammon Thank you Nick  I explained why I downvoted the other answer so others appreciate by themselves and in exchange shortly after I received a silent down-vote, I can only guess that It was from the fellow I down-voted. Why should I explain an upvote to a good and complete answer? You could do something at least where the downvoter has his own answer.

@Dorian Making assumptions about who downvoted and/or why will lead down paths of frustration--don't go down that path. It's not clear what would be reasonable to do if a downvoter-with-an-answer downvotes a different answer: randomly assigning downvote motivation on the part of the general public is fraught enough--putting any sort of official mechanism in place for that would be even worse.

@DaveNewton You're both right. Nothing is simple. Fixing something can break something else. That's life. Thanks for deleting the comment. It sure didn't helped anybody. Oh, you didn't, I thought It cant be deleted after all this time. I did.

I don't know and can't find out who up-votes or down-votes. Sometime there is "revenge" downvoting - it happens to me too and I am a moderator. (People don't like something I did and then start down-voting my posts, lol). Serial revenge-downvoting can be picked up by Stack Exchange's automated systems. One or two is nothing to worry about.

I cannot really understand why you can't catch pulses at 6613 Hz.
That is not that fast, even for an Uno.
I did the following experiment with an Uno: I use Timer 2 to
generate a short burst of pulses on pin 11 (PB3 = OC2A). This pin
is connected to pin 8 (ICP1), where I use Timer 1 to capture
the falling edges. In the input capture ISR I count the number of edges
received, and I also record the timestamps of the first and the last
edge. This way I can compute the received frequency.
The result of the experiment is that this way I can reliably measure
frequencies up to 125 kHz. This is about 19 times the
frequency of your burst. The measurement becomes unreliable if I keep
increasing the frequency.
Here is my test code:
// CPU cycles per half-period of the pulse burst.
const uint16_t half_period = 64;

// Statistics recorded by the input capture ISR.
volatile uint16_t capture_count;
volatile uint16_t timer_start;
volatile uint16_t timer_end;

// Input capture ISR.
ISR(TIMER1_CAPT_vect) {
    uint16_t now = ICR1;
    uint16_t count = capture_count;
    if (count == 0)
        timer_start = now;
    else
        timer_end = now;
    capture_count = count+1;
}

void setup() {
    Serial.begin(9600);
    Serial.print("Expected frequency: ");
    Serial.print((float) F_CPU / (2*half_period));
    Serial.println(" Hz");
    Serial.println("Measured frequency:");
    Serial.flush();

    // Configure Timer 2 for fast PWM.
    DDRB  |= _BV(PB3);    // digital 11 = PB3 = OC2A as output
    TCCR2A = _BV(COM2A0)  // toggle OC2A on compare match
           | _BV(WGM21);  // mode 2 = CTC, TOP = OCR2A
    TCCR2B = 0;           // keep timer stopped
    OCR2A  = half_period - 1;

    // Configure Timer 1 for input capture.
    TCCR1A = 0;           // normal mode
    TCCR1B = _BV(CS10);   // clock @ F_CPU
    TIFR1  = _BV(ICF1);   // clear input capture flag
    TIMSK1 = _BV(ICIE1);  // enable input capture interrupt
}

void loop() {
    // Reset the counter.
    capture_count = 0;

    // Send a burst of pulses.
    TCCR2B = _BV(CS20);   // clock Timer 2 @ F_CPU
    delayMicroseconds(1000);
    TCCR2B = 0;           // stop Timer 2

    // Report results.
    uint16_t timer_cycles = timer_end - timer_start;
    uint16_t pulse_count = capture_count - 1;
    Serial.print(pulse_count);
    Serial.print(" pulses in ");
    Serial.print(timer_cycles);
    Serial.print(" timer cycles -> ");
    Serial.print((float) pulse_count / timer_cycles * F_CPU);
    Serial.println(" Hz");
    delay(500);
}

And here is the output:
Expected frequency: 125000.00 Hz
Measured frequency:
255 pulses in 32640 timer cycles -> 125000.00 Hz
255 pulses in 32640 timer cycles -> 125000.00 Hz
256 pulses in 32768 timer cycles -> 125000.00 Hz
256 pulses in 32768 timer cycles -> 125000.00 Hz
255 pulses in 32640 timer cycles -> 125000.00 Hz
256 pulses in 32768 timer cycles -> 125000.00 Hz
256 pulses in 32768 timer cycles -> 125000.00 Hz
256 pulses in 32768 timer cycles -> 125000.00 Hz
255 pulses in 32640 timer cycles -> 125000.00 Hz
256 pulses in 32768 timer cycles -> 125000.00 Hz
256 pulses in 32768 timer cycles -> 125000.00 Hz

Thank you @Edgar Bonet very much for the sample program and the suggestion.  Will switch over to the AVR (currently using nRF52) and test it with your method.  I am having a go at Dorian's recommendation on cleaning up the input signal to the OP AMP first that is better adopted to the current doppler sensor vs the single-shot inductive sensor I used it with previously.

I tested the code and worked as you posted it @Edgar Bonet (except overflowing over 65535 in my case) but could not get the readings to correlate. I spent a considerable time massaging the OP AMP signal by rearranging the resistors on both inputs, but I am constrained by the previous soldered PCB setup that was for the other sensor type.  I need to setup a new clean OP AMP breadboard from scratch, along with a comparator example as also suggested by Dorian.  Will report back.

@TommyS: The overflow of the timer is not an issue, as long as the burst fits in 16 bits, i.e. is shorter than 4.096 ms. For longer bursts, you can set the timer prescaler to 8, which will increase the max burst duration to 32.768 ms, at the cost of degraded resolution. Alternatively, you can count the overflows in TIMER1_OVF_vect, but then it is tricky to avoid a race condition when the overflow fires very close to the capture.

Updated status and identified most likely problem and work-around solution,  Will open new Question on best path forward in squaring a sine wave.