message:
Need Digistump library for QWERTY keyboard and Fixes for my issues!

Hello there I am trying to install `Digistump` library to support ATTiny85 by digispark. But I am encountering a problem when trying to install Digistump AVR boards after adding an additional board URL preference as the library doesn't shows up after searching.I dont know what's the problem even after I tried from the fixes from other solutions across the web.
[![enter image description here][1]][1]

 So, I made an alternative method to work the board by installing `ATTinyCore` library. But it doesn't support `DIGIKEYBOARD` actions. So when I try to download from library manager there is only packages for AZERTY & Belgian AZERTY layout.
[![enter image description here][2]][2] [![enter image description here][3]][3]

So for me I need a package that support QWERTY layout. How to install the library.?

  [1]: https://i.stack.imgur.com/tWlqs.png
  [2]: https://i.stack.imgur.com/2I0jE.png
  [3]: https://i.stack.imgur.com/mwhgR.png

body:
The description of DigiKeyboardFr says it is “based on
[DigisparkKeyboard][] library”, and gives the link to that library.
DigisparkKeyboard doesn't seem to be available from the Arduino library
manager: you will most likely have to install it manually. Manual
installation of Arduino libraries is widely documented.

[DigisparkKeyboard]: https://github.com/digistump/DigisparkArduinoIntegration/tree/master/libraries/DigisparkKeyboard


sender: user

message:
I want the Arduino to be in sleep mode by default and have a button wake it up

I saw a library called LowPower_LowPowerLab that can set the Arduino in sleep mode. In their example they put the Arduino to sleep using an external button, is there anyway to invert this behavior? I want the Arduino to save battery power by being in sleep mode and then when I need it, hold a button down to keep the Arduino awake and then release the button to put it back to sleep. In their example below I have tried changing the attachInterrupt to HIGH/RISING/FALLING with no change. Also coul

LowPowerLab's Example:
``` // **** INCLUDES *****
#include "LowPower.h"

// Use pin 2 as wake up pin
const int wakeUpPin = 2;

void wakeUp()
{
    // Just a handler for the pin interrupt.
}

void setup()
{
    // Configure wake up pin as input.
    // This will consumes few uA of current.
    pinMode(wakeUpPin, INPUT);
}

void loop()
{
    // Allow wake up pin to trigger interrupt on low.
    attachInterrupt(0, wakeUp, LOW);

    // Enter power down state with ADC and BOD module disabled.
    // Wake up when wake up pin is low.
    LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);

    // Disable external pin interrupt on wake up pin.
    detachInterrupt(0);

    // Do something here
    // Example: Read sensor, data logging, data transmission.
}
 ```

sender: assistant

body:
> In their example they put the Arduino to sleep using an external button, is there anyway to invert this behavior?

Of course. Put the Arduino to sleep in `setup` and make the button wake it up.

