body:
for your case(**audio**) there also is https://github.com/connornishijima/arduino-volume1
or the volume library
to install it you can use the git to get the files, or if you use the arduino ide, you can open the arduino ide and in the software go to helptools(4thoptionoftopmenubar)->Manage Libraries-> {type volume in the search bar}-> install the library called volume. you can also chose volume 2 or volume 3, see the git for the differences.

this however still uses micro pwm, so it is not true analog, but for audio it works. also note that on low volume the audio will be affected. I recommend only using the volumes between 100 and 255.

this method requires no additional hardware, and works well for audio, to send the audio to other devices however I would just send the audio values and not the audio output.

NOT TRUE ANALOG, but it solves your problem, the methods I described in my other answer will work well for most other analog cases, or even adding a small capacitor at that ma output might work in many cases. however since audio needs the voltage to change really fast this method works well, also since the volume is read by your mind instead of a digital device it has a normalization filter built in and a low sampling speed as well as sensitivity to only low frequency(how human brains and ears work) which will make the volume sound natural.

If you have a separate arduino for the volume or a well optimized code you can also avoid interrupts to get a higher frequency, this method is harder and requires you to know what your code does but allows for better quality volume(speciffically at low volume levels)

**alternatively you can use a shiftregister** and connect resisters to the outputs, for example 12800, 6400,3200,1600,800,400,200,100. like a bit but reversed, since the audio gets louder with a lower resistance. you can use other values, just don't make them to low, since arduino outputs 5v and 3.3v, both are much higher than your average headphone connection, also turning on multiple parallel resistors at once gives a lower resistance. for example if we turn on the 100 ohm and the 200 ohm resistor we get a output of around 66,66666666 ohm since the output is 1/((1/Resistor1)+(1/Resistor2)+(1/ResistorETC)
like this a singe 8 bit shift register can deliver 256 different volume levels as true analog. if you have ports free on your ardruino you can also use those instead of a shift register, however be sure to use bitmanipulations and not digitalwrite, since the later one is slow.
1 pin = 2 volume levels
2 pin = 4 volume levels
3 pin = 8 volume levels
4 pin = 16 volume levels
5 pin = 32 volume levels
6 pin = 64 volume levels
7 pin = 128 volume levels
8 pin = 256 volume levels
etc.
this method can give true analog voltage if you know the resistance at the output, a speaker however differs in resistance based on many factors, but doing this will still give you good volume control like actual analog voltage, even though it is actually more analog amperage. to get voltage content the terminal connected to all the outputs of the resistors to another resistor to generate a voltage divider, this works for things like vga displays, however for things like audio, lights, etc. you should jus directly take the output of the resistors


sender: user

message:
Why does a pull down resistor configuration not destroy the pin it's connected to?

I don't understand why a pull-down resistor connected to ground would prevent a pin connected to 5V through a button would not destroy the pin as the current does not need to go through the resistor to get to the pin. I've tried looking online but the question was never asked and I couldn't find any information that explained how it works.

I'm asking this in the context of something without internal resistors so it would have no protection against a short circuit/being connected straight to a source.

sender: assistant

body:
When you have a pin in INPUT mode it is *high impedance*. That means that to all intents and purposes, to the outside world, the pin is not connected to anything internally.

In reality it is, but that internal connection is of such a *high impedance* (i.e., resistance) that it is almost equivalent to an open circuit.

It's simplest to think of an input pin as a voltmeter.  A pulldown resistor and button would look like this:

<!-- Begin schematic: In order to preserve an editable schematic, please
     don't edit this section directly.
     Click the "edit" link below the image in the preview instead. -->