Some tips [here](http://www.gammon.com.au/power).

Also, I wouldn't use LOW, I would use FALLING. LOW keeps interrupting the processor, so while you hold the button down it keeps entering the interrupt, which would make it unresponsive.


message:
Arduino read thermocouple Type K with ADS1115

I ordered a ADS1115 so I could measure temperature of a type K thermocouple, but I am not managing to get accurate readings. I had it working while having a normal A0 pin, but since the [type K table][1] shows pretty low voltages, the 0-1023 scale is not accurate.

When the thermocouple is at room temperature (around 22°c), it shows 00.0 millivolts on the multimeter (which I dont understand since it does not match with the table), and my program outputs a value of around -40 and a voltage of -0.005. When I heat it up until I measure 10.0 millivolts (around 250°c according table), the Arduino prints a value of 53 and a millivolts of 300.

What am I doing wrong? I suspect something with the calculation, but I am not able to find out how I should do it, I know very little about millivolts.

Can someone help me out what I am doing wrong here and what I should do?

I have the thermocouple and ADS1115 connected as shown in the image below.
[![wiring][2]][2]

The code I am using is as following

```cpp
#include <Adafruit_ADS1X15.h>

const int analogFruitPin = 0;

Adafruit_ADS1115 ads;

void setup()
{
  Serial.begin(9600);
  ads.begin();
  ads.setGain(GAIN_FOUR);
  ads.setDataRate(RATE_ADS1115_860SPS);
}

void loop()
{
  int sensorValue = ads.readADC_SingleEnded(analogFruitPin);
  float voltage = sensorValue * (5.0 / 32768.0);
  Serial.println(voltage,3);
  Serial.println(sensorValue);
  delay(500);
}
```

  [1]: https://www.thermocoupleinfo.com/type-k-thermocouple.htm
  [2]: https://i.stack.imgur.com/gy4yA.jpg

body:
Welcome! Interesting but expected. Thermocouples need what is called a cold junction compensation. That is a circuit or another thermonuclear that compensates for the thermocouple effect where the lead wires are connected to your measuring device. These thermocouple lead wires should be the same metallic material as the wires in the thermocouple. The metals are different where you connect to the measuring device and will generate a voltage as the temperature changes regardless of the sensing probe, that is how the thermocouple works. This link will help: https://www.tegam.com/what-exactly-is-cold-junction-compensation/

For more information check this link: https://randomnerdtutorials.com/arduino-k-type-thermocouple-max6675/


body:
To simplify your thermocouple temperature sensor project, consider using an [ADC][1] which also contains a cold junction temperature sensor.  [This product][2] from Adafuit.com integrates both into one package by using a Microchip.com [MCP9601 integrated circuit][3].

In short, thermocouples generate small amounts of voltage where dissimilar metals touch. This is true where the thermocouple wires are touching each other. And is also true where the thermocuple wires are touching the metal connecting them to the ADC circuit (commonly called the "cold junction"). To find the temperature where the thermocouple wires are touching we need to subtract the effects of the "cold junction". To do that, we need to first know the temperature of the "cold junction". We commonly do this with a second temperature sensor as it is a more practical (and portable) solution than a traditional zero centigrade ice bath (likely where the term "cold junction" came from).

  [1]: https://en.wikipedia.org/wiki/Analog-to-digital_converter
  [2]: https://www.adafruit.com/product/5165
  [3]: https://www.microchip.com/en-us/product/mcp9601


message:
Connect to wifi works only without password (Problem around WPA security)

I have an ESP32 Joy-it - SBC NodeMCU-ESP32 that should be use with board "ESP32 Dev Module". IDE says : Chip is ESP32-D0WDQ6 (revision v1.0).

Website product: https://joy-it.net/en/products/SBC-NodeMCU-ESP32

When I make a wifi scan, I find my AP, but if I connect with SSID + Password (both WPA (Internet box router - Freebox Crystal France) and WPA2 Personal (Xiaomi A2 Lite)), it doesn't work.

So I tried to make an AP without password on my phone, and ESP32 can connect without problem.

To do that, I used the default sketch "Wifi -> Wifi Client". My SSID and my password contain only letters/numbers (Only ASCII chars).

I tried to burn the bootloader, but nothing change.

I am using :

 - IDE Arduino 2.2.1
 - esp32 by espressif 2.0.14

Does somebody have an idea ?

body:
Solution, I'm using an old Freebox, which has only Open or WPA security,

Just add : `WiFi.setMinSecurity(WIFI_AUTH_WPA_PSK);` to allow connection to my router.

For people with *WEP* security, just use `WIFI_AUTH_WEP`


message:
Change USB VID and PID (Leonardo)

I'm new to using electronic boards, and have followed a guide online for printing a 6 DoF (degree of freedom) mouse. I'm stuck on an optional step that requires me to change the PID and VID of a "Arduino Leonardo" board.

I've located the appropriate "boards.txt" file, but I'm not sure which line to change. I've edited a few, but I'm worried I'll mess things up ([a tutorial for it][1] mentions they had destroyed 3 trying to rename it, and is back from 2009), and the ones I've changed do not result in a change.

I have checked out previous questions people have made regarding this topic, but quite frankly I can't understand the technical terms used in those.

[This is the code in question][2] I'm trying to compile, and lists example PID and VIDs as well.

I would love a clear explanation on which PID/VID I need to edit in the "boards.txt", so I can safely modify the board to be read as the space mouse in the code.

  [1]: https://forum.arduino.cc/t/customize-your-arduino/6983
  [2]: https://pastebin.com/z7yZXiBB

body:
[![Leave "boards.txt" alone. It is wrong side of your goal.][1]][1]

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

> C:\Users\\%USERNAME%\AppData\Local\Arduino15\packages\arduino\hardware\avr

    leonardo.build.mcu=atmega32u4
    leonardo.build.f_cpu=16000000L
    leonardo.build.vid=0x2341     <--- here
    leonardo.build.pid=0x8036
    leonardo.build.usb_product="Arduino Leonardo"

----------

    leonardo.build.vid=0x256f
    leonardo.build.pid=0xc631
    leonardo.build.usb_product="SpaceMouse Pro Wireless (cabled)"


message:
6v High Torque Servo Won't Function On Motor Shield?

[![circuit diagram here][1]][1]

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

I have only ever been able to get this servo to “somewhat” work when connected to 5v pin on the shield, the ground on the shield, and the signal line attached to whatever pin. But 5v is not enough and 9v is too much. I'm trying a million different ways to power this thing, but I don't understand why I give it an appropriate voltage from X source (while still having the signal line connected of course), and it doesn't want to move at all.

So currently my Arduino is powered via USB. The shield/motor is powered from a 12v 2a power supply, which with a simple voltage divider circuit gets me 6.29V. Multimeter seems to show this works. Also the “Vin Connect” jumper on back was cut to make the screw terminals a dedicated power line for the motor, per Arduino website. I tried this set up without cutting the jumper too, same - no result.

Can anyone help me out? All I want to do is power my arduino with shield, and motor, however that has to happen, and be able to run the "Servo Sweep" example code.

https://docs.arduino.cc/hardware/motor-shield-rev3

https://www.amazon.com/ANNIMOS-Digital-Voltage-Stainless-Waterproof/dp/B07KTSCN4J

body:
It may pay to think about current required as well as voltage. Looking at a data sheet I found online ([data sheet link)][1] it refers to a stall current of 3.5A when running at 6V.

What do you mean by “somewhat”? Can you give more detail on the behavior you see? It may be useful to hook your multimeter up as an ammeter to get an idea of whether current draw is approaching the limit of the wall plug (2A) used.

  [1]: https://m.media-amazon.com/images/I/81EFGw8qkhL.pdf


message:
Fluctuate output produce by LM35 temperature using Arduino and LINX LabVIEW

So I am currently working on a small project which involves Arduino, LINX LabVIEW and LM35 temperature sensor. I dont know why but sometimes the output graph plots weird fluctuate value (kinda looks like sine wave with noise), sometimes it just plots a stable value and could be adjust by increase the temperature around the sensor.

[![enter image description here][1]][1]

I take a look at the datasheet (https://www.ti.com/lit/ds/symlink/lm35.pdf), at fig 13 they recommend to add a resistor or a bypass capacitor at the output of the sensor. What is the problem ? I mean sometimes it still work like it should be but most of the time it just some weird wave. My the image of my vi and my setup is attached below so hopefully someone could help me to identify the problem and the solution.
[![enter image description here][2]][2]
[![enter image description here][3]][3]

  [1]: https://i.stack.imgur.com/90x7B.png
  [2]: https://i.stack.imgur.com/xeHUw.png
  [3]: https://i.stack.imgur.com/G7bHv.jpg

body:
I don't use LabVIEW with Arduino (UNO) often, so you might have to do some troubleshooting yourself (i.e. is the A0 really just the 0 in the sub-VI?), but!

Even without the resistor (which is useful for multiple things), your values are a little bit out of the range--I'd expect at least 20mV for 2C; moreover, assuming a normal ambient temperature, you should be seeing values around ~250mV (but next time, please label your graphs!). Therefore, what you are seeing is simply noise and while there are ways to mitigate that, I would start with a new sensor and this time *correctly* connect it. You should've flipped your 5V and GND to accommodate the fact that you've changed the way it's facing referencing the datasheet. You could try flipping it and seeing if it works, but there is a good chance you might have burned it up.

When you get the value acquired correctly, you should probably do some smoothing on it before you convert it into temperature--if you're sampling at 10 Hz, you could build a value once per second. I'm not sure what you're using it for, but if it's for simple ambient temperature monitoring, that will get rid of some noise--you could simply fill up an array and average it every second and put that number to be further processed and displayed. Simple averaging will work like a low pass filter, as you're getting rid of all the fast-changing values and keeping the base value.

A resistor might be helpful as it helps the sensor with driving high-capacitance loads--as in, the load would require a certain charge to be delivered before they change the voltage and the LM35 cannot easily do it, but you could decouple and form, essentially, a low-pass filter by adding a resistor in series with the capacitive load. In your case, I would consider it because usually breadboards contain a lot of capacitance; in other words, they can act as capacitors pretty well! Either way, the datasheet promises a 0.5 C linearity around room-temperatures, so at best you might get +/- 2.5mV of fluctuations or a range of 5mV of noise, but of course, you can always make this worse :)

Let me know if you need any further help!


message:
DHT20 and Oled display not working together

I am trying to get my DHT20 and Oled (Both from the Arduino Sensor Kit) to work at the same time. I am able to get them working separately with their respective test codes but when I try to combine the codes the Oled display no longer works. Both are I2C connections but I checked and each device has a different address so that shouldn't be a problem.

Here is my DHT20 test code:

    #include "Arduino_SensorKit.h"

    //uncomment line below if using DHT20
    #define Environment Environment_I2C

    void setup() {
      //uncomment line below if using DHT20
      Wire.begin();
      Serial.begin(9600);
      Environment.begin();
    }

    void loop() {
      Serial.print("Temperature = ");
      Serial.print(Environment.readTemperature()); //print temperature
      Serial.println(" C");
      Serial.print("Humidity = ");
      Serial.print(Environment.readHumidity()); //print humidity
      Serial.println(" %");
      delay(2000);
    }

Here is my Oled display test code:

    #include "Arduino_SensorKit.h"
    void setup() {
      Oled.begin();
      Oled.setFlipMode(true);
    }

    void loop() {
      int random_value = random(0, 1023);   // create a random value

      Oled.setFont(u8x8_font_chroma48medium8_r);
      Oled.setCursor(0, 3);
      Oled.print("Value: ");
      Oled.print(random_value);
      delay(1000);
    }

This is my code where I tried to get both devices working at the same time:

    #include "Arduino_SensorKit.h"
    #define Environment Environment_I2C

    void setup() {

      Oled.begin();
      Oled.setFlipMode(true);

      Wire.begin();
      Serial.begin(9600);
      Environment.begin();
    }

    void loop() {

      Oled.setFont(u8x8_font_chroma48medium8_r);
      Oled.setCursor(0, 3);
      Oled.print("Testing");

      Serial.print("Temperature = ");
      Serial.print(Environment.readTemperature()); //print temperature
      Serial.println(" C");
      Serial.print("Humidity = ");
      Serial.print(Environment.readHumidity()); //print humidity
      Serial.println(" %");

      delay(2000);

    }

When I use the above code the temp and humidity values are printed in the serial monitor but the Oled does not display anything.

Any help is much appreciated!

body:
### The basic problem

I don't have this sensor kit. But am able to observe what you're describing with substitutes and stand-ins. There seem to be two things you can do.

The basic problem is that the Arduino_SensorKit library is written to use software/bit-banged I2C for the display. Or rather, it tells U8G2LIB to do this, for what reason I don't know. When the ATmega328P I2C peripheral is enabled the GPIO hardware is no longer driving the pins. So the moment you enable the hardware I2C (via the DHT20 code) the GPIO bit-banging code in U8G2LIB cannot work correctly.

So, there are at least two ways this can be made to work.

* Modifying your code so it works with how the Arduino_SensorKit library is written.

* The other is modifying the Arduino_SensorKit library to use hardware I2C, in which case your original code works verbatim.

## Modifying the sketch

You can modify your sketch as follows:

```
#include "Arduino_SensorKit.h"
#define Environment Environment_I2C

void setup() {
  Oled.begin();
  Oled.setFlipMode(true);

  Serial.begin(9600);

  Wire.begin(); // only here to match the subsequent .end()
}

void loop() {
  Wire.end();  // make I2C release control back to GPIO
  {
    Oled.setFont(u8x8_font_chroma48medium8_r);
    Oled.setCursor(0, 3);
    Oled.print(millis()); //Oled.print("Testing");
  }
  Wire.begin(); // re-enable I2C for use by DHT20 ("Environment")

  Serial.print("Temperature = ");
  Serial.print(Environment.readTemperature()); //print temperature
  Serial.println(" C");
  Serial.print("Humidity = ");
  Serial.print(Environment.readHumidity()); //print humidity
  Serial.println(" %");

  delay(2000);
}
```

For the most part the AVR Wire library doesn't care if you use repeated `begin()` or repeated `end()` calls. It may affect your speed setting though. The braces around the `Oled` usage are just there for visual effect.

Anyway, it works when you make sure `Oled` can use GPIO.

## Modifying Arduino_SensorKit

With the following changes to Arduino_SensorKit library version 1.2.1 (current as of writing) I am able to use your sketch code verbatim. I also modified it to print `millis()` rather than `"Testing"` to be sure it was *continuing* to update the display.

### Arduino_SensorKit.h

On [line 24 of the libraries Arduino_SensorKit.h file](https://github.com/arduino-libraries/Arduino_SensorKit/blob/1.2.1/src/Arduino_SensorKit.h#L24), change:

```c++
extern U8X8_SSD1306_128X64_NONAME_SW_I2C Oled;
```

to

```c++
extern U8X8_SSD1306_128X64_NONAME_HW_I2C Oled;
```

Note `HW` (hardware) rather than `SW` (software).

### Arduino_SensorKit.cpp

Likewise make [the counterpart change to the definition of](https://github.com/arduino-libraries/Arduino_SensorKit/blob/1.2.1/src/Arduino_SensorKit.cpp#L14) `Oled` corresponding to above change in `extern` declaration of `Oled`, from:

```c++
U8X8_SSD1306_128X64_NONAME_SW_I2C Oled(/* clock=*/ _PIN_SCL, /* data=*/ _PIN_SDA, /* reset=*/ U8X8_PIN_NONE);
```

to:

```c++
U8X8_SSD1306_128X64_NONAME_HW_I2C Oled(/* clock=*/ _PIN_SCL, /* data=*/ _PIN_SDA, /* reset=*/ U8X8_PIN_NONE);
```

You can probably remove the arguments from the constructor call here; the ATMega328P has no options with respect to configuring TWI/I2C for more than one set of pins.

---

There's also nothing stopping you from leaving it as `U8X8_SSD1306_128X64_NONAME_SW_I2C`, but changing the pins so that the software I2C uses pins other than A4/A5 so as not to conflict with the DHT20 libraries use of hardware I2C.

---

For reference the U8G2LIB version I tested with was 2.33.15. arduino-cli version 0.32.2. arduino:avr core 1.8.7. *I don't think you need these. I'm just being complete in case someone finds this 5 years from now or whatever.*


message:
Clear serial data for new incoming values

I'm trying to extract numbers from a string sent via serial and then convert the numbers to integer values which I can use for arithmetic operations or toggle an Led. But the problem is I have to send the string twice before the module can receive it.

I am sending via serial monitor and bluetooth.

Example: if I first power the module and send voltage 100 via serial monitor, it will print voltage 0 instead of voltage 100.

But if I send voltage 100 again, then it will now print voltage 100 and the led will toggle.

Now If I decide to change the string and send voltage 50, it will still print voltage 100 instead of voltage 50.

If I send voltage 50 again, it will now print voltage 50.

So it seems to be printing the previous string for every new string sent to the serial.

So I had to send the same string twice for the device to receive it.

---

**How can I send the string once that the module will receive it and print on serial?** I don't want to be sending twice.

See my code and results below, any help would be appropriated.

Results of the code on the serial monitor with Autoscroll enabled:

When power is connected.
```
voltage: 0
voltage: 0
voltage: 0
voltage: 0
voltage: 0
```

When I sent "voltage 100".
```
voltage: 0
voltage: 0
voltage: 0
voltage: 0
voltage: 0
```

Then I sent "voltage 100" again.
```
voltage: 100
voltage: 100
voltage: 100
voltage: 100
```

Sent "voltage 50".
```
voltage: 100
voltage: 100
voltage: 100
voltage: 100
```

Sent "voltage 50" again.
```
voltage: 50
voltage: 50
voltage: 50
voltage: 50
```

Sent "voltage 120".
```
voltage: 50
voltage: 50
voltage: 50
voltage: 50
```

Sent "voltage 120" again.
```
voltage: 120
voltage: 120
voltage: 120
voltage: 120
```

This is my code:

```c++
int CD;
int maxvoltage = 100;
String readString, data;
const int Led = PB5;

void setup()
{
    Serial.begin(38400);
    pinMode(Led, OUTPUT);
}

void loop()
{
    if (Serial.available())
    {
        char c = Serial.read();  //gets one byte from serial buffer
        if (c == ' ')
        {
            Serial.println(readString); //prints string to serial port out

            if (readString.indexOf("voltage") >= 0)
            {
                data = readString.substring(0, 3); // extract numbers from the string
                CD = data.toInt(); // convert the extracted numbers to integers
                readString = ""; //clear variable for new input
                data = ""; // clear data
            }
        }
        else
        {
            readString = readString + c; //makes the string readString
        }
    }

    if (CD >= maxvoltage)
    {
        digitalWrite(Led, HIGH);
    }
    else
    {
        digitalWrite(Led, LOW);
    }
    Serial.print("voltage: ");
    Serial.println(CD);
    do_something(1000000); // do some delay
}

int do_something(int moment)
{
    volatile int i, j;

    for (i = 0; i < moment; ++i)
    {
        j++;
    }
}
```

body:
It is difficult to help with out knowing exactly what characters are being sent and why.  If we assume this is what is being sent:

    "voltage 24\n"
    "voltage 24\n"
    "voltage 55\n"
    "voltage 55\n"

Then we can speculate on how the code will react:

 1. The code will accept 7 new characters.
 2. The 8th character is a space (0x20) so the code will print out "voltage" (not mentioned in the question).
 3. This string is tested and found to be a match. Consequently the code will attempt to convert the characters "volta" (characters in position 0 through 4) into an integer.  This likely fails and the function likely returns zero. So the this is printed out "voltage: volta OK0" (the zero mentioned in the question, but the "volta" is not).
 4. The code will accept an unknown number of characters which were likely "20". But since there are likely no spaces (0x20) in the string, these are not processed as above.
 5. The process then repeats.

It is clear in the question the expected numbers are eventually printed.  So there is problem with the above. Either the assumed behavior is wrong or the received string is different then the expected.

If we assume this is what is being sent instead:

    "voltage 24 \n"
    "voltage 24 \n"
    "voltage 55 \n"
    "voltage 55 \n"

Then the expected output would change to:

    "voltage"
    "voltage: volta OK0"
    "24"
    "voltage: 24  OK24"
    "voltage"
    "voltage: volta OK0"
    "24"
    "voltage: 24 OK24"
    "voltage"
    "voltage: volta OK0"
    "55"
    "voltage: 55  OK55"
    "voltage"
    "voltage: volta OK0"
    "55"
    "voltage: 55 OK55"

While closer, this output still does not completely agree with how the question was worded.

So...

 - Edit your question to either make it clear what the program is printing out or copy and past the output of the program into the question. This answer can be adjusted if the question is edited.
 - Unlike human to computer communications, computer to computer communications is best kept short and with out spaces. Spaces are confusing to parse and often leads to coding problems. Better to use characters like ":" or "," to separate words and numbers.
 - It is assumed if the string, say, "voltage 24" is received it is not to be processed until it is received in its entirety. Consider ending the string with a, for example, ";".  Then testing for that character instead of for a space.  Also adjust your substring() parameters to pick off the number.  Likely passing 8 & 9 will result in the expected values.


body:
The error lays in your algorithm to collect the command. Your sketch uses the space character `' '` as the separator between incoming messages.

After the first transmission of "voltage 100", the resulting string in `readString` is `"voltage"`. The method `indexOf()` returns 0 as the index, because the keyword matches. Therefore, your sketch tries to parse an integer from the first characters of that string, which fails and returns zero. Therefore, the voltage is printed as "0".

With each next transmission, the following happens. For example, let's look at your second transmission, "voltage 100". The resulting string in `readString` is `"100\nvoltage"` or  `"100\r\nvoltage"`, depending on the end-of-line marker. It is composed of the remainder of the former transmission and the beginning of the current transmission. The method `indexOf()` returns a positive value greater than zero as the index. Therefore, your sketch tries to parse an integer from the first characters of that string, which succeeds this time and returns 100. But it is the value of the former transmission. Therefore, the voltage is now printed as "100".

The solution is to drop the space character as separator and instead use the end-of-line marker. Read the complete transmission into `readString`. Then check for the keyword and parse the later part. The actual implementation is left as an enlightening exercise.


message:
Automating Serial Monitor / Execute Serial Monitor Command without CMD input

Have a nice day.

Experiment title:
PH Sensor calibration and Utilization.

Experiment description:
I am working on an experiment where I am interfacing the esp32 with [a DFRobot PH Sensor Kit V2][1]. This kit is developed for 3.3V devices.

They have provided the user manual how to connect, calibrate and use this PH sensor meter.

In the description they have mentioned that this sensor should be calibrated with a buffer solution to detect the proper PH value.

This is [the link][2] for the library. They have also mentioned the procedure to calibrate it. I have done it and it's working fine.

Now I want to automate this calibration process. Which means that I want to automate whatever serial command I am currently entering manually with sketch/function calls. I don't want to enter commands in the Serial Monitor.

Let's say, when I press a button first it should execute "enterph" then it should wait in a loop for 10 times then it should execute "calibrateph" then again it should wait in a loop for 10 times and at last it should execute the "exitph" command.

Can anyone guide me how to do this?

  [1]: https://www.dfrobot.com/product-1782.html
  [2]: https://github.com/DFRobot/DFRobot_PH

body:
You're going to have to write a piece of software on your computer with whatever is your favorite language, and run it, connected to the proper serial port. I do this a lot in applications that communicate with an IOT device connected to a USB port. It's not very difficult.

Even a simple Python script should do the trick.

**UPDATE** (following comment)

In which case, towards the end of `setup()`, you read in a while loop the pin where the button is connected. When it goes HIGH, you send the first command. Then you wait for whatever period you feel is appropriate, then send the next command, then rinse and repeat.


message:
Alternative to polling interrupt flag from main loop?

I am using an ISR, which is written to be as minimal as possible:

``` c++
volatile bool interrupt1{};

void ISR1() {
    interrupt1 = true;
}
```
The interrupt is handled by polling the interrupt1 variable in ```loop()```:

```c++
if (interrupt1 == true) {

// Do stuff

interrupt1 = false;
}
```

Even though the interrupt signal coming in on the gpio isn't polled, the method described above is instead polling the interrupt variable from ```loop()```.

As an alternative to the above, is it possible to use some kind of push logic on the software side whenever an interrupt occurs, instead of continuously polling the interrupt variable? I hesitate to handle the full task from the ISR, as it's performing a lot of things.

What are my options here?

body:
If the task is pretty short and time sensitive, your best option is to
put it in the interrupt handler.

If the task is big and not too urgent (like: it could well wait for a
millisecond or so), your approach of polling the flag within `loop()` is
the best one, provided the main program is non-blocking.

If the task is both big and urgent... you may have a difficult problem.
You could try both approaches and see which one works best. Or you may
try to split the task into a top half (short and urgent) and a bottom
half (long but not so urgent). The interrupt handler would then perform
the top half and set a flag, whereas the main loop would poll the flag
and perform the bottom half.

**Edit**: for a short discussion on the top half / bottom half approach,
see the first paragraphs of [this article on Linux kernel
development][1].

[1]: https://litux.nl/mirror/kerneldevelopment/0672327201/ch07lev1sec1.html


body:
Since you tagged it Teensy: You could also reduce the priority of the interrupt, so that it can be interrupted by higher priority interrupts. Thus you can implement interrupts with longer durations without blocking important system functions.

Here is an example using the GPT1 and GPT2 timers running at different priorities:

```c++
#include "Arduino.h"
#include "TeensyTimerTool.h"

using namespace TeensyTimerTool;

PeriodicTimer loPrioTimer(GPT1);
PeriodicTimer hiPrioTimer(GPT2);

void onLowPrioTimer() // some long task running from interrupt with low prio
{
    Serial.printf("  Start low prio isr @t=%d ms\n", millis());

    for (int i = 0; i < 10; i++)
    {
        Serial.printf("    lowPriority task %d\n",i);
        delay(10);
    }

    Serial.println("  Stop low prio isr");
}

void onHiPrioTimer() // high prio, will interrupt the low prio isr
{
    Serial.printf("high priority @t=%d ms\n", millis());
}

void setup()
{
    while (!Serial) {}

    loPrioTimer.begin(onLowPrioTimer, 500ms); // GPT1
    hiPrioTimer.begin(onHiPrioTimer, 50ms);   // GPT2

    NVIC_SET_PRIORITY(IRQ_GPT1, 128); // lowest prio
    NVIC_SET_PRIORITY(IRQ_GPT2, 16);  // high prio
}

void loop()
{
}
```
which prints:
```
high priority @t=1057 ms
high priority @t=1107 ms
high priority @t=1157 ms
high priority @t=1207 ms
high priority @t=1257 ms
high priority @t=1307 ms
high priority @t=1357 ms
high priority @t=1407 ms
high priority @t=1457 ms
high priority @t=1507 ms
  Start low prio isr @t=1507 ms
    lowPriority task 0
    lowPriority task 1
    lowPriority task 2
    lowPriority task 3
    lowPriority task 4
high priority @t=1557 ms
    lowPriority task 5
    lowPriority task 6
    lowPriority task 7
    lowPriority task 8
    lowPriority task 9
high priority @t=1607 ms
  Stop low prio isr
high priority @t=1657 ms
high priority @t=1707 ms
high priority @t=1757 ms
high priority @t=1807 ms
high priority @t=1857 ms
high priority @t=1907 ms
high priority @t=1957 ms
high priority @t=2007 ms
  Start low prio isr @t=2007 ms
    lowPriority task 0
    lowPriority task 1
    lowPriority task 2
    lowPriority task 3
    lowPriority task 4
high priority @t=2057 ms
    lowPriority task 5
    lowPriority task 6
    lowPriority task 7
    lowPriority task 8
    lowPriority task 9
high priority @t=2107 ms
  Stop low prio isr
high priority @t=2157 ms
high priority @t=2207 ms
high priority @t=2257 ms
high priority @t=2307 ms
```

This shows that the high priority timer (running at 50 ms interval) intercepts the low priority ISR which runs every 500 ms for about 100 ms.


message:
Relay switch when CO value is met

I need some help with my code using mq-7 and esp8266.

Components I used:
MQ-7 (i've heated it up for 48hours)
ESP8266
4-channel relay
24vdc fan
mb102

All i wanna to do is mq-7 to constantly reading the co value, then the 4-channel relay will activate based on the ppm value to control the fan speed using different vinput on each relay channel.

I'm using the mq7.h library and here's my code for reference:

 ```
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <MQ7.h>

LiquidCrystal_I2C lcd(0x3F, 16, 2);
MQ7 mq7(A0,5.0);
const int relay1Pin = D6;
const int relay2Pin = D7;
const int relay3Pin = D8;
const float lambat_threshold = 10; //in ppm
const float med_threshold = 20; //in ppm
const float cepat_threshold = 30; //in ppm

void setup()
{
 Serial.begin(115200);
 pinMode(A0, INPUT);
pinMode(relay1Pin, OUTPUT);
pinMode(relay2Pin, OUTPUT);
pinMode(relay3Pin, OUTPUT);
digitalWrite(relay1Pin, LOW);
digitalWrite(relay2Pin, LOW);
digitalWrite(relay3Pin, LOW);
 lcd.begin();
 lcd.backlight();
 lcd.setCursor(00,00);
  lcd.print("Cooked Hood CO");
  lcd.setCursor(00,1);
  lcd.print("Istiyo Budi");
  delay(2000);
  lcd.clear();
}

void loop()
{
  float co = mq7.getPPM();
  lcd.setCursor(1, 0);
  lcd.print("CO: ");
  lcd.print(co);
  lcd.print(" PPM");
  delay(1000);
    Serial.print(co);
    Serial.println(" PPM");
    if (co < lambat_threshold) {
    digitalWrite(relay1Pin, HIGH);
    digitalWrite(relay2Pin, LOW);
    digitalWrite(relay3Pin, LOW);
    lcd.setCursor(1, 1);
    lcd.print("Speed: LOW");
  } else if (co >= med_threshold) {
    digitalWrite(relay1Pin, LOW);
    digitalWrite(relay2Pin, HIGH);
    digitalWrite(relay3Pin, LOW);
    lcd.setCursor(1, 1);
    lcd.print("Speed: MED");
  } else if (co >= cepat_threshold) {
    digitalWrite(relay1Pin, LOW);
    digitalWrite(relay2Pin, LOW);
    digitalWrite(relay3Pin, HIGH);
    lcd.setCursor(1, 1);
    lcd.print("Speed: HIGH");
    delay(2000);
}
}
 ```
Problem is, somehow when the value is around 30 or more, the relay won't switch. I'm stuck with this problem right now.

body:
When `co >= cepat_threshold` it is also `> med_threshold`
Reverse the tests, starting with the highest value:

    if (co >= cepat_threshold) {
        digitalWrite(relay1Pin, LOW);
        digitalWrite(relay2Pin, LOW);
        digitalWrite(relay3Pin, HIGH);
        lcd.setCursor(1, 1);
        lcd.print("Speed: HIGH");
    } else if (co >= med_threshold) {
        digitalWrite(relay1Pin, LOW);
        digitalWrite(relay2Pin, HIGH);
        digitalWrite(relay3Pin, LOW);
        lcd.setCursor(1, 1);
        lcd.print("Speed: MED");
    } else {
        digitalWrite(relay1Pin, HIGH);
        digitalWrite(relay2Pin, LOW);
        digitalWrite(relay3Pin, LOW);
        lcd.setCursor(1, 1);
        lcd.print("Speed: LOW");
    }


body:
Look at the structure of your `if ... else` statements (your "decision tree"). Imagine what happens when your CO sensor returns a value of 30 (for example).

Your code first evaluates `if (co < lambat_threshold)`, which is not true because lambat_threshold is 10 and co is 30. It will skip to the `else` part of the first `if` statement.

It then evaluates `if (co >= med_threshold)`, which evaluates to true because med_threshold is 20 and 30 is greater than 20. It will then carry out the commands in that block of code (i.e. turn on relay 2 and turn off the other relays) and print "MED" on the display.

Your code will then *skip* the last part of your decision block (i.e. `else if (co > cepat_threshold)` ) because this piece of your code comes after the `else` part of an `if` statement that has already evaluated to true.

The easiest way to solve this is to swap the `if (co >= med_threshold)` and the `if (co >= cepat_threshold)` parts of your decision tree.


message:
How to properly declare a random URL in ESPAsyncWebServer?

I'm trying to make a onetime URL with a random string to for example give a user onetime access to a house with a smart lock. I have a function to make a fixed 8-character string and the following code with the address that is randomly made.

```c++
  controlserver.on(userurl, HTTP_GET, [](AsyncWebServerRequest *request){
   if(urlactive==true){
   if(request->authenticate("admin","admin")){
      running=true;
      request->send(200);

      Serial.println("entered");
      urlactive=false;
      }else {
       return request->requestAuthentication();
      }
   }else{
       generateRandomString();
       request->send(200, "text/html", HTML_CSS_STYLING+ "<body>"
    "<br><h1 style=\"color:white; direction: rtl;\">LInk is not valid!</h1></body>" );

   }
  });
```
the following function generates the `userurl` which is a `const char*` because the requirement of ESPAsyncWebServer library.

```cpp
void generateRandomString() {
  const char specialChars[] = "0123456789";
  const char letters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
  String randomStringurl = "";
  String keppmyuserpass = "";
  randomStringurl += letters[random(26, 51)];
  for (int i = 0; i < 6; i++) {
    randomStringurl += letters[random(0, 51)];
  }
  randomStringurl += specialChars[random(0, 9)];
  Serial.println(randomStringurl);
  userurl = randomStringurl.c_str();

}
```
everything works fine when I enter the generated string that I convert into `const char*` using `c_str()` but I noticed an error when I copied the string partially by accident and too much to my surprise, I saw that the popup for the username and password showed up and I didn't expecte it, because I have a `notFound` function that will show an error when the entered URL doesn't exist. entered different strings but the problem is persistent. I think there is a problem with my string conversion to `const char*` using `c_str()`. but is it?

Here is compliable code, the wifi mode is STA ```WiFi.mode(WIFI_STA);``` :
```cpp
#include <Arduino.h>
#ifdef ESP32
#include <WiFi.h>
#include <AsyncTCP.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#endif
#include <ESPAsyncWebServer.h>

const char* userurl;
String  randomStringurl = "";
String  keppmyuserpass = "";

AsyncWebServer server(80);

const char* ssid = "your_ssid";
const char* password = "your_password";

const char* PARAM_MESSAGE = "message";

void notFound(AsyncWebServerRequest *request) {
    request->send(404, "text/plain", "Not found");
}
void generateRandomString() {
  const char specialChars[] = "0123456789";
  const char letters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
  randomStringurl = "";
  keppmyuserpass = "";
  randomStringurl += letters[random(26, 51)];
  for (int i = 0; i < 6; i++) {
    randomStringurl += letters[random(0, 51)];
  }
  randomStringurl += specialChars[random(0, 9)];
  Serial.println(randomStringurl);
  userurl = randomStringurl.c_str();
  keppmyuserpass = randomStringurl;
  keppmyuserpass += letters[random(26, 51)];
  keppmyuserpass += specialChars[random(0, 9)];
  Serial.println(keppmyuserpass);

}
void setup() {

    Serial.begin(115200);
    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, password);
    if (WiFi.waitForConnectResult() != WL_CONNECTED) {
        Serial.printf("WiFi Failed!\n");
        return;
    }

    Serial.print("IP Address: ");
    Serial.println(WiFi.localIP());

    server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
        request->send(200, "text/plain", "Hello, world");
    });

    // Send a GET request to <IP>/get?message=<message>
    server.on(userurl, HTTP_GET, [] (AsyncWebServerRequest *request) {
        String message;
        if (request->hasParam(PARAM_MESSAGE)) {
            message = request->getParam(PARAM_MESSAGE)->value();
        } else {
            message = "No message sent";
        }
        request->send(200, "text/plain", "Hello, GET: " + message);
    });

    // Send a POST request to <IP>/post with a form field message set to <message>
    server.on("/post", HTTP_POST, [](AsyncWebServerRequest *request){
        String message;
        if (request->hasParam(PARAM_MESSAGE, true)) {
            message = request->getParam(PARAM_MESSAGE, true)->value();
        } else {
            message = "No message sent";
        }
        request->send(200, "text/plain", "Hello, POST: " + message);
    });

    server.onNotFound(notFound);

    server.begin();
    generateRandomString();
}

void loop() {
}
```
And here is the code from ESPAsyncWebServer.h library, that required the ```url``` to be a  ```const char* uri``` what am I doing wrong?
```cpp
AsyncCallbackWebHandler& on(const char* uri, WebRequestMethodComposite method, ArRequestHandlerFunction onRequest, ArUploadHandlerFunction onUpload, ArBodyHandlerFunction onBody);
```
New Update: So, I forgot to add a ```"/"``` before the URL, by doing so it solved the problem and here is the new function:
```cpp
void generateRandomString() {
  const char specialChars[] = "0123456789";
  const char letters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
  randomStringurl = "";
  keppmyuserpass = "";
  randomStringurl +="/";
  randomStringurl += letters[random(26, 51)];
  for (int i = 0; i < 6; i++) {
    randomStringurl += letters[random(0, 51)];
  }
  randomStringurl += specialChars[random(0, 9)];
  Serial.println(randomStringurl);
  userurl = randomStringurl.c_str();
  keppmyuserpass = randomStringurl;
  keppmyuserpass += letters[random(26, 51)];
  keppmyuserpass += specialChars[random(0, 9)];
  OTUPC = keppmyuserpass.c_str();
  Serial.println(keppmyuserpass);

}
```
But when I renew the link, the new link is not recognized and the first generated link was working. I think that @6v6gt might be right about this: "Could it also be that the value of ```userurl``` must be known when ```setup()``` runs and the callback is registered?"

body:
6v6gt is right, that the URI for the handler must be known, when you use the `on()` function to set the handler. Inside the library, the `on()` function calls `setUri(const String& uri)`, which which saves the `uri` in the classes interal `String` member variable. Thus the handle will not notice, if the originally used variable changes.

I think the most elegant solution here would to be to use a regular expression for your handler URI (A regular expression is a string expression, that describes a template that can match other strings). That will let the handler match any URI, that fits that regex. Inside the handler you can then get the relevant part of the URI and check, if it is currently valid. If yes, you serve your content, otherwise you serve an error (for example a 404 Not Found).

The third answer to [this question][1] has a code snippet for this:

    #include <uri/UriRegex.h>

    web_server.on(UriRegex("/home/([0-9]+)/first"), HTTP_GET, [&]() {
        web_server.send(200, "text/plain", "Hello from first! URL arg: " + web_server.pathArg(0));
    });

The part of the URI, that's between the brackets, is the regex group, that is then made available via `web_server.pathArg(0)`. Your current code creates a string with one capital letter, 6 lower case letters and one digit, thus a regex group `([A-Z][a-z]{6}[0-9])`. You can read about how regex work online.

When you look at [this repo][2] of ESPAsyncWebServer (I'm not sure, which version you have), in the Readme right at the end under "path variable" you find this snippet:

    server.on("^\\/sensor\\/([0-9]+)$", HTTP_GET, [] (AsyncWebServerRequest *request) {
      String sensorId = request->pathArg(0);
    });

And a note, that regex support must be enabled.

As I didn't test this, I suggest you try both methods and see, what works for you.

  [1]: https://stackoverflow.com/questions/35816454/setting-a-wildcard-in-esp8266webserver
  [2]: https://github.com/me-no-dev/ESPAsyncWebServer#the-async-web-server


message:
Why is my variable giving the wrong value?

I'm making a program to show numbers in a WS2812 LED and TM1637. I'm also using a common 4x4 keypad.

The WS2812 LED is just DIY with 25 x 10. Only two values can be displayed in a LED matrix just now. Without the LED part of the program, just the TM1637 and keypad connected to the Arduino, everything is fine. But adding the LED part of the program, I found out that entering 2 on keypad puts  an erroneous value in my variable (-256 to exact). I tried debugging my code and found out that replacing the last iteration

`for (int i = 225; i <= 231; i++) {`

with this line

`for (int i = 225; i <= 230; i++) {`

mysteriously solved my problem. Any thoughts why this is happening?

```
#include <Keypad.h>
#include <Arduino.h>
#include <TM1637Display.h>
#include <Wire.h>
#include <FastLED.h>
// Module connection pins (Digital Pins)
#define CLK 2
#define DIO 3
#define NUM_LEDS  225
#define LED_PIN   12
CRGB leds[NUM_LEDS];
TM1637Display display(CLK, DIO);
int DisplayNos=0;
int KeyNum;
char key;
boolean NewKey = false;
boolean DeleteAll=false;
int SavedNum;
// for 3 digits
int ExtractDigit[3] = {0, 0, 0};
byte DigitPoint= 1;
const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns
char keys[ROWS][COLS] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};
byte rowPins[ROWS] = {11, 10, 9, 8}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {7, 6, 5, 4}; //connect to the column pinouts of the keypad
//Create an object of keypad
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
void setup(){
  Serial.begin(9600);
  FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);
  FastLED.setBrightness(250);
}
void loop(){
int k;
//  uint8_t data[] = { 0x0, 0x0, 0x0, 0x0 };
//  uint8_t blank[] = { 0x00, 0x00, 0x00, 0x00 };
  display.setBrightness(0x0f);
  key = keypad.getKey();// Read the key
  // Print if key pressed
  if (key){
    Serial.print("Key Pressed : ");
    Serial.println(key);
    if (isDigit(key)){
      KeyNum = key-48;
      Serial.println(key);
      Serial.println(DisplayNos);
      if (DigitPoint==1){
        DisplayNos = 0;
        DisplayNos = KeyNum;
      }
      if (DigitPoint==2){
        DisplayNos = KeyNum + (DisplayNos*10);
      }
      if (DigitPoint==3){
        DisplayNos = KeyNum + (DisplayNos*10);
      }
      DigitPoint= DigitPoint+1;
      if (DigitPoint==4){
        DigitPoint=1;
      }
    }
      if (key=='*'){   // asterist key cancels all char
      DisplayNos = 0;
      DigitPoint = 1;
    }
    if (key=='#'){   // asterisk key cancels all chars

    }
    NewKey = true;
  }
  display.showNumberDec(DisplayNos,false,3,0);
  if (NewKey == true){
    DisplayLED();
    FastLED.show();
  }
}
void DisplayLED(){
int LedNum;
byte digitnos;
NewKey = false;
  ExtractDigit[3] = (DisplayNos/100);
  ExtractDigit[2] = (DisplayNos/10);
  ExtractDigit[1] = (DisplayNos);
  for (int digitnos= 1; digitnos <= 3; digitnos++) {
    LedNum = (digitnos-1)*9;
    if (ExtractDigit[digitnos] == 1){
      leds[21-LedNum]= CRGB::Blue;
      leds[28+LedNum]= CRGB::Blue;
      leds[29+LedNum]= CRGB::Blue;
      leds[71-LedNum]= CRGB::Blue;
      leds[78+LedNum]= CRGB::Blue;
      leds[121-LedNum]= CRGB::Blue;
      leds[128+LedNum]= CRGB::Blue;
      leds[171-LedNum]= CRGB::Blue;
      leds[178+LedNum]= CRGB::Blue;
      leds[221-LedNum]= CRGB::Blue;
      leds[229+LedNum]= CRGB::Blue;
      leds[228+LedNum]= CRGB::Blue;
      leds[227+LedNum]= CRGB::Blue;
    }
    if (ExtractDigit[digitnos] == 2){
      for (int i = 20; i <= 22; i++) {
        leds[i-LedNum] = CRGB::Blue;
      }
      leds[26+LedNum]= CRGB::Blue;
      leds[30+LedNum]= CRGB::Blue;
      leds[68-LedNum]= CRGB::Blue;
      leds[74-LedNum]= CRGB::Blue;
      leds[76+LedNum]= CRGB::Blue;
      leds[122-LedNum]= CRGB::Blue;
      leds[128+LedNum]= CRGB::Blue;
      leds[170-LedNum]= CRGB::Blue;
      leds[180+LedNum]= CRGB::Blue;
      leds[218-LedNum]= CRGB::Blue;
      leds[225+LedNum]= CRGB::Blue;
      leds[226+LedNum]= CRGB::Blue;
      leds[227+LedNum]= CRGB::Blue;
      leds[228+LedNum]= CRGB::Blue;
      leds[229+LedNum]= CRGB::Blue;
      for (int i = 225; i <= 231; i++) {
        leds[i-LedNum] = CRGB::Blue;
      }
    }
  }
  }
```

body:
    #define NUM_LEDS  225
    ...
    CRGB leds[NUM_LEDS];
    ...
      leds[225 + LedNum] = CRGB::Blue;
      leds[226 + LedNum] = CRGB::Blue;
      leds[227 + LedNum] = CRGB::Blue;
      leds[228 + LedNum] = CRGB::Blue;
      leds[229 + LedNum] = CRGB::Blue;

Your RGB matrix has 225 LEDs, but you're writing to RAM out of range and destroying their stored data and/or variables.


message:
Arduino IDE is still saying not connected even after I connected it

While I was using a L293D motor shield on my UNO, the negative wire of my total 7.4v was connected in the motor shield. But mistakenly the positive wire got connected in the UNO and the lights turned on(I don't know if it was a problem or not). Now when I connect the UNO with laptop the IDE says not connected and did not detect the UNO. On the UNO all the lights are on. Can anyone tell me whats the problem?

body:
The grounds are shared on the motor shield and the Arduino.

If your 7.4v wire was connected to Vin, you should be fine, but if the wire was connected to your Arduino 5v supply rail, it now has 7.4v on it and your Arduino is likely dead.


message:
The Y, P, R (Yaw Pitch Roll) values obtained by DMP (Digital Motion Processor) are not getting stabilized,

When tested in 3D space, all the values(Y, P, R) change even though the motion is only in a single direction. Is there any other better algorithm or library that can be used to tackle this, apart from the DMP?

body:
Are you calibrating the gyro and accelerometer?
```
mpu.CalibrateAccel(6);
mpu.CalibrateGyro(6);
```

Check the official Arduino github for examples.
https://github.com/ElectronicCats/mpu6050/blob/master/examples/MPU6050_DMP6/MPU6050_DMP6.ino


message:
Some of my <include> statements do not work

I'm trying to include the thing...
```cpp
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>

BLEServer* pServer = NULL;

void setup() {
  // put your setup code here, to run once:

}

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

}
```

But it simply doesn't see what's inside the .h files:

```
C:\Users\void\AppData\Local\Temp\.arduinoIDE-unsaved20231028-7016-1na7gr9.y1do\sketch_nov28b\sketch_nov28b.ino:6:1: error: 'BLEServer' does not name a type; did you mean 'Server'?
 BLEServer* pServer = NULL;                        // Pointer to the server
 ^~~~~~~~~
 Server
```

May it be, I bought the wrong board? I've set it as lolin s2 mini.

[![enter image description here][1]][1]

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

body:
Many of the [ESP32 variants][1] have Bluetooth/BLE support. The ESP32-S2 board/module you're trying to use does not. [The module](https://www.espressif.com/sites/default/files/documentation/esp32-s2_datasheet_en.pdf) has WiFi, but not Bluetooth.

[![Crop from original board image showing S2 markings highlighted.][2]][2]

So you need another board, Lolin seems to have an -S3 version of your board. But many other boards would work.

The majority of the `<BLEServer.h>` header's contents are [conditionally compiled based on whether or not](https://github.com/espressif/arduino-esp32/blob/2.0.14/libraries/BLE/src/BLEServer.h#L11) `CONFIG_BLUEDROID_ENABLED` is `#define`d.

And this only done for modules that have support for Bluetooth. The Lolin S3 version of the Mini would have Bluetooth support and in the configuration file it would use you can [see it defined](https://github.com/espressif/arduino-esp32/blob/2.0.14/tools/sdk/esp32s3/qio_qspi/include/sdkconfig.h#L178). In the one for the S2 board you are trying to use [it is missing](https://github.com/espressif/arduino-esp32/blob/2.0.14/tools/sdk/esp32s2/qio_qspi/include/sdkconfig.h#L17-L18).

In effect, although you're including the header, it is as though it were blank. So no definition of the `BLEServer` type. It would have been nice if they'd handled this a different way, but this is not uncommon.

  [1]: https://en.wikipedia.org/wiki/ESP32#ESP32-xx_family
  [2]: https://i.stack.imgur.com/X4d42.jpg


message:
ESP32 SPI Mutual Communication

I have two ESP32 cards. I want to set one of these cards as Master and the other as Slave and communicate via SPI. I have done this before on Arduino Uno, but I cannot do this on ESP32.
Below are my Master and Slave codes that I have prepared simply. I can't get what I want in any way. Can anyone help?

**Master Code:**
```cpp
#include <SPI.h>

#define CS_PIN 5  // Choose the appropriate pin for Chip Select (CS)

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

void loop() {
  char dataToSend = 'A';

  digitalWrite(CS_PIN, LOW); // Start communication with the slave
  SPI.transfer(dataToSend); // Send data to the slave
  digitalWrite(CS_PIN, HIGH); // End communication with the slave

  delay(2000); // Delay for demonstration purposes
}
```

**Slave Code:**
```cpp
#include <SPI.h>

#define CS_PIN 5  // Choose the appropriate pin for Chip Select (CS)

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

void loop() {
  if (digitalRead(CS_PIN) == LOW) {  // Check if CS (Chip Select) is LOW, meaning the device is selected
    char receivedData = SPI.transfer(0); // Read received data from the master

    // Display received data on the serial monitor
    Serial.println("Received Data: " + String(receivedData));

    delay(1000);  // Optional delay for demonstration purposes
  }
}

```

***New Code - New Problem:***

I tried to adapt the codes at https://microcontrollerslab.com/esp32-spi-communication-tutorial-arduino/. From what I understand it uses the following pins for SPI: MISO-12; MOSI-13; SCLK-14; SS-15.
I set my connections the same way, but I cannot get the output I expected from the Slave. It remains waiting at the slave.wait line.

**Master Code:**

```cpp
#include <SPI.h>

// Define ALTERNATE_PINS to use non-standard GPIO pins for SPI bus

  #define HSPI_MISO   MISO
  #define HSPI_MOSI   MOSI
  #define HSPI_SCLK   SCK
  #define HSPI_SS     SS

static const int spiClk = 1000000; // 1 MHz

//uninitalised pointers to SPI objects
SPIClass * hspi = NULL;

void setup() {
  //initialise instance of the SPIClass attached to HSPI
  hspi = new SPIClass(HSPI);

  //initialise hspi with default pins
  //SCLK = 14, MISO = 12, MOSI = 13, SS = 15
  hspi->begin();

  pinMode(HSPI_SS, OUTPUT); //HSPI SS
}

// the loop function runs over and over again until power down or reset
void loop() {
  hspi_send_command();
  delay(100);
}

void hspi_send_command() {
  byte data_on = 0b00000001; // data 1 to turn on LED of slave
  byte data_off = 0b0000000; // data 0 to turn off LED of slave

  hspi->beginTransaction(SPISettings(spiClk, MSBFIRST, SPI_MODE0));
  digitalWrite(HSPI_SS, LOW);
  hspi->transfer(data_on);
  digitalWrite(HSPI_SS, HIGH);
  hspi->endTransaction();

  delay(1000);

  hspi->beginTransaction(SPISettings(spiClk, MSBFIRST, SPI_MODE0));
  digitalWrite(HSPI_SS, LOW);
  hspi->transfer(data_off);
  digitalWrite(HSPI_SS, HIGH);
  hspi->endTransaction();
  delay(1000);

}
*/
```

**Slave Code:**

```cpp
#include <ESP32SPISlave.h>

ESP32SPISlave slave;

static constexpr uint32_t BUFFER_SIZE {32};
uint8_t spi_slave_tx_buf[BUFFER_SIZE];
uint8_t spi_slave_rx_buf[BUFFER_SIZE];

#define LED 2

void setup() {
    Serial.begin(115200);
    delay(2000);
    pinMode(LED, OUTPUT);
    // begin() after setting
    // HSPI = CS: 15, CLK: 14, MOSI: 13, MISO: 12 -> default
    // VSPI = CS:  5, CLK: 18, MOSI: 23, MISO: 190
    slave.setDataMode(SPI_MODE0);
    slave.begin();
    // slave.begin(VSPI);   // you can use VSPI like this

    // clear buffers
    memset(spi_slave_tx_buf, 0, BUFFER_SIZE);
    memset(spi_slave_rx_buf, 0, BUFFER_SIZE);
}

void loop() {
    // block until the transaction comes from master
    Serial.println("Initialize...");

    slave.wait(spi_slave_rx_buf, spi_slave_tx_buf, BUFFER_SIZE);

    Serial.println("*********************");

    // if transaction has completed from master,
    // available() returns size of results of transaction,
    // and buffer is automatically updated
    char data;
    while (slave.available()) {
        // show received data
         Serial.print("Command Received: ");
         Serial.println(spi_slave_rx_buf[0]);
         data = spi_slave_rx_buf[0];
         slave.pop();
    }
    if(data == 1 )
    {
        Serial.println("Setting LED active HIGH ");
        digitalWrite(LED, HIGH);
    }
    else if(data == 0 )
    {
        Serial.println("Setting LED active LOW ");
        digitalWrite(LED, LOW);
    }
}
```

body:
For ESP32, unless the exact board variant is specified, by default the macros for `MISO`, `MOSI`, `SCK` and `SS` are defined as follows and are used for VSPI(i.e. SPI0):
```cpp
static const uint8_t SS    = 5;
static const uint8_t MOSI  = 23;
static const uint8_t MISO  = 19;
static const uint8_t SCK   = 18;
```

This can be seen in the [source code](https://github.com/espressif/arduino-esp32/blob/master/variants/esp32/pins_arduino.h#L12C1-L15C33) and HSPI is automatically configured to use SCLK 14, MISO 12, MOSI 13 and SS 15 when `SPI.begin()` is called, see this part of the [source code](https://github.com/espressif/arduino-esp32/blob/master/libraries/SPI/src/SPI.cpp#L100-L103).

Since you defined `HSPI_SS` as `#define HSPI_SS SS`, when you do `pinMode(HSPI_SS, OUTPUT);`, you are actually setting pin 5 as output, not the pin 15 that you thought it was.

There are two ways to properly set up the HSPI port.
1. What you can do is to define the macros as follows and call `hspi->begin();` by passing your configuration:
```cpp
#define HSPI_MISO   12
#define HSPI_MOSI   13
#define HSPI_SCLK   14
#define HSPI_SS     15

void setup() {
  hspi = new SPIClass(HSPI);
  hspi->begin(HSPI_SCK, HSPI_MISO, HSPI_MOSI, HSPI_SS);
  // rest of your setup code
}
```
2. As you can see from the source code shown in the above link, if you don't explicitly pass the pins as parameters when calling `SPI.begin()`, the library will automatically assign the pins based on whether VSPI is used (SCLK 18, MISO 19, MOSI 23, SS 5), or HSPI is used (SCLK 14, MISO 12, MOSI 13 and SS 15). So all you need to define is your `HSPI_SS` pin:

```cpp
#define HSPI_SS     15

void setup() {
  hspi = new SPIClass(HSPI);
  hspi->begin();
  // rest of your setup code
}
```


message:
L298n driver with Arduino with 2 motors won't work

I connected the 12v power supply with 9v battery. The problem is that when i run 1 motor at time from any side (out 1, 2 out 3, 4) it works perfectly, but when I try to run both of them, only one will run and the other won't. They work if I run one motor at a time.

Is this a problem with not enough power? The motors are DC gear motors. This is the code:
```cpp
int in1 = 12;
int in2 = 13;
int in3 = 8;
int in4 = 9;
int en1 = 11;
int en2 = 10;
void setup() {
   pinMode(in3, OUTPUT);
   pinMode(in4, OUTPUT);
   pinMode(en1, OUTPUT);
   pinMode(in1, OUTPUT);
   pinMode(in2, OUTPUT);
   pinMode(en2, OUTPUT);
}

void loop() {
   analogWrite(en1, 255);
   digitalWrite(in1, LOW);
   digitalWrite(in2, HIGH);
   analogWrite(en2, 255);
   digitalWrite(in3, LOW);
   digitalWrite(in4, HIGH);
}
```

body:
Yes, most likely. Motors can draw a lot of power and your 9v battery is probably struggling to output enough voltage. 50-100 mA is about the max current you want to draw from a 9v. 9v batteries have a high internal resistance and the voltage will drop *potentially* well below 9v when you draw a lot of current from them. Used to make Altoids tin USB chargers back in the day with a 9v but cellphones now need multiple Amps of power and so do motors.

Here's a couple things you can do to check:

Set up your code to run both motors. Connect a motor to one side and see if it works. Then connect it to the other side (without changing the program or other wiring.) If that motor runs on both sides, check the other motor. This will make sure both motors are good and that both channels on the driver are good. Check the voltage on the battery and the motor and write down the values each time.
If the current you measure with a single motor is much higher than 25-50 mA, 2 motors will exceed the limit. Note the motor (label them) and the channel it is connected to.

If that seems to check out, connect both motors. We know they don't both spin, but take this time and measure battery voltage and motor voltage. Measure the current if possible too. If you are getting greater than 50-100mA from the battery, you are likely going to have issues.


message:
First Uses of Digispark can't get past upload error

Windows 7 (64Bit) Parallels VM on Macbook Pro running BigSur. Arduino version 1.18.19, Digispark ATtiny85 Micro USB.

Loaded Boards Manager http://digistump.com/package_digistump_index.json and updated all.
Installed Windows Driver DPinst64 from digistump.
Device Manager shows:

>libusb-win32 USB Devices<br>
>   Digispark Bootloader

This a first-time use of Digispark.

I have written a couple of successful programs for the ESP32 devkit v1.
```cpp
Test Program

    void setup() {
      // initialize the digital pin as an output.
      pinMode(0, OUTPUT); //LED on Model B
      pinMode(1, OUTPUT); //LED on Model A
    }

    // the loop routine runs over and over again forever:
    void loop() {
      digitalWrite(0, HIGH); // turn the LED on (HIGH is the voltage level)
      digitalWrite(1, HIGH);
      delay(5000); // wait for a second
      digitalWrite(0, LOW); // turn the LED off by making the voltage LOW
      digitalWrite(1, LOW);
      delay(5000); // wait for a second
    }
```
Compiles OK. Upload immediately goes to the following error: (with the Digispark not plugged in).

>Running Digispark Uploader...\
Plug in device now... (will timeout in 60 seconds)\
Assertion failed: res >= 4, file library/micronucleus_lib.c, line 100

I can find no relevant information on the error, I need help.

body:
The device is only in bootload mode for a brief moment after power-up, therefore you have to unplug the device before hitting upload, and *only* connect it once it tells you to. This way the programmer can hit the bootloader in time to halt normal bootup, before execution is handed off to your code.

Literally stumbled over the same issue today, dunno why it won't just tell you this in the console right away.


message:
Unable to get keypad key in while loop

I'm a beginner into Arduino so I have a little problem where I'm trying to do a countdown on LCD using while loop but I'm also trying to get a key input inside that same while loop. Problem is that its hard to get a input in that while because there are delay because of timer. Tried to look around the internet for solution but didn't find one. If anybody got a good solution I would be great full if you post it :) Thanks again!

Here is my code:
```
while (gameInProgress) {

    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Until boom! ");
    lcd.print(timer);
    lcd.setCursor(0, 1);
    lcd.print(passwordInputed);

    char key = keypad.getKey();
    if (key && gameInProgress) {
      passwordInputed += key;
    }

    analogWrite(buzzerPin, 145);
    delay(200);
    analogWrite(buzzerPin, 0);
    delay(800);
    timer--;
    if (timer == 0){
      gameInProgress = false;
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Boom happend!");
      lcd.setCursor(0, 1);
      lcd.print("You lost :(");
    }
  }
```

body:
In general, when a program needs to perform two or more functions (for example, counting off seconds and reacting to a button press that could happen at any moment) a [state machine][1] programming pattern will provide an optimal solution.

Essentially, remove all calls to delay(). Instead, record the value returned from millis() outside the loop. If tracking a, say, 1 second (1000ms) interval, add 1000 to the recorded value. Each time through the loop, check if mills() is greater then the recorded value.  When it is, change the state, add 1000 to the recorded value again and do what ever is needed when the state indicating 1 second has elapsed has changed.  Now clear the state and wait for the cycle to repeat.

As this loop with out calls to delay() is being executed as fast as possible, a scan for a button press can be added and the necessary reaction to that button press can be very responsive.

Add states as needed for more complex behavior. Remember, in most state machines, outputs normally happen upon state changes. And there are no delays within the loop.  Tests to trigger state changes are run as fast as possible each time through the loop.

  [1]: https://en.wikipedia.org/wiki/Finite-state_machine


message:
Using ESP32CAM board but no face is enrolled

I was working on a project to use the ESP32CAM board to detect faces and open some sort of lock. The program can detect the face using the yellow box that shows up as you can see from the following image:
[![enter image description here][1]][1]

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

But after clicking "Enroll Face", nothing changes. I'm currently using the default CameraWebServer application located in the ESP32CAM board examples. Any advice to solve these issues would be greatly appreciated

body:
The short version is you need an ESP32-S3 (which the ESP32CAM isn't) if you want practical face recognition from this example. But you *may* be able to make face recognition work on the ESP32CAM with this example *very slowly* if you really want to try it.

---

A comment the example code [explains](https://github.com/espressif/arduino-esp32/blob/master/libraries/ESP32/examples/Camera/CameraWebServer/CameraWebServer.ino#L9-L11):

> You must select partition scheme from the board menu that has at least 3MB APP space.
> Face **Recognition is DISABLED for ESP32** and ESP32-S2, because it takes up from 15
> seconds to process single frame. Face *Detection* is ENABLED if PSRAM is enabled as well

My understanding is "detection" refers to just what you're seeing in the image you've included, that it can find faces (**any** face) and draw a box around it. This makes sense because [the board has PSRAM](https://github.com/espressif/arduino-esp32/blob/2.0.14/boards.txt#L16954).

"Recognition" is detection of the **specific** face you "enroll", which "is DISABLED for ESP32". And the ESP32CAM [uses an ESP32](https://github.com/espressif/arduino-esp32/blob/2.0.14/boards.txt#L16947-L16950) (importantly not more powerful ESP32-**S3**)

You can see this again in the form of code rather than a comment [in the web server code](https://github.com/espressif/arduino-esp32/blob/2.0.14/boards.txt#L16947-L16950).

The web page served is not configured to show anything different when those features are disabled. It it just passes events back to the web server code. However, if you're looking at the serial output you should see messages [saying](https://github.com/espressif/arduino-esp32/blob/2.0.14/libraries/ESP32/examples/Camera/CameraWebServer/app_httpd.cpp#L923C1-L923C48) "Unknown command: face_enroll" and "Unknown command: face_recognize" if you have the Core Debug Level setting at Info level or higher.

---

They say it takes 15 seconds on an plain ESP32, which apparently means it is possible if a bit useless. So, if you really want to try it you may be able to modify [this line](https://github.com/espressif/arduino-esp32/blob/2.0.14/libraries/ESP32/examples/Camera/CameraWebServer/app_httpd.cpp#L35C19-L35C19) in app_httpd.cpp to read:

```c++
#define CONFIG_ESP_FACE_RECOGNITION_ENABLED 1
```

<s>I may try it later if I find my ESP32CAM. But the expectation is that it will "work" but have horrible performance.</s> Well, I found my ESP32CAM and edited that line and yes, it barely functions, but you can see that does technically work, at least for a little while. I may be crashing it during the enroll process or it might just be picking up what it thinks are extra faces and it's so bogged down that it stops responding, which may have motivated why they just disabled it outright. Either way, yeah, it behaves more or less as explained by the comment.


message:
Do I connect multiple I2C units to the microcontroler in series or parallel?

I have a project (still planning) with three I2C sensors: GPS, 3-axis gyro+accelerometer, and OLED. Do I connect SDA/SCL in series, or do I connect them in parallel?

body: Connect the three I2C devices in parallel.


body:
Use the [Wikipedia page on the protocol][1] as an introduction to your learning curve on I2C. I may cite:

> At the physical layer, both SCL and SDA lines are [a ...] bus design, [...]

This means that all devices connect in parallel (image from the same page, public domain):

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

> Rp are pull-up resistors, Rs are **optional** series resistors. (Emphasis by me)

  [1]: https://en.wikipedia.org/wiki/I²C
  [2]: https://i.stack.imgur.com/esXHK.png