![schematic](https://i.stack.imgur.com/UEVbT.png)

<!-- End schematic -->

When the button is opened the voltmeter reads zero, because one end is connected to ground, and the other end is connected to ground through the resistor.

However when you press the button the voltmeter reads the voltage across the resistor - that is, 5V - because one end is connected to ground and the other to 5V, with a resistor across it.

If you don't have the resistor then the voltmeter can't measure anything when the button isn't pressed - it's just waving around in the air without a clue what it's doing - and a wire waving around in the air is called an antenna...

The Arduino is that voltmeter. All it does is detect the voltage at the pin, it doesn't conduct any (or only a very very tiny amount of leakage) current through the pin.

Now the possibility of a short circuit comes when you set the pin to OUTPUT. If you drive the pin LOW then the pin is essentially connected to GND, and pressing the button will connect the 5V straight to GND through the LOW-driven IO pin.


body: A pullup or pulldown *wire* would destroy the pin because it would source or sink enough current to burn out the pin driver.  But a pullup or pulldown *resistor* limits the current to a very small value (I = E/R = 5v/10000Ohm = .0005A or .5 ma, well within the pin driver's 20 ma limit.


message:
Don't understand problem with my code

I'm trying to get a robot car(elegoo one) to do the obstacle avoidance course. I am trying to write my own one from scratch to better myself and thus would really appreciate it if someone were to tell me what's wrong with my code and why it's not working

```c++
#include <Servo.h>  //servo library
Servo myservo;      // create servo object to control servo
Servo servosweep;
int Echo = A4;
int Trig = A5;

#define ENA 5
#define ENB 6
#define IN1 7
#define IN2 8
#define IN3 9
#define IN4 11
#define carSpeedForward 100
#define carSpeedLeftandRight 150
int rightDistance = 0, leftDistance = 0, middleDistance = 0;
int pos=0;

void forward(){
  analogWrite(ENA, carSpeedForward);
  analogWrite(ENB, carSpeedForward);
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, HIGH);
  Serial.println("Forward");
}

void back() {
  analogWrite(ENA, carSpeedForward);
  analogWrite(ENB, carSpeedForward);
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, HIGH);
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);
  Serial.println("Back");
}

void left() {
  analogWrite(ENA, carSpeedLeftandRight);
  analogWrite(ENB, carSpeedLeftandRight);
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, HIGH);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, HIGH);
  Serial.println("Left");
}

void right() {
  analogWrite(ENA, carSpeedLeftandRight);
  analogWrite(ENB, carSpeedLeftandRight);
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);
  Serial.println("Right");
}

void stop() {
  digitalWrite(ENA, LOW);
  digitalWrite(ENB, LOW);
  Serial.println("Stop!");
}

//Ultrasonic distance measurement Sub function
int Distance_test() {
  digitalWrite(Trig, LOW);
  delayMicroseconds(2);
  digitalWrite(Trig, HIGH);
  delayMicroseconds(20);
  digitalWrite(Trig, LOW);
  float Fdistance = pulseIn(Echo, HIGH);
  Fdistance= Fdistance / 58;
  return (int)Fdistance;
}

void setup() {
  myservo.write(pos);
  myservo.attach(3);  // attach servo on pin 3 to servo object
  Serial.begin(9600);
  pinMode(Echo, INPUT);
  pinMode(Trig, OUTPUT);
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(IN3, OUTPUT);
  pinMode(IN4, OUTPUT);
  pinMode(ENA, OUTPUT);
  pinMode(ENB, OUTPUT);
  //stop();
}

void loop(){
  for (pos = 0; pos < 90; pos += 1.0) {
  servosweep.write(pos);
  delay(50);
  leftDistance=Distance_test();
  }

  myservo.write(90);
  middleDistance=Distance_test();

  for (pos=90;pos<=180;pos+=1.0){
    servosweep.write(pos);
    delay(50);
    rightDistance=Distance_test();

  }

  if(rightDistance > leftDistance) {
        right();
        delay(360);
      }
      else if(rightDistance < leftDistance) {
        left();
        delay(360);
      }
      else if((rightDistance <= 40) || (leftDistance <= 40)) {
        back();
        delay(180);
      }
      else {
        forward();
      }
}
```

I'm trying to get the ultrasonic sensor to read values from the left(0 to 90), the middle(90) and the right(90 to 180) and then use them for comparison to decide where to go. When I run this code my car goes in circles and I don't know what the problem is. Any help would be appreciated.

body:
As jsotola writes, you are running through the 0-89 position and updating leftDistance every time. Then you find the middleDistance and finally you go through 91-180 and update rightDistance. After the two for loops, leftDistance will have the value for 89 and rightDistance will have the value for 180 because you overwrite your value without doing anything with it.

Start by skipping the for loops and measure at 0, 90 and 180 and use these values as you left, middle and right distance. When deciding if you want to back up, use the middle distance. Remember to use a delay between measurements that is large enough for the servo to get to the position for the next measurement


body:
As a couple people already pointed out, you're using for loops that are unnecessary, and will cause you to get the wrong measurements. You're better off just using `myservo.write();` to set your servo to positions 0 and 180.

Additionally you never check to see if there's an obstacle infront of your robot. Instead, your robot immediately tries turn right or left. That's what's causing it to spin.

Here's a fixed version of your `void loop()`

```
void loop(){

  myservo.write(0);
  delay(50);
  leftDistance=Distance_test();

  myservo.write(90);
  delay(50);
  middleDistance=Distance_test();

  myservo.write(180);
  delay(50);
  rightDistance=Distance_test();

  /* Start by checking if there is space to go forward */
  if(middleDistance > 40){
     forward();
     }
/* If there isn't space to go forward, turn */
  else if(rightDistance > leftDistance) {
        right();
        delay(360);
      }
  else if(rightDistance < leftDistance) {
        left();
        delay(360);
      }
  else if((rightDistance <= 40) || (leftDistance <= 40)) {
        back();
        delay(180);
      }
   else {
        forward();
      }
}
```
I hope this helps!


message:
Why am I receiving random input values in my Arduino?

I want to use a switch for my Arduino using digitalRead(), but I keep receiving random inputs. Whenever I connect energy to that pin, it always returns HIGH, but otherwise it goes completely random.

I have tried using a resistor for the input pin, but that didn't seem to help. I am using an [Elegoo UNO][1], and the input pin I am using is pin 2. Here's my code in case you need it:

    const int switchPin = 3;

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

    void loop() {
      // put your main code here, to run repeatedly:
      if (digitalRead(switchPin) == HIGH){
        Serial.println("on");
      }

      else{
        Serial.println("off");
      }
    }

  [1]: https://www.elegoo.com/products/elegoo-uno-project-super-starter-kit

body:
Your code mentions pin 3 while you describe using pin 2. Perhaps that has to do with your error.

Otherwise, check the following things:

 - do you use long cables or is it near strong magnetic or static
   objects.
 - for your code since you only read if it is high, see if the button is connected to 5 V and pin 2 or 3 whichever one you use

You can try adding a resistor between your I/O pin and the ground.

Another test I prefer to do is:

Take a working jumper cable, test it with a voltmeter, or see if you can make an LED light up when connected to it (use the Arduino 5 V, ground and a resistor for this (resistor to not let your LED explode like that zeppelin).

With the working jumper cable or breadboard cable, connect one end to the pin you plan to use. Then run the program and connect the other end to ground, then 5 V, and then ground and so forth to see if it responds well.

This is based on an Arduino Uno. If you use another type of Arduino, make sure to use the proper voltage pin. You can always add a resistor between the wire and the Arduino for extra safety.


body:
You're getting noise pickup on the input pin when the button is not pressed. You need a [pull-down resistor][1], about 10 kΩ to ground, to quiet the noise when the switch is open.
<br>Or even easier, use the built-in pull-up resistor in the Arduino, which is ~10 kΩ to +5 V, wire your button to ground instead of +5 V, and reverse the `if` tests to test for logic LOW instead of HIGH, to detect a button press. You'd change your pinmode statement to:

    pinMode(switchPin, INPUT_PULLUP);  // engage the input pullup

and your test to:

     if (digitalRead(switchPin) == LOW ){ // Negative logic

No additional (external) hardware is needed!

  [1]: https://en.wikipedia.org/wiki/Pull-up_resistor


body:
Here is what you can do

1. Check if the switch is connected to the defined input pin. The Arduino starts form pin 0 and sometimes we can misread while connecting.

2. Check if the serial monitor has same baud rate as defined in the program.

3. Check the voltages around switch using a multimeter.

4. Still not getting a solution? Attach a pull-down resistor.

5. Still not getting a solution? Invert the logic and current flow as [suggested by JRobert][1].

  [1]: https://arduino.stackexchange.com/questions/81796/why-am-i-receiving-random-input-values-in-my-arduino/81799#81799


body:
Few things that can be checked and used.

 1. If you are using a normal push button then check the connections properly as two of the pins are internally connected two each other. So we need 2 pins that are not connected so check it with DMM.[![enter image description here][1]][1]
 2. You need a Pull-UP or pull-Down resisters attached to the input pin.

    The value of a resistor depends on your requirement like if you have long wires or more noise you need a strong pullup or pulldown resister like 1k. And the best way is to test it out first with an internal pull-up resistor which is considered a week pullup and Atmega328p has its value of around 20k.
    ```pinMode(switchPin, INPUT_PULLUP);```

 3. As TeD has stayed check that you are using the same digital pin in your hardware and code.

 4. And last a simple counter type debouncing logic will help to denounce the button input signals. as shown in the below code.
```
#define switchPin 2
byte debounce_counter = 150;

void setup() {
  pinMode(switchPin, INPUT_PULLUP);
  Serial.begin(9600);
}

void loop() {
  if (digitalRead(switchPin) == HIGH) {
    debounce_counter++;
  }
  else {
    debounce_counter--;
  }

  if (debounce_counter >= 240)
  {
    debounce_counter = 150;
    Serial.println("OFF");
  }
  else if (debounce_counter <= 60)
  {
    debounce_counter = 150;
    Serial.println("ON");
  }
}
```

You can also check other methods and libraries for debouncing the input signals which uses the millis function.

  [1]: https://i.stack.imgur.com/KmjAo.gif


message:
Detect if a display is connected

I want to detect wether a display is connected or not.
This is the display: https://www.az-delivery.de/en/products/1-77-zoll-spi-tft-display

I read connecting a pin of the display with another pin with a pull up resistors. Unfortunetely nothing worked so far.

My microcontroller board is Arduino Mega.

body:
There is nothing immediately apparent on that display that can tell you if it's connected or not. If you had a full SPI interface (you are missing the MISO pin) you could query the display for the HWID, but alas not. And there's no pins at all that are outputs.

The only suggestion I can come up with is to connect a small (say 1Ω) resistor between the Arduino's 5V pin and the display's VCC / LEDA pins and use an analogue input to measure the voltage on the display side of it. When the display is disconnected it will give a 5V reading. When it's connected the reading will drop to a slightly lower voltage (depending on the current draw).

Schematic:

<!-- Begin schematic: In order to preserve an editable schematic, please
     don't edit this section directly.
     Click the "edit" link below the image in the preview instead. -->

![schematic](https://i.stack.imgur.com/9ouia.png)

<!-- End schematic -->


body: As jsotola mentioned in his comment, pin 1 and pin 14 on the display are connected to each other (GND). You can connect pin 14 to an input pin with enabled INPUT_PULLUP. If no display is connected, this pin will be pulled high by the pullup, thus the pin will read high. If the display is connected, the pin will read low.


message:
NodeMCU and SDS011

today I connected the SDS011 to NodeMCU. I noticed that this only works when the sensor is connected to the voltage VU. If I connect the sensor to another pin for the voltage, it does not respond.
Why is this so?

If I see it correctly, the reason must be that data is exchanged via RX and TX.

```
#include "SdsDustSensor.h"

int rxPin = 5; //d1
int txPin = 4; //d2
SdsDustSensor sds(rxPin, txPin);

void setup(){
  Serial.begin(9600);
  sds.begin();
  sds.setCustomWorkingPeriod(0);

}

void loop(){
PmResult pm = sds.readPm();
  if (pm.isOk()) {
     Serial.println(pm.pm25);
     Serial.println(pm.pm10);
  }

  delay(250);

}

```

body: The SDS011 needs 5 V powering and the VU pin is the 5 V from USB on the NodeMCU development board.


message:
Rotating Servo Motor using Arduino

Using arduino, I'm trying to rotate a 360 servo that will move clockwise 5 seconds,pause and counterclockwise for 5 seconds and then completely stop. However, my servo just continuously keeps on rotating in one direction. Any suggestions will be helpful

body:
you have not put your code here so i can not understand it properly.From what i understand you must have put your code for rotating the servo motor 5 times in void loop. Don't do that put loop for rotating servo 5 time in setup.

void loop run continuously so it must be rotating 5 time then again 5 time and so on.


message:
Is there a Arduino UI library that provides dialog box and button functionality at a minimum?

I have been looking at the Arduino TFT Library and it supports all the bits and pieces for making a simple display, but I am looking for something a little higher level that has primitive dialog box and button capability, and presumably, the ability to layer the display so I can push and pop display elements.  Is there a higher level GUI library for Arduino TFT displays?

body:
Take a look at this library. Will this do all that you want?

https://github.com/AndreiDegtiarev/AWind

I have not tried it yet but I would like to.

Edit:

I just remembered this https://github.com/ImpulseAdventure/GUIslice
https://github.com/ImpulseAdventure/GUIslice/wiki

A lightweight GUI framework for embedded displays

The library supports creation of multiple pages of buttons, text, images, checkboxes, sliders and other graphics primitives. New UI / widget types can be created easily.

It works with many existing TFT libraries. There also is a drag & drop builder application.  https://github.com/ImpulseAdventure/GUIslice-Builder


message:
What is the highest baud rate that can work between Android device and an Arduino connected to an HC05?

I see a lot of baud rates in the AT Command documentation for the HC05 however I am not sure what is the fastest that can work between the Arduino controlled embedded system and the Android phone. I also do not know of a way to change the baud rate of the Bluetooth communication in software. I am writing the application in Java with Android Studio IDE.

I read the documentation for HC05 and realize that it only operates with one Bluetooth profile. i.e the Serial Port Profile. The documentation says that this profile offers a maximum data-rate of 128000 bits/sec. However, the HC05 has a max baud rate option of 1382400 bits/sec. Why would this option be there if it is not possible to use? Can you please explain what I am missing and point me into the direction of some useful information? Thank you.

body:
The HC-05 may only have implemented baud rates up to 1382400, even though the protocol is spec'd for up to 128000.

If you're using Software Serial to talk to the HC-05 from an Uno, 9600 baud is about as fast as SoftwareSerial can keep up with incoming bytes (I've heard from some people that 19200 will work).

If you're using one of the UARTs on a Mega, you may be able to use the full rate implemented by the HC-05. An experiment would be in order...

Update:

> I did an experiment and found out that the maximum baud rate
> achievable between the HC05 (communicated with by SoftwareSerial on
> Arduino Nano) and the Android device is 115200.

I would guess you were transmitting from the Arduino? I've been able to transmit that fast with SoftwareSerial but its receiving ability is more limited. (This has enabled me to, f/ex, set an HC-05 or an ESP8266 to a slower baud-rate than it shipped with, by blindly transmitting an appropriate 'AT' command at the higher speed, then testing it at my intended speed to see if the command worked).


message:
How does one wire OV7670 camera with Arduino Due?

The parts that I want to interface together are:

 - Arduino Due
 - OV7670 Camera Module
 - 3.5" TFT Touchscreen LCD (uses MCUFRIEND_kbv library)

My goal is to get the video feed from the camera to the LCD screen. Any help will be appreciated.

body:
I am working with small project same in little bit like what you trying to do..

  starting with..
1- Arduino UNO + OV7670 + 2.4" TFT LCD (I got not clear live Image)..

so I made some changes..
2- Arduino DUE + OV7670 Live Image (still working with, having problem in reading Image) want to compile the result Image (convert it to text) then sending the result to (3) by serial Port
3- Arduino UNO + 3.5" TFT LCD (it works)..

  by the way  Arduino UNO + OV7670 Live Image (worked perfectly), but I am trying to get same project using DUE.. (faster speed & maybe could deal with Image too..)

here link of how OV7670 work with Arduino DUE..
https://www.instructables.com/How-to-Connect-OV7670-to-Arduino-Due/
.....


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

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


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

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


message:
digitalRead() function of Arduino doesn't read Input value sent by sensor after detecting the object

[![Schematic diagram][1]][1]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.

```c++
//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);
}
```

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

body:
`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.


message:
Pullup on compatible Arduino Mega

I've got an Arduino mega compatible board, called Ethermega, from Freetronics (ATmega2560).

Schematic [here][1].

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

  [1]: https://raw.githubusercontent.com/freetronics/EtherMegaR3/master/EtherMegaR3-schematic.pdf

body:
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*.


message:
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 !

body:
> 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][1] 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][2].  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][3] 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][4]. 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][5]:

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.

  [1]: https://github.com/NicoHood/HoodLoader2
  [2]: https://github.com/NicoHood/HoodLoader2/wiki/Hardware-Installation
  [3]: https://github.com/NicoHood/HoodLoader2/wiki/Installation-sketch-(standalone-Arduino-Uno-Mega)
  [4]: https://github.com/NicoHood/HoodLoader2/wiki/Troubleshoot-FAQ#flipped-isp-header
  [5]: https://github.com/NicoHood/HoodLoader2/blob/master/avr/variants/HoodLoader2/pins_arduino.h#L129


message:
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)

body:
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;
 }
}
```


message:
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 audio amplifier circuit][1]][1]

  [1]: https://i.stack.imgur.com/Q9jRz.png

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.

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

<!-- Begin schematic: In order to preserve an editable schematic, please
     don't edit this section directly.
     Click the "edit" link below the image in the preview instead. -->

![schematic](https://i.stack.imgur.com/rcdMK.png)

<!-- End schematic -->

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][1]

  [1]: https://arduinoforadvanceddevelopers.wordpress.com/2018/03/17/non-blocking-adc-converter-class/


message:
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!

body:
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:

<!-- Begin schematic: In order to preserve an editable schematic, please
     don't edit this section directly.
     Click the "edit" link below the image in the preview instead. -->

![schematic](https://i.stack.imgur.com/ZubDI.png)

<!-- End schematic -->

R2 just exists to keep M1 turned off when the Arduino's not actively driving it (i.e., while the bootloader runs, etc).


body:
For what to do see [Majenko's answer][1].

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.

  [1]: https://arduino.stackexchange.com/a/81855/70020


message:
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).

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


body:
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][1] 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.

  [1]: https://en.wikipedia.org/wiki/Placement_syntax


body:
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()`.


body:
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][cppref]. 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`:

```c++
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(){}
```

[cppref]: https://en.cppreference.com/w/cpp/language/union


message:
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):
[![readings from OP AMP via Arduino][1]][1]

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.
[![Op AMP circuit][2]][2]
[!["beautiful" reading via OP AMP][3]][3]

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:
[![enter image description here][4]][4]
[![enter image description here][5]][5]

  [1]: https://i.stack.imgur.com/KjDgV.png
  [2]: https://i.stack.imgur.com/gxCDA.png
  [3]: https://i.stack.imgur.com/Wss8Z.jpg
  [4]: https://i.stack.imgur.com/imRJN.jpg
  [5]: https://i.stack.imgur.com/B9TvL.jpg

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

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


body:
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:

```c++
// 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:

```text
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
```


message:
I have a problem combining two different sketches into one sketch

Below are two attached the two codes, the second code is for using a microphone to detect for cough and sneezes where the first code is used for humidity and temp.

```c++
// For Scanning Insitu Exhale Parameters via nRFConnect or any BLE Service App
// Carbon-dioxide & Volatile OCs have been pseudo-mapped under Pressure & Rainfall respectively(ppm & ppb);)
#include <ArduinoBLE.h>
#include <Wire.h>
#include <SparkFunBME280.h>
#include <SparkFunCCS811.h>
#define CCS811_ADDR 0x5B
#define PIN_NOT_WAKE 5
CCS811 myCCS811(CCS811_ADDR);
BME280 myBME280;

BLEService sensorService("181A");  // Environmental_Sensor-Service
// 180D HeartRate
// 181B BodyComposi.
BLEShortCharacteristic sensorLevelChar1("2A6E", BLERead | BLENotify);   // Temperature-Characteristic
BLEShortCharacteristic sensorLevelChar2("2A6F", BLERead | BLENotify);   // Humidity-Characteristic
BLELongCharacteristic sensorLevelChar3("2A6D", BLERead | BLENotify);    // PCo2-Characteristic
BLELongCharacteristic sensorLevelChar4("2A78", BLERead | BLENotify);    // PTVoC-Characteristic
// 2A37 HRmeasurement
// 2A2C Magdeclination
// 2A98 weight
// 2A6D Pressure
// 2A9D Recom.HRMax.
// 2A8E Height
// 2A8D Max.HR
// 2A8C Gender
// 2A00 DeviceName
// 2A38 bodysensorlocation
int oldSensorLevel1 = 0;
int oldSensorLevel2 = 0;
int oldSensorLevel3 = 0;
int oldSensorLevel4 = 0;
long previousMillis = 0;

void setup() {
  Serial.begin(9600);
  while (!Serial);
  pinMode(23, OUTPUT);

  if (!BLE.begin()) {
    Serial.println("Bluetooth init. failed!");
    while (1);
  }
  Wire.begin();
  CCS811Core::status returnCode = myCCS811.begin();
  Serial.print("CCS811 begin exited with: ");
  printDriverError( returnCode );
  Serial.println();
  myBME280.settings.commInterface = I2C_MODE;
  myBME280.settings.I2CAddress = 0x77;
  myBME280.settings.commInterface = I2C_MODE;
  myBME280.settings.I2CAddress = 0x77;
  myBME280.settings.runMode = 3; //Normal mode
  myBME280.settings.tStandby = 0;
  myBME280.settings.filter = 4;
  myBME280.settings.tempOverSample = 5;
  myBME280.settings.pressOverSample = 5;
  myBME280.settings.humidOverSample = 5;
  delay(10);
  myBME280.begin();

  BLE.setLocalName("Mask.xME");
  BLE.setAdvertisedService(sensorService);
  sensorService.addCharacteristic(sensorLevelChar1);
  BLE.addService(sensorService);
  sensorLevelChar1.writeValue(oldSensorLevel1);

  sensorService.addCharacteristic(sensorLevelChar2);
  BLE.addService(sensorService);
  sensorLevelChar2.writeValue(oldSensorLevel2);

  sensorService.addCharacteristic(sensorLevelChar3);
  BLE.addService(sensorService);
  sensorLevelChar3.writeValue(oldSensorLevel3);

  sensorService.addCharacteristic(sensorLevelChar4);
  BLE.addService(sensorService);
  sensorLevelChar4.writeValue(oldSensorLevel4);

  // start advertising
  BLE.advertise();
  Serial.println("Bluetooth active, waiting to be connected.....");
}

void loop() {
  // waiting for a BLE central device.
  BLEDevice central = BLE.central();
  if (central) {
    Serial.print("Connected to central: ");
    Serial.println(central.address());
    digitalWrite(23, HIGH);  // indicate connection
    while (central.connected()) {
  if (myCCS811.dataAvailable())
  {
    myCCS811.readAlgorithmResults();
    printInfoSerial();
    float BMEtempC = myBME280.readTempC();
    float BMEhumid = myBME280.readFloatHumidity();
    myCCS811.setEnvironmentalData(BMEhumid, BMEtempC);
  }
  else if (myCCS811.checkForStatusError())
  {
    printSensorError();
  }
      long currentMillis = millis();
      if (currentMillis - previousMillis >= 200) {
        previousMillis = currentMillis;
        updateSensorLevel1();
        updateSensorLevel2();
        updateSensorLevel3();
        updateSensorLevel4();
      }
    }
    digitalWrite(23, LOW);
    Serial.print("Disconnected from central: ");
    Serial.println(central.address());
  }
}

void updateSensorLevel1() {
  float temperature = myBME280.readTempC();
  Serial.print("Temperature = ");
  Serial.print(temperature, 0);
  //float T = myBME280.readTempC();
  Serial.println(" °C");
  float sensorLevel1 = map(temperature, 0, 100, 0, 10000);
  sensorLevelChar1.writeValue(sensorLevel1);
  oldSensorLevel1 = sensorLevel1;
}

void updateSensorLevel2() {
  float humidity = myBME280.readFloatHumidity();
  Serial.print("Humidity = ");
  Serial.print(humidity, 0);
  Serial.println(" %");
  float sensorLevel2 = map(humidity, 0, 100, 0, 10000);
  sensorLevelChar2.writeValue(sensorLevel2);
  oldSensorLevel2 = sensorLevel2;
}

void updateSensorLevel3() {
  float CO2 = myCCS811.getCO2();
  Serial.print("Co2 = ");
  Serial.print(CO2);
  Serial.println(" ppm");
  float sensorLevel3 = map(CO2, 0, 100, 0, 1000);
  sensorLevelChar3.writeValue(sensorLevel3);
  oldSensorLevel3 = sensorLevel3;
}

void updateSensorLevel4() {
  float VoC = myCCS811.getTVOC();
  Serial.print("TVoC = ");
  Serial.print(VoC);
  Serial.println(" ppb");
  float sensorLevel4 = map(VoC, 0, 100, 0, 100);
  sensorLevelChar4.writeValue(sensorLevel4);
  oldSensorLevel4 = sensorLevel4;
}

void printInfoSerial()
{
  Serial.println("CCS811 data:");
  Serial.print(" CO2 concentration : ");
  Serial.print(myCCS811.getCO2());
  Serial.println(" ppm");
  Serial.print(" TVOC concentration : ");
  Serial.print(myCCS811.getTVOC());
  Serial.println(" ppb");

  Serial.println("BME280 data:");
  Serial.print(" Temperature: ");
  Serial.print(myBME280.readTempC(), 2);
  Serial.println(" degrees C");
  Serial.print(" %RH: ");
  Serial.print(myBME280.readFloatHumidity(), 2);
  Serial.println(" %");
  Serial.println();
}

void printDriverError( CCS811Core::status errorCode )
{
  switch ( errorCode )
  {
    case CCS811Core::SENSOR_SUCCESS:
      Serial.print("SUCCESS");
      break;
    case CCS811Core::SENSOR_ID_ERROR:
      Serial.print("ID_ERROR");
      break;
    case CCS811Core::SENSOR_I2C_ERROR:
      Serial.print("I2C_ERROR");
      break;
    case CCS811Core::SENSOR_INTERNAL_ERROR:
      Serial.print("INTERNAL_ERROR");
      break;
    case CCS811Core::SENSOR_GENERIC_ERROR:
      Serial.print("GENERIC_ERROR");
      break;
    default:
      Serial.print("Unspecified error.");
  }
}
void printSensorError()
{
  uint8_t error = myCCS811.getErrorRegister();
  if ( error == 0xFF ) //comm error
  {
    Serial.println("Failed to get ERROR_ID register.");
  }
  else
  {
    Serial.print("Error: ");
    if (error & 1 << 5) Serial.print("HeaterSupply");
    if (error & 1 << 4) Serial.print("HeaterFault");
    if (error & 1 << 3) Serial.print("MaxResistance");
    if (error & 1 << 2) Serial.print("MeasModeInvalid");
    if (error & 1 << 1) Serial.print("ReadRegInvalid");
    if (error & 1 << 0) Serial.print("MsgInvalid");
    Serial.println();
  }
}
```

Code 2

```c++
// Cough & Sneeze Classifier built through Edge Impulse Studio.
// If your target is limited in memory remove this macro to save 10K RAM
#define EIDSP_QUANTIZE_FILTERBANK   0
#include <PDM.h>
#include <cscan2_inference.h>

typedef struct {
    int16_t *buffer;
    uint8_t buf_ready;
    uint32_t buf_count;
    uint32_t n_samples;
} inference_t;

static inference_t inference;
static bool record_ready = false;
static signed short sampleBuffer[2048];
static bool debug_nn = false; // Set this to true to see e.g. features generated from the raw signal

/**
 * @brief      Arduino setup function
 */
void setup()
{
    // put your setup code here, to run once:
    Serial.begin(115200);
    Serial.println("SpecVital Inference...");
    // summary of inferencing settings (from model_metadata.h)
    ei_printf("Inferencing settings:\n");
    ei_printf("\tInterval: %.2f ms.\n", (float)EI_CLASSIFIER_INTERVAL_MS);
    ei_printf("\tFrame size: %d\n", EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE);
    ei_printf("\tSample length: %d ms.\n", EI_CLASSIFIER_RAW_SAMPLE_COUNT / 16);
    ei_printf("\tNo. of classes: %d\n", sizeof(ei_classifier_inferencing_categories) / sizeof(ei_classifier_inferencing_categories[0]));
    if (microphone_inference_start(EI_CLASSIFIER_RAW_SAMPLE_COUNT) == false) {
        ei_printf("ERR: Failed to setup audio sampling\r\n");
        return;
    }
}

/**
 * @brief      Arduino main function. Runs the inferencing loop.
 */
void loop()
{
    ei_printf("Starting inferencing in 2 seconds...\n");
    delay(5000);
    ei_printf("Recording...\n");
    bool m = microphone_inference_record();
    if (!m) {
        ei_printf("ERR: Failed to record audio...\n");
        return;
    }
    ei_printf("Recording done\n");

    signal_t signal;
    signal.total_length = EI_CLASSIFIER_RAW_SAMPLE_COUNT;
    signal.get_data = &microphone_audio_signal_get_data;
    ei_impulse_result_t result = { 0 };

    EI_IMPULSE_ERROR r = run_classifier(&signal, &result, debug_nn);
    if (r != EI_IMPULSE_OK) {
        ei_printf("ERR: Failed to run classifier (%d)\n", r);
        return;
    }

    // print the predictions
    ei_printf("Predictions (DSP: %d ms., Classification: %d ms., Anomaly: %d ms.): \n",
        result.timing.dsp, result.timing.classification, result.timing.anomaly);
    for (size_t ix = 0; ix < EI_CLASSIFIER_LABEL_COUNT; ix++) {
        ei_printf("    %s: %.5f\n", result.classification[ix].label, result.classification[ix].value);
    }
#if EI_CLASSIFIER_HAS_ANOMALY == 1
    ei_printf("    anomaly score: %.3f\n", result.anomaly);
#endif
}
/**
 * @brief      Printf function uses vsnprintf and output using Arduino Serial
 *
 * @param[in]  format     Variable argument list
 */
void ei_printf(const char *format, ...) {
    static char print_buf[1024] = { 0 };
    va_list args;
    va_start(args, format);
    int r = vsnprintf(print_buf, sizeof(print_buf), format, args);
    va_end(args);
    if (r > 0) {
        Serial.write(print_buf);
    }
}
/**
 * @brief      PDM buffer full callback
 *             Get data and call audio thread callback
 */
static void pdm_data_ready_inference_callback(void)
{
    int bytesAvailable = PDM.available();
    // read into the sample buffer
    int bytesRead = PDM.read((char *)&sampleBuffer[0], bytesAvailable);
    if (record_ready == true || inference.buf_ready == 1) {
        for(int i = 0; i < bytesRead>>1; i++) {
            inference.buffer[inference.buf_count++] = sampleBuffer[i];
            if(inference.buf_count >= inference.n_samples) {
                inference.buf_count = 0;
                inference.buf_ready = 1;
            }
        }
    }
}
/**
 * @brief      Init inferencing struct and setup/start PDM
 *
 * @param[in]  n_samples  The n samples
 *
 * @return     { description_of_the_return_value }
 */
static bool microphone_inference_start(uint32_t n_samples)
{
    inference.buffer = (int16_t *)malloc(n_samples * sizeof(int16_t));
    if(inference.buffer == NULL) {
        return false;
    }
    inference.buf_count  = 0;
    inference.n_samples  = n_samples;
    inference.buf_ready  = 0;
    // configure the data receive callback
    PDM.onReceive(&pdm_data_ready_inference_callback);
    // optionally set the gain, defaults to 20
    PDM.setGain(80);
    //ei_printf("Sector size: %d nblocks: %d\r\n", ei_nano_fs_get_block_size(), n_sample_blocks);
    PDM.setBufferSize(4096);
    // initialize PDM with:
    // - one channel (mono mode)
    // - a 16 kHz sample rate
    if (!PDM.begin(1, EI_CLASSIFIER_FREQUENCY)) {
        ei_printf("Failed to start PDM!");
    }
    record_ready = true;
    return true;
}
/**
 * @brief      Wait on new data
 *
 * @return     True when finished
 */
static bool microphone_inference_record(void)
{
    inference.buf_ready = 0;
    inference.buf_count = 0;
    while(inference.buf_ready == 0) {
        delay(10);
    }
    return true;
}
/**
 * Get raw audio signal data
 */
static int microphone_audio_signal_get_data(size_t offset, size_t length, float *out_ptr)
{
    arm_q15_to_float(&inference.buffer[offset], out_ptr, length);
    return 0;
}

/**
 * @brief      Stop PDM and release buffers
 */
static void microphone_inference_end(void)
{
    PDM.end();
    free(inference.buffer);
}

#if !defined(EI_CLASSIFIER_SENSOR) || EI_CLASSIFIER_SENSOR != EI_CLASSIFIER_SENSOR_MICROPHONE
#error "Invalid model for current sensor."
#endif
```

body:
You have 2 different problems you need to solve before you can merge these sketches.

The first sketch has a loop within a loop. in psuedocode it is:

    void loop(){
       Connection con = connect();
       while(con.connected()){
           doStuff();
       }
       notify_disconnected();
    }

This is a problem because the loop never exits in normal operation.

you can rewrite this into

    Connection con;
    void loop(){
        if(con.connected()){
            was_connected = true;
            doStuff();
        } else{
            if(was_connected){
                notify_disconnected();
                was_connected = false;
            }
            con = connect();
        }
    }

The other sketch has the classic delay problem which the first sketch gives an example of handling.

    void loop(){
        delay(5000);
        doStuff();
    }

this can be changed into

    void loop(){
        long currentMillis = millis();
        if (currentMillis - previousMillis >= 5000) {
            previousMillis = currentMillis;
            doStuff();
        }
    }

After you do these fixes and make sure the names of the globals and functions don't collide and no unneeded wires cross you can put both in the same sketch:

    void setup(){
        setup_sketch1();
        setup_sketch2();
    }

    void loop(){
        loop_sketch1();
        loop_sketch2();
    }


message:
How to bring WiFi back up if woken from deepSleep(WAKE_RF_DISABLED)

I'm trying to build a sensor that should update an MQTT broker only if something changes. So every few seconds it's supposed to wake up just enough to check a few inputs, compare them with the last time it woke up, and only if there has been a change should it connect to the broker and write the updates. I don't expect many updates per day, but if I sleep more than 10 seconds, I might miss them.

I'm using `WiFi.forceSleepBegin()` and `WiFi.forceSleepWake()`, mainly based on [these articles](https://www.bakke.online/index.php/2017/05/21/reducing-wifi-power-consumption-on-esp8266-part-1/). But there is this tempting option of `ESP.deepSleep(n, WAKE_RF_DISABLED)`

The [API](https://arduino-esp8266.readthedocs.io/en/latest/libraries.html#esp-specific-apis) that I found only mentions this:

> If you implement deep sleep with WAKE_RF_DISABLED and require WiFi functionality on wake up, you will need to implement an additional WAKE_RF_DEFAULT before WiFi functionality is available.

Do I read this correct if I understand that I would need to make another `deepSleep` just to wake up again with WiFi back active? Or is there an easier way to boot up the WiFi after such a sleep?

Thank you

body:
    WiFi.forceSleepBegin();
    delay(1);
    WiFi.forceSleepWake();
    delay(1);

Source: [GitHub][1]

That also works, I tested it December 2020.  Thanks to Erik Bakke for finding it.  It's a bit more clean than another Deep Sleep boot with the modem enabled.  Igrr and I both struggled to find a way to wake the modem, and Erik mixed the magic sauce.  Hopefully it still works today with the changes to the core WiFi files.

  [1]: https://github.com/esp8266/Arduino/issues/3072#issuecomment-741524721


body:
Yes, you understood correctly; after using `ESP.deepSleep(n, WAKE_RF_DISABLED)` to disable WiFi, the most reliable method to re-enable it is to call `ESP.deepSleep(1, WAKE_RF_DEFAULT)`. Then connect to WiFi on the next wake (which should be in 1 second). [Apparently][1], `WAKE_RFCAL` and `WAKE_NO_RFCAL` also result in WiFi working.

A cheap way to approach this, is to normally sleep with `WAKE_RF_DISABLED` but when your WiFi connection fails, sleep with `WAKE_RF_DEFAULT` to make the next connection more likely to be successful.

If you want a more elegant, but slightly more complex solution, you can use the [RTC memory][2] to store the known WiFi state when you sleep; so when you sleep with `WAKE_RF_DISABLED`, you'll know that you'll have to reset with `WAKE_RF_DEFAULT` before trying to connect. And, when you wake again, you'll know the WiFi has been enabled.

As mentioned in [another answer][3], after using `WAKE_RF_DISABLED`, you could call `WiFi.forceSleepBegin()` and then immediately call `WiFi.forceSleepWake()` to try to bring the WiFi back up without resetting. While I have actually found this to work, sadly it seems to be unreliable. Seems like it might work while on USB power, but when changing to another power source, it stops working. I'm not sure why. When using that approach, sometimes the MCU will consume only 40 mA when it's supposed to consume 70 mA with WiFi on, so this suggests to me that the WiFi doesn't properly initialize.

All that being said, I would suggest that using `WAKE_RF_DISABLED` is quite extreme. Like in your original solution, I have found that you can avoid using `WAKE_RF_DISABLED` altogether if you call `WiFi.forceSleepBegin()` immediately when the device starts (i.e. at the top of your `setup()` function), and then `WiFi.forceSleepWake()` when you want to use WiFi. When the device starts, there is only perhaps 50-100ms when the device is using 70mA before WiFi is turned off. This is probably acceptable for most low power designs.

  [1]: https://hutscape.com/tutorials/wakeup-with-no-radio
  [2]: https://hutscape.com/tutorials/rtc-memory
  [3]: https://arduino.stackexchange.com/a/85289/78174


message:
Any advice on how to repeat the song 6 times instead of infinitely?

//Here is my code so far

    int speakerPin = 9;

    int length = 28;

    char notes[] = "GGAGcB GGAGdc GGxecBA yyecdc";

    int beats[] = { 2, 2, 8, 8, 8, 16, 1, 2, 2, 8, 8,8, 16, 1, 2,2,8,8,8,8,16, 1,2,2,8,8,8,16 };

    int tempo = 150;

    void playTone(int tone, int duration) {

    for (long i = 0; i < duration * 1000L; i += tone * 2) {

       digitalWrite(speakerPin, HIGH);

       delayMicroseconds(tone);

       digitalWrite(speakerPin, LOW);

       delayMicroseconds(tone);

    }

    }

    void playNote(char note, int duration) {

    char names[] = {'C', 'D', 'E', 'F', 'G', 'A', 'B',

                     'c', 'd', 'e', 'f', 'g', 'a', 'b',

                     'x', 'y' };

    int tones[] = { 1915, 1700, 1519, 1432, 1275, 1136, 1014,

                     956,  834,  765,  593,  468,  346,  224,

                     655 , 715 };

    int SPEE = 5;

    for (int i = 0; i < 17; i++) {

       if (names[i] == note) {
        int newduration = duration/SPEE;
         playTone(tones[i], newduration);

       }

    }

    }

    void setup() {

    pinMode(speakerPin, OUTPUT);

    }

    void loop() {

    for (int i = 0; i < length; i++) {

       if (notes[i] == ' ') {

         delay(beats[i] * tempo);

       } else {

         playNote(notes[i], beats[i] * tempo);

       }

       delay(tempo);

    }

    }

body:
Assuming, the program can stop after playing 6 times, put another `for` loop in the `loop` function:

    void loop()
    {
       for (int nTimes = 0; nTimes < 6; nTimes++)
       {
          // Existing loop code
       }

       while(true) {};
    }

A less crude way is to create a global variable:

    int _timesPlayed = 0;

And change the `for loop`:

    void loop()
    {
       if (_timesPlayed < 6)
       {
          // Existing loop code

         _timesPlayed++;
       }
    }


message:
How to extract code on one DT-06 board to another board?

I have two DT-06 boards [DT06 datasheet][1].

----------

The board stock firmware provides Web UI for wifi/network/serial setup. I've replaced the firmware on one board with other sketch; but now I want to revert it to the stock firmware. I cannot find the stock firmware source code anywhere. The DT-06 manufacturer also won't give it out.

Is it possible to extract the stock firmware from another DT-06 board and put it back into the other DT-06 board?

Thank you.

  [1]: https://www.mikrocontroller.net/attachment/349564/UserManualForTTL-WiFi.pdf

body:
Okay. I found a way to extract the binary file (stock firmware) from one DT-06 and flash it to another modified DT-06, by using esptool command

    /*To extract firmware */:
    esptool.py -p COM4 -b 460800 read_flash 0 0x400000 dt06_backup.bin
    /*To flash the backup binary file to another DT-06 */
    esptool.py -p com4 write_flash -fm dout 0x00000 dt06_backup.bin