message:
Adafruit MPU-6050 and adafruit I2C Multiplexer

[![enter image description here][1]][1]
I have 3 adafruit MPUs hooked up to adafruit I2c Multiplexer. All of which is hooked up to a Arduino uno.
Attached is also my code.

    /* Assign a unique ID to this sensor at the same time */

    /*Adafruit_HMC5883_Unified mpu1 = Adafruit_HMC5883_Unified(1);
    Adafruit_HMC5883_Unified mpu2 = Adafruit_HMC5883_Unified(2);*/

    #define TCAADDR 0x70

    #include <Adafruit_MPU6050.h>
    #include <Adafruit_Sensor.h>
    #include <Wire.h>
    Adafruit_MPU6050 mpu1 = Adafruit_MPU6050();
    Adafruit_MPU6050 mpu2 = Adafruit_MPU6050();
    Adafruit_MPU6050 mpu3 = Adafruit_MPU6050();

    void displaySensorDetails(Adafruit_MPU6050 *mpu)
    {
    sensor_t sensor;
    mpu->getGyroSensor();
    Serial.println("------------------------------------");
    Serial.print ("Sensor: "); Serial.println(sensor.name);
    Serial.print ("Driver Ver: "); Serial.println(sensor.version);
    Serial.print ("Unique ID: "); Serial.println(sensor.sensor_id);
    Serial.print ("Max Value: "); Serial.print(sensor.max_value); Serial.println(" uT");
    Serial.print ("Min Value: "); Serial.print(sensor.min_value); Serial.println(" uT");
    Serial.print ("Resolution: "); Serial.print(sensor.resolution); Serial.println(" uT");
    Serial.println("------------------------------------");
    Serial.println("");
    delay(500);
    }

    void setUpMPU(Adafruit_MPU6050 *mpu)
    {
      mpu->setAccelerometerRange(MPU6050_RANGE_8_G);
      Serial.print("Accelerometer range set to: ");
      switch (mpu->getAccelerometerRange()) {
      case MPU6050_RANGE_2_G:
        Serial.println("+-2G");
        break;
      case MPU6050_RANGE_4_G:
        Serial.println("+-4G");
        break;
      case MPU6050_RANGE_8_G:
        Serial.println("+-8G");
        break;
      case MPU6050_RANGE_16_G:
        Serial.println("+-16G");
        break;
      }
      mpu->setGyroRange(MPU6050_RANGE_500_DEG);
      Serial.print("Gyro range set to: ");
      switch (mpu->getGyroRange()) {
      case MPU6050_RANGE_250_DEG:
        Serial.println("+- 250 deg/s");
        break;
      case MPU6050_RANGE_500_DEG:
        Serial.println("+- 500 deg/s");
        break;
      case MPU6050_RANGE_1000_DEG:
        Serial.println("+- 1000 deg/s");
        break;
      case MPU6050_RANGE_2000_DEG:
        Serial.println("+- 2000 deg/s");
        break;
      }

      mpu->setFilterBandwidth(MPU6050_BAND_21_HZ);
      Serial.print("Filter bandwidth set to: ");
      switch (mpu->getFilterBandwidth()) {
      case MPU6050_BAND_260_HZ:
        Serial.println("260 Hz");
        break;
      case MPU6050_BAND_184_HZ:
        Serial.println("184 Hz");
        break;
      case MPU6050_BAND_94_HZ:
        Serial.println("94 Hz");
        break;
      case MPU6050_BAND_44_HZ:
        Serial.println("44 Hz");
        break;
      case MPU6050_BAND_21_HZ:
        Serial.println("21 Hz");
        break;
      case MPU6050_BAND_10_HZ:
        Serial.println("10 Hz");
        break;
      case MPU6050_BAND_5_HZ:
        Serial.println("5 Hz");
        break;
    }
    }

    void tcaselect(uint8_t i) {
    if (i > 7) return;
    Wire.beginTransmission(TCAADDR);
    Wire.write(1 << i);
    Wire.endTransmission();
    }

    void setup(void)
    {
    while (!Serial)
        delay(10); // will pause Zero, Leonardo, etc until serial console opens
    Serial.begin(115200);
    Serial.println("HMC5883 Magnetometer Test"); Serial.println("");
    Serial.println("HMC5883 Magnetometer Test"); Serial.println("");

    /* Initialise the 1st sensor */
    tcaselect(0);
    mpu1.setAccelerometerRange(MPU6050_RANGE_8_G);
    Serial.print("Accelerometer range set to: ");
    switch(mpu1.getAccelerometerRange()) {
    case MPU6050_RANGE_2_G:
      Serial.println("+-2G");
      break;
    case MPU6050_RANGE_4_G:
      Serial.println("+-4G");
      break;
    case MPU6050_RANGE_8_G:
      Serial.println("+-8G");
      break;
    case MPU6050_RANGE_16_G:
     Serial.println("+-16G");
      break;
    }
    mpu1.setGyroRange(MPU6050_RANGE_500_DEG);
    Serial.print("Gyro range set to: ");
    switch (mpu1.getGyroRange()) {
    case MPU6050_RANGE_250_DEG:
      Serial.println("+- 250 deg/s");
      break;
    case MPU6050_RANGE_500_DEG:
      Serial.println("+- 500 deg/s");
      break;
    case MPU6050_RANGE_1000_DEG:
      Serial.println("+- 1000 deg/s");
      break;
    case MPU6050_RANGE_2000_DEG:
      Serial.println("+- 2000 deg/s");
      break;
    }
    mpu1.setFilterBandwidth(MPU6050_BAND_21_HZ);
    Serial.print("Filter bandwidth set to: ");
    switch (mpu1.getFilterBandwidth()) {
    case MPU6050_BAND_260_HZ:
      Serial.println("260 Hz");
      break;
    case MPU6050_BAND_184_HZ:
      Serial.println("184 Hz");
      break;
    case MPU6050_BAND_94_HZ:
      Serial.println("94 Hz");
      break;
    case MPU6050_BAND_44_HZ:
      Serial.println("44 Hz");
      break;
    case MPU6050_BAND_21_HZ:
      Serial.println("21 Hz");
      break;
    case MPU6050_BAND_10_HZ:
      Serial.println("10 Hz");
      break;
    case MPU6050_BAND_5_HZ:
      Serial.println("5 Hz");
      break;
    }

    /* Initialise the 2 sensor */
    tcaselect(1);
    mpu2.setAccelerometerRange(MPU6050_RANGE_8_G);
    Serial.print("Accelerometer range set to: ");
    switch(mpu1.getAccelerometerRange()) {
    case MPU6050_RANGE_2_G:
      Serial.println("+-2G");
      break;
    case MPU6050_RANGE_4_G:
      Serial.println("+-4G");
      break;
    case MPU6050_RANGE_8_G:
      Serial.println("+-8G");
      break;
    case MPU6050_RANGE_16_G:
     Serial.println("+-16G");
      break;
    }
    mpu2.setGyroRange(MPU6050_RANGE_500_DEG);
    Serial.print("Gyro range set to: ");
    switch (mpu1.getGyroRange()) {
    case MPU6050_RANGE_250_DEG:
      Serial.println("+- 250 deg/s");
      break;
    case MPU6050_RANGE_500_DEG:
      Serial.println("+- 500 deg/s");
      break;
    case MPU6050_RANGE_1000_DEG:
      Serial.println("+- 1000 deg/s");
      break;
    case MPU6050_RANGE_2000_DEG:
      Serial.println("+- 2000 deg/s");
      break;
    }
    mpu2.setFilterBandwidth(MPU6050_BAND_21_HZ);
    Serial.print("Filter bandwidth set to: ");
    switch (mpu1.getFilterBandwidth()) {
    case MPU6050_BAND_260_HZ:
      Serial.println("260 Hz");
      break;
    case MPU6050_BAND_184_HZ:
      Serial.println("184 Hz");
      break;
    case MPU6050_BAND_94_HZ:
      Serial.println("94 Hz");
      break;
    case MPU6050_BAND_44_HZ:
      Serial.println("44 Hz");
      break;
    case MPU6050_BAND_21_HZ:
      Serial.println("21 Hz");
      break;
    case MPU6050_BAND_10_HZ:
      Serial.println("10 Hz");
      break;
    case MPU6050_BAND_5_HZ:
      Serial.println("5 Hz");
      break;
    }

    /* Initialise the 3rd sensor */
    tcaselect(2);
    mpu3.setAccelerometerRange(MPU6050_RANGE_8_G);
    Serial.print("Accelerometer range set to: ");
    switch(mpu1.getAccelerometerRange()) {
    case MPU6050_RANGE_2_G:
      Serial.println("+-2G");
      break;
    case MPU6050_RANGE_4_G:
      Serial.println("+-4G");
      break;
    case MPU6050_RANGE_8_G:
      Serial.println("+-8G");
      break;
    case MPU6050_RANGE_16_G:
     Serial.println("+-16G");
      break;
    }
    mpu3.setGyroRange(MPU6050_RANGE_500_DEG);
    Serial.print("Gyro range set to: ");
    switch (mpu1.getGyroRange()) {
    case MPU6050_RANGE_250_DEG:
      Serial.println("+- 250 deg/s");
      break;
    case MPU6050_RANGE_500_DEG:
      Serial.println("+- 500 deg/s");
      break;
    case MPU6050_RANGE_1000_DEG:
      Serial.println("+- 1000 deg/s");
      break;
    case MPU6050_RANGE_2000_DEG:
      Serial.println("+- 2000 deg/s");
      break;
    }
    mpu3.setFilterBandwidth(MPU6050_BAND_21_HZ);
    Serial.print("Filter bandwidth set to: ");
    switch (mpu1.getFilterBandwidth()) {
    case MPU6050_BAND_260_HZ:
      Serial.println("260 Hz");
      break;
    case MPU6050_BAND_184_HZ:
      Serial.println("184 Hz");
      break;
    case MPU6050_BAND_94_HZ:
      Serial.println("94 Hz");
      break;
    case MPU6050_BAND_44_HZ:
      Serial.println("44 Hz");
      break;
    case MPU6050_BAND_21_HZ:
      Serial.println("21 Hz");
      break;
    case MPU6050_BAND_10_HZ:
      Serial.println("10 Hz");
      break;
    case MPU6050_BAND_5_HZ:
      Serial.println("5 Hz");
      break;
    }

    /* Display some basic information on this sensor */
    tcaselect(0);
    displaySensorDetails(&mpu1);
    tcaselect(1);
    displaySensorDetails(&mpu2);
    tcaselect(2);
    displaySensorDetails(&mpu2);
    }

    void loop(void)
    {
    /* Get a new sensor event */
    sensors_event_t a, g, temp;
    tcaselect(0);
    mpu1.getEvent(&a, &g, &temp);
    /* Display the results (magnetic vector values are in micro-Tesla (uT)) */
    Serial.print("Sensor #1 - ");
    //Serial.print("X: "); Serial.print(event.magnetic.x); Serial.print(" ");
    //Serial.print("Y: "); Serial.print(event.magnetic.y); Serial.print(" ");
    //Serial.print("Z: "); Serial.print(event.magnetic.z); Serial.print(" ");Serial.println("uT");
    Serial.print("Acceleration X: ");
    Serial.print(a.acceleration.x);
    Serial.print(", Y: ");
    Serial.print(a.acceleration.y);
    Serial.print(", Z: ");
    Serial.print(a.acceleration.z);
    Serial.println(" m/s^2");

    tcaselect(2);
    mpu2.getEvent(&a, &g, &temp);
    /* Display the results (magnetic vector values are in micro-Tesla (uT)) */
    Serial.print("Sensor #2 - ");
    Serial.print("X: "); Serial.print(event.magnetic.x); Serial.print(" ");
    Serial.print("Y: "); Serial.print(event.magnetic.y); Serial.print(" ");
    Serial.print("Z: "); Serial.print(event.magnetic.z); Serial.print(" ");Serial.println("uT");
    Serial.print("Acceleration X: ");
    Serial.print(a.acceleration.x);
    Serial.print(", Y: ");
    Serial.print(a.acceleration.y);
    Serial.print(", Z: ");
    Serial.print(a.acceleration.z);
    Serial.println(" m/s^2");
    delay(500);
    }
In this configuration All of my mpu sensors are sending back unreasonable numbers for acceleration and temperature. Am I initializing my mpus correctly in my code?

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

body:
It seems like you would need to call `.begin()` on your `Adafruit_MPU6050` instances, [like the examples do][1].

So, following the pattern, in `setup()` you would need to:

```c++
 tcaselect(0);
 if (!mpu1.begin()) {
    Serial.println(F("Failed to find MPU6050 chip 1"));
    while (1) {
      delay(10);
    }
 }

 tcaselect(1);
 if (!mpu2.begin()) {
    Serial.println(F("Failed to find MPU6050 chip 2"));
    while (1) {
      delay(10);
    }
 }

 tcaselect(2);
 if (!mpu3.begin()) {
    Serial.println(F("Failed to find MPU6050 chip 3"));
    while (1) {
      delay(10);
    }
 }
```

I see you're removing some repetition with functions.  I'm guessing you just haven't gotten to doing that with the repeated `switch` statements for printing frequencies and such. You may want to put your `mcu1`/`mcu2`/`mcu3` into an array instead for similar reasons.

An array of `Adafruit_MPU6050`:

```c++
Adafruit_MPU6050 mpus[3];
```

The code for calling `begin()` could look something like:

```c++
size_t index = 0;
for (auto &an_mpu: mpus) {
  tcaselect(index);
  if (!an_mpu.begin()) {
    Serial.print(F("Failed to find MPU6050 chip, mpu["));
    Serial.print(index);
    Serial.println(']');
    Serial.println(F("Halting..."));
    while (1) {
      delay(10);
    }
  }

  ++index;
}
```

  [1]: https://github.com/adafruit/Adafruit_MPU6050/blob/2.0.5/examples/basic_readings/basic_readings.ino#L16


sender: user

sender: assistant

body:
You don't need the I2C multiplexors at all - I currently have seven MPU6050 modules being managed by one Teensy 3.5 chip.  Four MPU6050's are on one of the T3.5's I2C busses, and the remaining three are on another.  I could run them all from just one I2C bus, but I split them just for wiring convenience.  The 'trick' is to replace the I2C address of each MPU6050 in turn in the setup() routine, as shown by the code associated with the blog post referenced below

See [this post][1] and related ones on my blog site 'Paynter's Palace'.

  [1]: https://www.fpaynter.com/2020/07/replacing-hc-sro4-ultrasonic-sensors-with-vl53l0x-arrays-part-iv/

I've been using this technique for quite a while now, so let me know if you have any additional questions.

22 Sept 21 edit:

Here's the function that handles address initialization for the four MPU6050's on the Wire2 I2C bus:

    bool InitWire2Sensors()
    {
      delay(1000);
      Serial.printf("Initializing VL53L0X Sensor Array Elements on Wire2\n");
      bool retval = true;

      //Put all sensors in reset mode by pulling XSHUT low
      digitalWrite(LF_XSHUT_PIN, LOW);
      digitalWrite(LC_XSHUT_PIN, LOW);
      digitalWrite(LR_XSHUT_PIN, LOW);
      digitalWrite(Rear_XSHUT_PIN, LOW);

      //left-front
      //input w/o pullups sets line to high impedance so XSHUT pullup to 3.3V takes over
      pinMode(LF_XSHUT_PIN, INPUT);
      delay(10);

      if (!lidar_LF.init())
      {
        Serial.println("Failed to detect and initialize LF sensor!");
        retval = false;
      }
      else
      {
        Serial.printf("lidar_LF successfully initialized at %x\n", lidar_LF.getAddress());
        lidar_LF.setMeasurementTimingBudget(20000);
        lidar_LF.startContinuous();

        lidar_LF.setAddress(DEFAULT_VL53L0X_ADDR + 4);
        Serial.printf("lidar_LF. address is now 0x%x\n", lidar_LF.getAddress());
      }

      //now bring lidar_LC only out of reset and set it's address
      //input w/o pullups sets line to high impedance so XSHUT pullup to 3.3V takes over
      pinMode(LC_XSHUT_PIN, INPUT);
      delay(10);

      if (!lidar_LC.init())
      {
        Serial.println("Failed to detect and initialize LC sensor!");
        retval = false;
      }
      else
      {
        Serial.printf("lidar_LC successfully initialized at %x\n", lidar_LC.getAddress());
        lidar_LC.setMeasurementTimingBudget(20000);
        lidar_LC.startContinuous();

        lidar_LC.setAddress(DEFAULT_VL53L0X_ADDR + 5);
        Serial.printf("lidar_LC. address is now 0x%x\n", lidar_LC.getAddress());
      }

      //now bring lidar_LR only out of reset and set it's address
      //input w/o pullups sets line to high impedance so XSHUT pullup to 3.3V takes over
      pinMode(LR_XSHUT_PIN, INPUT);
      delay(10);

      if (!lidar_LR.init())
      {
        Serial.println("Failed to detect and initialize LR sensor!");
        retval = false;
      }
      else
      {
        Serial.printf("lidar_LR successfully initialized at %x\n", lidar_LR.getAddress());
        lidar_LR.setMeasurementTimingBudget(20000);
        lidar_LR.startContinuous();

        lidar_LR.setAddress(DEFAULT_VL53L0X_ADDR + 6);
        Serial.printf("lidar_LR. address is now 0x%x\n", lidar_LR.getAddress());
      }

      //now bring lidar_Rear only out of reset and set it's address
      //input w/o pullups sets line to high impedance so XSHUT pullup to 3.3V takes over
      pinMode(Rear_XSHUT_PIN, INPUT);
      delay(10);

      if (!lidar_Rear.init())
      {
        Serial.println("Failed to detect and initialize Rear sensor!");
        retval = false;
      }
      else
      {
        Serial.printf("lidar_Rear successfully initialized at %x\n", lidar_Rear.getAddress());
        lidar_Rear.setMeasurementTimingBudget(20000);
        lidar_Rear.startContinuous();

        lidar_Rear.setAddress(DEFAULT_VL53L0X_ADDR + 7);
        Serial.printf("lidar_Rear. address is now 0x%x\n", lidar_Rear.getAddress());
      }
      //input w/o pullups sets line to high impedance so XSHUT pullup to 3.3V takes over
      pinMode(LR_XSHUT_PIN, INPUT);
      delay(10);

      if (!lidar_LR.init())
      {
        Serial.println("Failed to detect and initialize LR sensor!");
        retval = false;
      }
      else
      {
        Serial.printf("lidar_LR successfully initialized at %x\n", lidar_LR.getAddress());
        lidar_LR.setMeasurementTimingBudget(20000);
        lidar_LR.startContinuous();

        lidar_LR.setAddress(DEFAULT_VL53L0X_ADDR + 2);
        Serial.printf("lidar_LR. address is now 0x%x\n", lidar_LR.getAddress());
      }

      return retval;
    }

Frank


message:
Arduino Due generate 400KHz sine waze

I new in Arduino environment.
Found some code generate sine wave but frequency between 14kHz to 84kHz. URL is [https://www.instructables.com/SineWave-Generator-for-Arduino-DUE/][1]

I need to generate sine waze 400kHz frequency.
Output should be on DAC0 or DAC1.

Any one can help to solve my problem.

  [1]: https://www.instructables.com/SineWave-Generator-for-Arduino-DUE/

body:
I think you may be overestimating the capabilities of the Due DAC. My understanding and experimentation is that waveform generating code (e.g., https://forum.arduino.cc/t/funkgenie-a-wavetable-based-function-generator/214938) can generate consistent output waves up to “a few kHz”. After which the wave shapes suffer from distortion.

If wave shape is not critical (though you did mention you specifically needed a sine wave) you may be able to push further using PWM outputs (e.g., https://forum.arduino.cc/t/due-high-frequency-waveform-up-too-500khz/423392).

However, I think you may need to design a suitable electronic circuit to generate the wave you’re seeking. That may be a topic for the Electrical Engineering stack exchange though? There is an introduction to wave generation circuit options going up into the RF frequencies [here][1].

  [1]: https://www.circuitbasics.com/sine-wave-generators/


body:
The Due's DAC can go up to, and I quote direct from the datasheet:

> Up to 350ksps conversion rate

That means you can set *up to* 350,000 data points on your waveform per second. With two datapoints (giving you a square wave or, more realistically, a waveform with a sharks fin shape) the maximum you could get is (350,000/2) 175kHz.

Given that you stipulate you want a sine wave you're going to need many more than just 2 data points in your waveform. Assuming a (reasonable) minimum of 32 data points (more would give a smoother waveform) you'd be looking at a maximum frequency of about 10kHz. Sacrificing waveform fidelity you could increase that, but the higher you go the less and less it resembles a sine wave.


message:
Setup Due counter

How do I setup a Due to count rising edges on a pin automatically without having to waste time on an ISR?

I have some wheel encoders, the simplist implementation is direction less where you only count rising edges.

I went the Due to count rising edges automatically and an ISR on a timer will periodically pole the current count

body:
You need to pick a timer that isn't being used for anything else and configure it as a simple counter with the clock source set to the external clock pin for that timer.

> At block level, input clock signals of each channel can either be connected to the external inputs TCLK0, TCLK1 or
TCLK2, or be connected to the internal I/O signals TIOA0, TIOA1 or TIOA2 for chaining by programming the TC
Block Mode Register (TC_BMR). See Figure 36-2.
Each channel can independently select an internal or external clock source for its counter:
> * External clock signals(1): XC0, XC1 or XC2
> * Internal clock signals: MCK/2, MCK/8, MCK/32, MCK/128, SLCK
> This selection is made by the TCCLKS bits in the TC Channel Mode Register (TC_CMR).

I am not personally familiar with the peripherals of the Due, but chapter 36 of the [SAM3X datasheet](https://ww1.microchip.com/downloads/en/devicedoc/atmel-11057-32-bit-cortex-m3-microcontroller-sam3x-sam3a_datasheet.pdf) details the workings and registers that you need to set.

Your encoder signal then connects to that clock input pin and the counter then counts every incoming pulse until you reset the count from your other periodic timer ISR.


message:
Timer to send a periodic pulse

I am looking for a very low power, small component (perhaps an arduino) that will send a pulse 3.3V logic HIGH pulse once every X seconds to another system.  I want to be able to configure X (maybe a trim pot or something) based on the use case the most rapid use case would be about once per second and the slowest would be once per hour. The duration of the pulse doesn't really matter much as long as it's one second or less.

Adafruit sells an item (PRODUCT ID: 3573) based on a Texas Instruments TPL5110 chip that sort of does this but it's a timed constant HIGH signal, not a pulse.  I am an electronics noob and am not sure what category of component this falls under but I have tried googling and reading tutorials on timers.

body:
As Edgar Bonet commented, you can do this using an [ATtiny85 IC in an 8-pin DIP package](https://uk.rs-online.com/web/p/microcontrollers/1331672) which is available for about $1 and can be programmed using the Arduino IDE.

You have to tell the Arduino software about the ATtiny85 by installing a "core" for it such as [Spence Konde's](https://github.com/SpenceKonde/ATTinyCore/blob/master/Installation.md)

You will need a device to transfer the program into the ATtiny85, either a $5-$15 [AVR programmer](https://coolcomponents.co.uk/products/pololu-usb-avr-programmer-v2-1) or something like an Arduino Uno using the [Arduino-as-ISP](https://www.arduino.cc/en/Tutorial/BuiltInExamples/ArduinoISP) sketch .

Writing the software will be extremely easy by Arduino standards.

One advantage of the ATtiny85 over the same sized NE555 is that the ATtiny85 needs no external components (resistors capacitors etc) and so is a lot simpler to use. You can run this ATtiny85 on a 3.3 Volt supply (anything from 2.7 → 5.5 V will work).

If you want an ATtiny85 on a pre-assembled PCB (like that Adafruit TPL5110 product), try a [Digispark](https://proto-pic.co.uk/product/digispark-microcontroller-board-usb/) or a $1 [Digispark clone](https://www.aliexpress.com/item/32891293434.html), it can be plugged directly into a USB port for programming with the Arduino IDE. I haven't tried running one on 3.3V but I suspect that should be possible by connecting the 3.3V supply to the "5V" pin to bypass the Digispark's 5V regulator.

---

See https://wokwi.com/arduino/projects/310458692893934146

[![Wokwi project][1]][1]

I was also able to run it on a cheap Digispark clone from a 3V3 supply

[![Digispark][2]][2]

The only advantage over a bare ATtiny85 is that you don't need any programming hardware, just a USB port on a PC.

  [1]: https://i.stack.imgur.com/mWEUf.png
  [2]: https://i.stack.imgur.com/Vfxg9.jpg


message:
Arduino, generating smaller frequency than 31Hz

I'm controlling a car instrument panel with Arduino using the tone() function, however with Arduino Uno's minimum 31Hz frequency I can only set the speedometer at ~12mph or more.  I'd like to be able to set the speed from 0, which would require around 10Hz I believe. Are there any code tricks I could use? Maybe I should use hardware timer, or a different board?

body:
For this, I would consider using Timer 1 in mode 14 (fast PWM, with TOP
value controlled by ICR1), with the prescaler set to 64. The timer would
then be clocked at 250 kHz, giving you the following specs:

* timer frequency: 250 kHz (time resolution = 4 µs)
* minimum frequency: 3.81 Hz (exact period = 218 µs = 262,144 ms)
* maximum frequency: 125 kHz (period = 8 µs)

As the time resolution is constant, the frequency resolution worsens as
you increase the frequency. At 400 Hz the resolution is about 0.16%, or
0.64 Hz.

This is not the only possible solution. Toggle mode would work also, and
also other prescaler values, which would give different frequency ranges
and resolutions.

Check the datasheet to see how to set the configuration bits (basically:
non-inverting PWM on either OC1A or OC1B, waveform generation mode = 14,
prescaler = 64). You may be able to find libraries to do this if you
prefer that approach, I have not checked this possibility.


message:
Mounting an Arduino inside a PC

I want to mount an [Arduino Pro Micro][1] inside my PC, hooked up to the PC's USB.

I don't want to have external cables for this, but have it neatly cabled inside.

My motherboard has USB connectors with 9 pins (5+5 grid, 10th pin key), like these:
[![motherboard][2]][2]

These connectors would take a cable that looks like this:

[![9pin cable][3]][3]

But how would I connect this to the Arduino that has Micro USB?

I've been looking everywhere, but 9-pin USB to USB Micro does not seem to exist?

The closest I could find is a cable that goes from USB micro to a 5-pin header:

[![5pin cable][4]][4]

What is the preferred way to hook up an Arduino Micro with internal cabling?

Why does the 9-pin to USB-micro not exist?

  [1]: https://wiki.keyestudio.com/Ks0249_keyestudio_PRO_MICRO_Development_Board
  [2]: https://i.stack.imgur.com/LGHlE.jpg
  [3]: https://i.stack.imgur.com/QehJo.png
  [4]: https://i.stack.imgur.com/qqPXH.png

body:
@Bram, @jsotola is highlighting in the comments that the example photo you show with a 9 pin keyed  two row connector has two usb cables connecting to it. USB connections often have four wires each. The standard wire color coding is:

[![usb wiring Colours][1]][1]
(Source [Wikipedia - USB][2])

Board manufacturers are often looking for a simple way to connect multiple panel mount USB ports to the PCB and this could have been a cheap and convenient way to connect two USB ports per pcb connector.

Some suggestions:

 - Research the specific motherboard online to see if a schematic or connector layout is available. It’s quite likely to be laid out like this:

[![enter image description here][3]][3]

 - Experiment by making your own [connector][4], and use a multimeter to figure out which are the power and which are the data wires.
 - If the old USB ports which used to connect to the PCB are still available, investigate further until you’re more confident about how they were wired.
 - An [adapter][4] may help you experiment further to understand the PCB connections further.

[![enter image description here][5]][5]

 - A [micro-USB breakout board][6] may help you experiment with connections on the Arduino side.
[![enter image description here][7]][7]

  [1]: https://i.stack.imgur.com/f1YTv.jpg
  [2]: https://en.wikipedia.org/wiki/USB?wprov=sfti1
  [3]: https://i.stack.imgur.com/QlwDj.jpg
  [4]: https://www.ebay.com.au/itm/Single-Double-Row-DuPont-2-54mm-Connector-Plug-Housing-Shell-1-10Pin-2-3-9Pin-/264226603708?mkcid=16&mkevt=1&_trksid=p2349624.m46890.l49286&mkrid=705-154756-20017-0
  [5]: https://i.stack.imgur.com/h41YI.jpg
  [6]: https://www.ebay.com.au/itm/USB-Type-B-Micro-B-Male-Plug-Receptacle-Breakout-Module-Board-for-/192267601843?mkcid=16&mkevt=1&_trksid=p2349624.m46890.l49286&mkrid=710-127635-2958-0
  [7]: https://i.stack.imgur.com/tHAEz.jpg


message:
how to detect when a transmitter is turned off?

Using the nrf24l01 wireless module I want to control a led with the sketch below.
The transmitter automatically sends data at intervals of one second continuously and when the receiver counter reaches 2, it turns on the LED at the desired time and then turns it off.
but what I want is when I turn off the power of the transmitter when 2 counts are detected from the transmitter, the led does not light up.

I want to turn the led on and off when I turn off the power of the transmitter after sending 2 signals from the transmitter.

Thank you for all the information you provide.

    #include "nRF24L01.h"
    #include "RF24.h"
    #include "SPI.h"
    int ReceivedMessage[1] = {000}; //  NRF24L01 tarafından alınan değeri saklamak için kullanılır
    RF24 radio(3, 4); //  NRF24L01 SPI pimleri. uno'daki Pin 8 ve 9
    const uint64_t pipe = 0xE6E6E6E6E6E6; // 2 NRF24L01 arasındaki iletişim için aynı olması gerekir

    int led = A7;

    bool flag = false;
    bool ledflag  = false;
    unsigned long  previous1 = 0;
    unsigned long  interval1 = 5000;

    unsigned long  previous2 = 0;
    unsigned long  interval2  = 2000;
    int button1PushCounter = 0;

    void setup () {

      radio.begin(); // NRF24L01'i başlatın

      radio.openReadingPipe(1, pipe); // NRF24L01'i almaya hazır hale getirin

      radio.startListening(); // Bilginin alınıp alınmadığını görmek için dinleyin

      Serial.begin(9600);

      pinMode(led, OUTPUT);

    }

    void loop () {

      unsigned long currentmillis = millis();
      while (radio.available())
      {
        radio.read(ReceivedMessage, 1); // NRF24L01'den bilgileri okuyun

        if (ReceivedMessage [0] == 111) //  switch'e basıldığını gösterir
        {

          button1PushCounter++;
          Serial.println( button1PushCounter);
          delay(700);
        }

        if ( button1PushCounter == 2) {

          flag = true;
          previous1 =  currentmillis;

        }

        if ( flag ) {
          if (currentmillis - previous1 >= interval1  ) {

            digitalWrite(led, HIGH);
            ledflag  = true;
            previous2 =  currentmillis;
            flag = false;
            button1PushCounter = 0;
          }
        }

        if ( ledflag && (currentmillis - previous2 >= interval2  )) {
          digitalWrite(led,  LOW);
          ledflag  = false;

        }
      }
    }

body:
I found solution as below:-

    if ( button1PushCounter == 3 ) {

      for (int i = 0; i < 5; i++)
      {
        delay(1000);
        Serial.println(i);
        a = HIGH;
      }
    }

    if ( a == HIGH ) {

      digitalWrite(led, HIGH);
      delay(1000);
      digitalWrite(led,  LOW);
      a = LOW;
      button1PushCounter = 0;
    }


message:
Leonardo with hm-10 doesn't work

I have a hm-10 module attached to Arduino Leonardo board, I'm using a bluetooth terminal app to send some text.

The problem is I can send data from the Serial monitor to my phone but when I send from my phone, there is no output in the serial monitor.

It works fine if I test it on Arduino Uno.
I'm struggling with something that should be simple.

Can someone please help me?

Here is my code:-

    #include <SoftwareSerial.h>

    SoftwareSerial BTSerial(4, 5);

    void setup(){
      Serial.begin(115200);
      Serial.println("Hello!");
      BTSerial.begin(115200);
    }

    void loop(){
      while (BTSerial.available()){
        byte data = BTSerial.read();
        Serial.write(data);
      }

      while (Serial.available()){
        byte data = Serial.read();
        BTSerial.write(data);
      }
    }

body:
I GOT IT!! It was problem with the pin settings.

According to SoftwareSerial library documentation, only pins 8,9,10,11,14,15,16 can be used for RX pin. But i used pin 4 for RX.


message:
Second I2C on Due RTClib, can't start

I am using SDA1, SCL1 for my DS3232 with RTClib on Due. It works on a Mega2560 on SDA, SCL.
I ran I2c_test with success after I inserted
#define Wire Wire1
However with ds3231.ino this define doesnot work. Looking at RTClib.cpp it looks like I can pass a parameter to Wire.begin(). I have tried sda1, scl1 and Wire1. They didnot work.
Thanks for the help.

body:
The unmodified [RTCLib][1] DS3231 sample code running on Arduino Due defaults to the *Wire* I2C connection on pins 20 SDA and 21 SCL.
[![Due connection via Wire I2C pins][2]][2]
To enable the same sketch to connect to a device connected to the *Wire1* I2C connection on pins 70 SDA1 and 71 SCL1, I changed line 333 of RTClib.h to reference &Wire1 rather than &Wire.
[![Photo of code snippet in RTCLib.h][3]][3]
[![Due connection via Wire1 I2C pins][4]][4]
Successful test output from the Wire1 connection is shown.
[![Serial Monitor Output][5]][5]

**Update:**
OP @Marlin Turbett pointed out that adding `#define Wire Wire1` to RTClib.h also works. I agree. The modification of line 333 of RTClib.h which I suggested originally is I think the minimal change to get the desired behaviour. But using substitution to achieve the same change also works. A global change across the whole library may be a bigger hammer than might be desirable.

#define substitution works in single compilation units, so the #define needs to be in the same compilation unit as the text to be overwritten. In this case in the library, not the sketch.

The technique of using #define directives to overwrite which *Wire* port is referenced in RTClib is used selectively by the library depending on arduino architecture (see RTClib.cpp lines 46-73, below).

    #include "RTClib.h"
    #if defined(__AVR__) && !defined(TWCR) && defined(USICR)
    #include <TinyWireM.h>
    #define Wire TinyWireM
    #else
    #include <Wire.h>
    #endif

    #ifdef __AVR__
    #include <avr/pgmspace.h>
    #elif defined(ESP8266)
    #include <pgmspace.h>
    #elif defined(ARDUINO_ARCH_SAMD)
    // nothing special needed
    #elif defined(ARDUINO_SAM_DUE)
    #define PROGMEM
    #define pgm_read_byte(addr) (*(const unsigned char *)(addr))
    #define Wire Wire1
    #endif

    #if (ARDUINO >= 100)
    #define _I2C_WRITE write ///< Modern I2C write
    #define _I2C_READ read   ///< Modern I2C read
    #else
    #include <WProgram.h>
    #define _I2C_WRITE send   ///< Legacy I2C write
    #define _I2C_READ receive ///< legacy I2C read
    #endif

I don't know why the library code at lines 60 to 64 (for ARDUINO_SAM_DUE) was not effective, and I hope to do some more testing. Maybe others here can shed some light?

**Update 2:** Noting the link from @Edgar Bonet in the comments to the new example sketch `customWire_DS3231onSAMD21.ino` in RTClib 1.14.1 which specifically caters for multiple i2c ports. Nice one.

  [1]: https://github.com/adafruit/RTClib
  [2]: https://i.stack.imgur.com/dgjO5.jpg
  [3]: https://i.stack.imgur.com/cwngk.png
  [4]: https://i.stack.imgur.com/yoXqX.jpg
  [5]: https://i.stack.imgur.com/5Zphg.png


message:
avrdude: stk500v2_ReceiveMessage(): timeout error for bluetooth arduino

I am trying to link the Bluetooth module to my arduino UNO in order to wirelessly program a robot. The only issue that I am having is that the bluetooth module does not seem to pick up the arduino.

Here is how the bluetooth module is wired up to my arduino:
[![enter image description here][1]][1]

The bluetooth module is paired to my PC via a bluetooth dongle. I know that the bluetooth module is working on port COM7. The LED then on the bluetooth module blinks quickly. After this I set the port to the correct port that the bluetooth module uses:

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

One thing that I found strange was that the name of the arduino board does not come up just like when I use a USB to upload the program.

When I open up the serial monitor the LED on the bluetooth module begins to blink more slowly possibly indicating it is connected. I afterwards try to send an AT command via the serial monitor to the arduino by typing in AT to the serial input at the top of the serial monitor and hitting enter and nothing happens. I then tried to send 3 different pieces of code separately to the arduino one at a time:

First code sample:

    void setup() {

     Serial.begin(9600);

    while (!Serial) {
       ; // wait for serial port to connect. Needed for native USB port only
     }

     Serial.println("ASCII Table ~ Character Map");
    }

    int thisByte = 33;

    void loop() {

     Serial.write(thisByte);

     Serial.print(", dec: ");
     Serial.print(thisByte);

     Serial.print(", hex: ");
     Serial.print(thisByte, HEX);

     Serial.print(", oct: ");
     Serial.print(thisByte, OCT);

     Serial.print(", bin: ");
     Serial.println(thisByte, BIN);

     if (thisByte == 126) {
       while (true) {
         continue;
       }
     }
     thisByte++;

    }

Second code sample:

    #include <SoftwareSerial.h>
    SoftwareSerial BTSerial (2,3);
    void setup() {
      // put your setup code here, to run once:
      Serial.begin(9600);
      Serial.println("Enter AT Commands");
      BTSerial.begin(9600);
    }

    void loop() {
      // put your main code here, to run repeatedly:
      if(BTSerial.available()){
        Serial.write(BTSerial.read());
      }
      if(Serial.available()){
        BTSerial.write(Serial.read());
      }
    }

Third code sample:

    char inputByte;
    void setup() {
     Serial.begin(9600);
     pinMode(13,OUTPUT);

    }

    void loop() {
    while(Serial.available()>0){
      inputByte= Serial.read();
      Serial.println(inputByte);
      if (inputByte=='Z'){
      digitalWrite(13,HIGH);
      }
      else if (inputByte=='z'){
      digitalWrite(13,LOW);
      }
      }
    }

(The following situation occurs for all 3 samples of code I copied from online). When I set the port to COM7 and then click upload to the board, the IDE says "Uploading" and the LED begins to blink more slowly just like as I was mentioning before with the serial monitor. After a while eventually the following error messages came up:

    avrdude: stk500v2_ReceiveMessage(): timeout
    avrdude: stk500v2_getsync(): timeout communicating with programmer

I looked online for answers. The internet suggested to use a larger baud rate so I switched it from 9600 to 57600 and also at the same time switch from Newline to Both NL and CR. Still nothing happened and I got the following error message. One final suggestion I saw on the internet was to put a resistor divider/voltage divider across the RX pin (I haven't done this as I don't see how this could make a difference, I could be wrong about it though and it could make the whole difference).

  [1]: https://i.stack.imgur.com/VOiJl.png
  [2]: https://i.stack.imgur.com/p2Fro.png

body:
The Bluetooth range is small so the robot can't be far from the computer for upload.

----------

To solve the reset for the Bluetooth you could add a reset button on the robot and use it while avrdude attempts to upload the sketch. Baud rate on HC-05 must be set to 115200 baud.

----------

As an alternative you could have USB connector on the robot. You can use a short USB extension cable as internal cable from the USB connector of the Arduino to the outer shell of the robot.


message:
What is the simplest way to emulate the original gameboy's cpu using Arduino?

My initial question assumes it is possible to emulate the original GameBoy system using an Arduino board.

Additional information in non-technical terms: I am looking to create an Arduino based device that accepts cartridges as input devices (in some cases they will also function as output devices) I am interested primarily in the Hexadecimal/pixel based "logic" which gameboy games uses to display game data.

What is the simplest way to emulate the original gameboy's hexadecimal based pixel logic to fetch, decode, and execute data using Arduino?

Before flagging this question, please comment so that I may clarify as this is a complex question to ask and I am willing to re word it as necessary.

body:
(Assembling an answer from the comments)

The consensus is that there is no "simple way to emulate the original gameboy cpu using Arduino". That a more powerful platform is required.

Multiple commenters expressed difficulty with the novel concept of "hexadecimal/pixel based logic". It is suggested that this concept may be without merit.


message:
Convert String to const unsigned char

String abc ="0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff";

    const unsigned char displaydata={reinterpret_cast<const unsigned char*>(abc.c_str())};

    display.drawBitmap(displaydata, startX, startY, bmpWidth, bmpHeight, GxEPD_WHITE);

**Get error: invalid conversion from 'const unsigned char' to 'unsigned char' [-fpermissive]***

**When I write like this**

    String abc ="0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff";

    display.drawBitmap(reinterpret_cast<const unsigned char*>(abc.c_str()), startX, startY, bmpWidth, bmpHeight, GxEPD_WHITE);

**No error but black screen no display image**

**When I write like this**

    const unsigned char displaydata[]={ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};

    display.drawBitmap(displaydata, startX, startY, bmpWidth, bmpHeight, GxEPD_WHITE);

**It is working**

The string data coming from the server is returning to me as stirng, I am trying to reflect it on the screen. I want to convert a string data to const unsigned char with code

So I'm trying to convert

body:
That string is literally the characters 0xff ... while the array is the bytes 0xff...

Where the string contains 4 bytes to say 0,x,f,f (followed by comma and space) the array will have 1 byte the 255 (and no need for a comma or space to delimit).

If you are looking to convert the text hex string to bytes, look at a combination of https://arduino.stackexchange.com/questions/39861/how-to-convert-an-hex-string-to-an-array-of-bytes and looping through the string.


message:
Why the unsigned long is overflowing?

I want to convert hour to seconds but unsigned long is overflowing, here's the code:

    #include <Wire.h>
    #include <DS3231.h>

    RTClib myRTC;
    unsigned long seconds;
    char timestr[9];

    void setup() {
      Serial.begin(250000);
      Wire.begin();
    }

    void loop() {
      DateTime now = myRTC.now();

      snprintf(timestr, 9, "d:d:d", now.hour(), now.minute(), now.second());
      seconds = (now.hour() * 3600);
      Serial.println(timestr);
      Serial.println(seconds);
      delay(100);
    }

And the console output is:

    16:33:36
    4294959360

Why is this happening?

body:
It's not the unsigned long that's overflowing but the calculation that you're assigning to it.

3600 is a signed integer (by default), and `now.hour()` is an unsigned byte. The unsigned byte gets promoted to match the "largest" type in the calculation - a signed integer - and then the calculation is performed, resulting in a signed integer.

That signed integer is then assigned to an unsigned long and, if the result is negative (as it may well be - 10*3600 > 32767) you end up with a massive number.

The simple "cure" is to ensure that one value in the calculation is an unsigned long. And the best way of doing that is to make your constant an unsigned long: by appending "UL" to it:

    seconds = (now.hour() * 3600UL);


message:
ESP32 AP Automatic Web Page

I've often encountered WiFi networks that require you to sign in through a web page that automatically opens after connecting to the access point, such as hotels. I'd like to implement something similar with an ESP32, where a web page opens automatically after connecting to the AP. Is this doable? This seems to be difficult to Google, because I just get a bunch of introductory tutorials on setting up an AP.

Here's some project context in case it helps. I'm making an IoT device that needs to connect to the user's WiFi network, so the user needs to specify the login credentials. The solution I'm trying to implement is having the ESP32 set up a temporary AP, where the user can connect to that and enter their home WiFi credentials. As it stands now, the user has to manually type in the IP address of the ESP32 after connecting to the AP, but it'd be much more user friendly if the web page opened automatically like hotel WiFi networks sometimes do.

I've tinkered with this [WiFi Manager][1] library that appears to do what I want, but I'd like to implement mine from scratch.

  [1]: https://github.com/zhouhan0126/WIFIMANAGER-ESP32

body:
Of course, as soon as I linked that WiFi Manager library in my question, I figured it out. The term I was missing was "captive portal" and I was able to figure it out from there. But I decided to post the question anyways, since it might help someone else stuck in the same situation.

Here's my understanding of how it works: when your device connects to a new network, it tries to ping a server to see whether it has internet access. With the ESP32, you can set up a DNS that redirects that ping to a web server running on the ESP32, which opens up the browser on the device.

I found this tutorial helpful for me to understand how that works, along with example code. This should be enough for me to get it working.

https://iotespresso.com/create-captive-portal-using-esp32/


message:
How can I make my code Thread-Safe?

So I made a post yesterday running into an issue on my ESP32 using both cores on the microcontroller (with wifi enabled, incase that is important).

I'm using both cores to control two Neopixel strips individually. I'm making a music visualizer, and I want the neopixels to react to the change in music as quickly as possible, so I felt like having one for every individual core was the best way for that to happen. The issue I am running into is that when audio is playing, the Music Visualizer function either in the primary core (Core 1), or secondary core (Core 0) will just completely freeze. I tried troubleshooting with some Serial.Print statements to understand where the code breaks, and it seems to happen around the **setPixelColor** command. I think my code is being thread locked, and I wanted to know what I could do to make it thread safe.

    void musicVisualizer(void) {
      middle_strip.clear();
      upper_strip.clear();

      middle_strip.show();
      upper_strip.show();

      // Add code to tell Core 0 to wait until LED's are cleared.
      while (vu_meter) {
        tweeter_prev = tweeter;
        if (analogRead(tweeter_sample) <= 490)
          tweeter_adc = 0;
        else {
          tweeter_adc = (analogRead(tweeter_sample) - 490);
          if (tweeter_adc < 0)
            tweeter_adc = 0; // Filter for changing reference voltage
          else if (tweeter_adc > MIDDLE_LED_COUNT)
            tweeter_adc = tweeter_prev; // Filter for if there are intermittent spikes in the adc
        }
        tweeter_filter.Filter(tweeter_adc);
        tweeter = tweeter_filter.Current() * 6;  // 6 scaler is for when Alexa is at Volume Level 4

        //    /* Changing LED Number to improve efficency when turning on LED's */
        //    if (tweeter > 43)
        //      LED_COUNT = 65;
        //    else if (tweeter > 21)
        //      LED_COUNT = 43;
        //    else if (tweeter <= 21)
        //      LED_COUNT = 21;

        /* LED's turning on and off in response to audio */
        if ((tweeter > tweeter_prev) && (tweeter <= MIDDLE_LED_COUNT)) {
          for (int x = tweeter_prev; x < tweeter; x++) {
            //        middle_strip.setPixelColor(x, color);
            middle_strip.setPixelColor(x, 0, 0, middle_strip.gamma32(brightness));
            middle_strip.show();
          }
        }
        else if (tweeter_prev > tweeter) {
          for (int x = tweeter_prev; x >= tweeter; x--) {
            middle_strip.setPixelColor(x, 0, 0, 0);
            middle_strip.show();
          }
        }
      }

      /* Leaving VU Meter, returning to current lamp color set */
      if (led_on) {
        if (!color_white) {
          for (int i = 0; i < LOWER_LED_COUNT; i++) {
            lower_strip.setPixelColor(i, color);
            lower_strip.show();
          }
          for (int i = 0; i < MIDDLE_LED_COUNT; i++) {
            middle_strip.setPixelColor(i, color);
            middle_strip.show();
          }
          for (int i = 0; i < UPPER_LED_COUNT; i++) {
            upper_strip.setPixelColor(i, color);
            upper_strip.show();
          }
        }
        else {
          for (int i = 0; i < LOWER_LED_COUNT; i++) {
            lower_strip.setPixelColor(i, 0, 0, 0, lower_strip.gamma32(brightness));
            lower_strip.show();
          }
          for (int i = 0; i < MIDDLE_LED_COUNT; i++) {
            middle_strip.setPixelColor(i, 0, 0, 0, middle_strip.gamma32(brightness));
            middle_strip.show();
          }
          for (int i = 0; i < UPPER_LED_COUNT; i++) {
            upper_strip.setPixelColor(i, 0, 0, 0, upper_strip.gamma32(brightness));
            upper_strip.show();
          }
        }
      }
      else {
        upper_strip.clear();
        middle_strip.clear();
        lower_strip.clear();

        upper_strip.show();
        middle_strip.show();
        lower_strip.show();
      }
    }

    void vu_meter_sub(void * parameter) {
      while (true) {
        esp_task_wdt_init(30, false);
        if (vu_meter) {
          lower_strip.clear();
          lower_strip.show();
          while (vu_meter) {
            sub_prev = sub;
            sub_adc = analogRead(sub_sample);
            if (sub_adc > LOWER_LED_COUNT)
              sub_adc = LOWER_LED_COUNT-1;
            sub_filter.Filter(sub_adc);
            sub = sub_filter.Current();
            //        if (sub < 0)
            //          sub = 0;
            Serial.println(sub);
            if ((sub > sub_prev) && (sub <= LOWER_LED_COUNT)) {
              for (int x = sub_prev; x < sub; x++) {
                //            lower_strip.setPixelColor(x, color);
                lower_strip.setPixelColor(x, 0, lower_strip.gamma32(brightness), 0);
                lower_strip.show();
              }
            }
            else if (sub_prev > sub) {
              for (int x = sub_prev; x >= sub; x--) {
                lower_strip.setPixelColor(x, 0, 0, 0);
                lower_strip.show();
              }
            }
            Blynk.run();
          }
        }
      }
    }

body:
I am not sure this is related to thread-safety, but you should be aware
that `strip.show()` is a slow function that blocks while the data is
being sent. `setPixelColor()`, in contrast, is fast, as it only updates
the data in memory.

I suggest you modify `musicVisualizer()` in such a way that it only
`show()`s each strip once. The bulk of the function should be about
computing the colors you want and setting them with `setPixelColor()`.
Then, at the very end of the function, `show()` the three strips.


message:
I need help producing 2 pwm signals

My project is to use an Arduino to control two solenoid valves with PWM and receive an input signal from a sensor as feedback.

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

The valves direct the flow of water which cause a hydraulic actuator to move which is detected by an LVDT sensor.

What I want my program to do is to allow me to set a desired displacement as a goal which causes the Arduino to dynamically change the duty cycle of the pwm signal based off of the feedback input the Arduino receives. I am going to implement a PID to control it.

The circuit consist of the Arduino sending PWM signals to two logic level NPN mosfets to control the solenoids that are powered by 2 external 12V sources.

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

[![enter image description here][3]][3]

What I specifically need help with is how to write the part of the program that will let me produce 2 PWM signals that will allow me to change the frequency of the pwm waves so that the solenoids have enough time to switch and then also the ability to set the duty cycle.

I am a total novice programmer and its my first time working with electronics. I'm just hoping someone can point me in the right direction.

  [1]: https://i.stack.imgur.com/LH76m.jpg
  [2]: https://i.stack.imgur.com/CT8QG.jpg
  [3]: https://i.stack.imgur.com/n6X9D.jpg

body:
You can try to use my [**AVR_Slow_PWM** Library](https://github.com/khoih-prog/AVR_Slow_PWM), which can provide these following features and generate 2 independent PWM signals to any GPIO pin. Certainly only if your hardware design can correctly use PWM signals.

>This library enables you to use ISR-based PWM channels on AVR-based boards, such as Mega-2560, UNO,Nano, Leonardo, etc., using AVR core to create and output PWM any GPIO pin. Because this library doesn't use the powerful purely hardware-controlled PWM with many limitations, the maximum PWM frequency is currently limited at 500Hz, which is still suitable for many real-life applications


body:
If you only need two PWM pins, I suggest using hardware PWM with
Timer 1. The [Timer 1][t1] library makes the process quite easy. It
supports frequencies from 0.12 Hz up to a few MHz, although the
resolution degrades above 7.8 kHz.

Compared to an interrupt-based solution, hardware PWM has less jitter
and it does not consume CPU cycles. The drawback is that you will be
limited to 2 channels operating at the same frequency, but this
doesn't seem to be an issue for your project.

[t1]: https://github.com/PaulStoffregen/TimerOne


body:
Tacking on this as a belated observation more than anything else.

Since there is no indication of an accumulator on the hydraulic circuit and the two valves are working in opposition, it might be necessary to maintain both complementary PWM ratios and consistent relative phase.

The TimerOne library appears- by eye- to maintain a consistent relative phase. The AVR_Slow_PWM library definitely doesn't.

If it is /not/ necessary to apply an offset to the PWM edges to accommodate the valves having different open and close times then it might be easiest to simply change the switching sense of one of the FETs with both driven from the same PWM signal (i.e. when one sees 75% on, the other sees 75% off).

If it /is/ necessary to apply an offset then it might end up being best to manually code something in a timer interrupt handler, particularly since I am told that typical valves should operate at about 10Hz but not much faster: this eliminates most of the standard PWM libraries.


message:
Measure voltage in 14 points 0 - 60 volts (14s LiPo battery) with single ADC

I wish to measure 14S battery voltage on each cell with single ADC.
I guess I need some ADC built-in or external (I2C), voltage divider and switch chip that will allow me to select one of 14 pins to measure.

Am I correct?

Could you advice what switch chip should I use?

or Should I build that curtuit myself with 2 74HC595 and mosfets? (not sure if that will ever work)

body:
I would do it manually (but then I am a bit sadistic like that).

The circuit for one cell is pretty simple, and you just need to replicate it 14 times. A P+N pair of MOSFETs to switch a battery channel on and off, and a pair of resistors to make a voltage divider. You can keep the "lower" of the resistors common between all channels if you like to reduce the number of components and complexity, but once you have 14 channels the complexity will become pretty silly anyway.  Here's an example with just 3 channels:

<!-- 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/49hCQ.png)

<!-- End schematic -->

You would need to size RA|RL, RB|RL and RC|RL (etc) accordingly to get the right voltage ranges for the ADC input, and keep the output impedance low enough (<10k) for the ADC to handle it properly. You may want a couple of different load resistors (RL) for different groups of cells.

All the N-channel MOSFETs could be replaced by a 4-to-16 decoder with open-collector outputs (such as, if you can get it, the 74xx159), which would also protect against switching on multiple channels at once, which you *never* want to do.

Note that this arrangement gives you the voltage of the first cell, the voltage of the first two cells, the voltage of the first three cells, etc. To get the voltage of just the third cell (for example) you will need to subtract the voltage of the lower cells.


message:
How to power ESP32 with 230V AC

I want to power ESP32 with 230V AC and I don’t know how to do it. The requirement is that it must never overheat. What components should i use? The ESP will be in small space with no airflow. Will it be even possible?

body:
The folks over at [Random Nerd Tutorials][1] offer a solution for this exact scenario using a [HLK-PM03][2] Hi-Link 100-240V AC to 3.3V 1A DC converter. They add electrical and thermal fuses to mitigate some of the possible failure modes of over-temperature or over-current.

The specifications of the HLK-PM03 are [here][3]. I suspect there will be a few alternatives available that do a similar function.

My suggestion is to be hyper-aware of the safety issues of dealing with mains power, and to be realistic about your own capabilities.

  [1]: https://randomnerdtutorials.com/esp8266-hi-link-hlk-pm03/
  [2]: https://makeradvisor.com/tools/hi-link-hlk-pm03/
  [3]: http://www.hlktech.net/product_detail.php?ProId=59


message:
Serial Monitor in Arduino works, but other Serial Terminal work only one way

I have a Arduino code working on a Adafruit Feather STM32F405 Express, and as long as I test it with Arduino serial Monitor, everything works perfect. As I want to use a serial terminal (a C# application, or the "Terminal Br@y++") through the same COM port, then I can write my commands, there are executed (output pins send expected signal), but I don't received the serial feedback.

My Arduino code :

    void setup() {
      Serial.begin(115200); // initialise USB Serial Port
      pinMode(pumpP, OUTPUT);  // Pump Pin is an output
    }
    void loop() {
        if (Serial.available() > 0) {
          command = Serial.readStringUntil('\n');
        }
        if (command == "do-it"){
            digitalWrite(5, HIGH);
            Serial.println("did it!");
        }
    }

In my Arduino Serial Monitor, I write "do-it", and I recieved "did it!" and I can see the Pin 5 changing level.
In all serial application I could use, I can see the pin 5 changing level, but not the "did it!".

I configured Arduino as described on this Adafruit page :
https://learn.adafruit.com/adafruit-stm32f405-feather-express/arduino-ide-setup [ *summary: use STM32F4 library, board number = "Adafruit Feather STM32F405", USB support = "CDC ( Generic Serial supercedes USART)", upload method = "STM32CubeProgrammer (DFU)"* ]
And I connect the DFU pin to 3,3V during upload, and reset the board after it.

The worst in this story, is that at first time, it worked OK. Since a week or two, I don't get it to work again.

body:
Thank you @Majenko, you gave the solution :
I checked the box "RTS/CTS" in the "handschake" section of Terminal by Bray, and I got all my serial message back from the STM32.

I guess this is a common think on more that stm32?
how did you know, is that somewhere written in Arduino documentation?

for people like me who do not know what is RTS/CTS, here you are: http://www.brainboxes.com/faq/items/what-is-rts--cts-hardware-flow-control-
or not so straight-forward https://en.wikipedia.org/wiki/RS-232#RTS,_CTS,_and_RTR

Funny to figure out that this "5 pin communication" is virtualise in USB.

@Majenko: if you want to "own" the solution, I let you do write it yourself, I will set your answer as solution.


message:
NodeMCU with a 5V latching relay - LOW triggers relay

I am going to connect NodeMCU to a latching relay board like tis one (4 channel version): [LINK][1]

Both MCU board and relay board will be powered from the same 5V voltage regulator.

Now I have two problems to solve:

**Problem 1** - logic levels

NodeMCU logic level is 3.3V and relays board works in 5V levels.
I can either use logic level converters or simple transoptors. Because I am going to attach NodeMCU to a custom PCB, I think transoptors will be simpler to solder.

**Problem 2** - relay triggers with low pulse on the control pin

This relay boards works like this: every time the channel pin (T1 - T4) is connected to ground for few miliseconds - the relay flips to other state.
Here is the question: **when the MCU board resets/reboots on power cycle, how do I ensure that the control pins are HIGH from the beginning?** If they are not, the relay can flip randomly before my program starts and I will not know the initial state of relay.

What would be the best approch here ?

  [1]: https://www.wish.com/product/1pc-5v-12v-flip-flop-latch-relay-module-bistable-self-lock-io25c04-5ddc9180e799ac03db9d54d3?hide_login_modal=true&share=web

body:
Since ports commonly are configured as inputs at reset, you will need to add a pull-up resistor.

Then write your setup so that the pin is high before switching to output mode.

**EDIT:**

Some microcontrollers have internal pull-ups, that are even activated at reset, see the specific data sheet. (_Thanks, Juraj._ I don't know NodeMCU enough to go in details. Anyway, my answer might apply to other controllers and other loads, too.)

The value of the pull-up can be determined by the maximum input current for the relay module (or your adapting circuitry) and the respective voltages. To be sure, make it a bit smaller, for example to the next E-series value. Just an example: minimum supply voltage is 3.15V (3V minus 5%), the maximum input voltage to detect "high" is 2.4V and maximum input current is 10 µA. Then the resistor will need to be at most Rmax = (Vdd_min - Vin_max) / Iin_max = (3.15V - 2.4V) / 10 µA = 75kOhm. This value is part of the E24 series, but is can be 68kOhm that is in the E6 series.

However, it [seems as if the circuit of the modules contains a simple PNP BJT][1], a pull-up will not work here, because the input needs to be pulled up to the supply voltage of the module. You need a level converter, this could be a simple transistor. How to design that circuit, is another issue. There are lots of information in the web how to do this.

  [1]: https://arduinodiy.wordpress.com/2018/08/07/re-inverting-an-inverting-relay/


message:
Use and definition of a destructor class

I created a class for TFT buttons and messages when using a Wemos 2.4 tft touch display.

In a code I use about 12 buttons (3 different screens with 4 buttons in each screen ), for example in my home control code "Main Screen" has `Lights`, `Windows` `Alarms`, `Temperatures`, and each screen below has set of others.

Since button's life expectancy is only for current screen (also in `loop()` since it monitor press at defined location), and each button take no little resources as show below in lib's `.h` file (other class with touch function are not show here), I would like to know how to create a destructor to free up space, since main resources are used in `MessageTFT` class.

    #ifndef TFT_GUI_h
    #define TFT_GUI_h

    #include <SPI.h>
    #include <Adafruit_GFX.h>
    #include <Adafruit_ILI9341.h>
    #include <XPT2046_Touchscreen.h>

    extern XPT2046_Touchscreen ts; /* Touch screen */
    extern Adafruit_ILI9341 tft;   /* Graphics */

    const uint8_t _pos_corr_factor[3] = {3, 6, 9}; /* Center text inside a box */
    class MessageTFT
    {
    public:
      uint8_t a, b;
      int xc, yc;
      uint8_t txt_size = 1;
      uint8_t screen_rotation = 0;
      uint8_t border_thickness = 1;
      uint16_t face_color = ILI9341_GREEN;
      uint16_t border_color = ILI9341_RED;
      uint16_t txt_color = ILI9341_BLACK;

      char txt_buf[30];
      bool roundRect = false;

    public:
      MessageTFT(Adafruit_ILI9341 &_tft);
      void drawMSG();
      void text(char *txt);
    private:
      uint8_t _radius = 15;

    private:
      void _drawFace();
      void _drawBorder();
      void _put_text();
    };
    #endif

body:
Destructors, despite their name, are not used to destroy the object. They are, instead, a "hook" that is called *when* the object is destroyed. Much like the "constructor" is called *when* the object is created - it doesn't *do* the creating.

A destructor is intended to "clean up" an object before it is deleted. That usually entails freeing any memory allocated at runtime (through `malloc()`, `new`, etc) by the object.

Since you don't do anything at runtime that needs to be cleaned up there is nothing for your destructor to do. All your variables are simple statically allocated memory as part of the object istelf, so those automatically get destroyed when the object is destroyed.

You can think of it as crushing a car. The seats, engine and steering wheel all get crushed without you having to worry about it. But first you want to take the dog out of the boot - you *really* don't want him in there when the car gets crushed, it'll get really really messy and the dog will be lost forever ... :(


message:
Convert float to int error

I am trying to convert 1.06 to 106 by multiplying by 100 but the answer comes 105, I do not know why. Variable ver can be any decimal in this format x.xx

    float ver = 1.06;
    int vers = ver * 100;
    vm[0] = (vers / 100U) % 10;
    vm[1] = (vers / 10U) % 10;
    vm[2] = (vers / 1U) % 10;
    Serial.println(vers);

Could  you let me know what I am doing wrong or maybe I have to do something else.

body:
1.06 is not a float. The closest float is 1.059999942779541015625. If
you multiply that by 100 you get a number that, again, is not a float.
Rounding to the nearest float yields 105.99999237060546875, which is the
result of the expression `ver * 100`, and just one [ULP][] short of 106.
Yes, floating point computations do quite usually involve rounding
steps.

Casting to an `int` implicitly rounds towards zero, and you get 105,
which is the correct result. Correct according to the rules of IEEE 754
arithmetics.

You may want to `round()` to the nearest integer before the cast.

> Variable ver can be any decimal in this format x.xx

No, a `float` cannot be “any decimal” in this format. Floats are stored
in binary, and most decimal numbers (numbers that can be written with a
finite number of decimal digits) cannot be written in binary with a
finite number of bits.

Except for a few values (namely the multiples of 0.25), `ver` can only
store an _approximation_ of the decimal number.

[ULP]: https://en.wikipedia.org/wiki/Unit_in_the_last_place


message:
Delay() and millis() functions don't work in cpp external files

I'm currently facing an issue using **delay()** and **millis()** functions in an external cpp file.
The issue is that when I used delay() in my main program (meaning .ino file) it works well but when I call the same function in an external cpp file, I'm stuck in the delay function. Concerning the setup, the .hpp linked to the used cpp is well included in the .ino file and the librairy Arduino.h is included in my cpp. I also tried to replace delay by a loop using millis but the value returned by millis is always 0.
I'm using an Arduino mega2560 and a water level sensor in the follwing example. The Arduino IDE version is 1.8.16.

Here is an extract from my ino file:

    #include <Arduino.h>
    #include "DS3231.h"
    #include "MyGardenClock.hpp"
    #include "sensors.hpp"
    #include <LiquidCrystal.h>
    #include "Keypad.h"
    #include <Wire.h>

    ///Time object creation
    DS3231 clock; //Clock object -> contains basic Real Time Clock functions
    RTCDateTime dt; //Struct from DS3231 lib - contains date and time
    mG_RTC myClock; //Object that contains specific clock functions to my project like printing date and time on the lcd...

    ///LCD object creation
    //--Pin allocation
    const int rs = 2, en = 1, d4 = 4, d5 = 7, d6 = 8, d7 = 10;
    //--LCD dynamic object creation
    LiquidCrystal* pLCD = new LiquidCrystal(rs, en, d4, d5, d6, d7);

    ///Keypad parametrization and object creation
    //Define col nb and row nb
    const byte ROWS = 4; //four rows
    const byte COLS = 4; //four columns
    //define the cymbols on the buttons of the keypads
    char hexaKeys[ROWS][COLS] = {
      {'1','2','3','A'},
      {'4','5','6','B'},
      {'7','8','9','C'},
      {'*','0','#','D'}
    };
    byte rowPins[ROWS] = {52, 50, 48, 46}; //connect to the row pinouts of the keypad
    byte colPins[COLS] = {44, 42, 40, 38}; //connect to the column pinouts of the keypad
    //Keypad dynamic object creation
    Keypad* pKpd = new Keypad(makeKeymap(hexaKeys),rowPins,colPins,ROWS,COLS);

    ///Sensors object creation
    //WaterLvl Sensors
    //--Pin allocation
    const int WtrLvlAnalogPin = 8; //pin used to read value from water lvl sensor
    const int WtrLvlPowerPin = 35; //pin used to power the sensor before reading a value
    //--WaterLvl dynamic object creation
    Water_Lvl_Sensor* pWtrLvlSens = new Water_Lvl_Sensor(WtrLvlAnalogPin,WtrLvlPowerPin); //contains the delay and millis functions that don't work

    /////////// TEST FUNCTIONS ///////////
    void testLCD_Kpd(Keypad*,LiquidCrystal*); //test lcd and keypad
    void testWtrLvlSens(Water_Lvl_Sensor*,LiquidCrystal*); //test water lvl sensor

    void setup()
    {
        Serial.begin(9600);
        pLCD->begin(16,2);
        testLCD_Kpd(pKpd,pLCD);
        testWtrLvlSens(pWtrLvlSens,pLCD);

    }

    void loop()
    {

    }
    ////////////////////// TEST FUNCTIONS ///////////////////////////
    void testLCD_Kpd(Keypad* pKpd, LiquidCrystal* pLCD)
    {
       char test;
       test ='i';

       pLCD->print("Hello");
       do
       {
        test = pKpd->waitForKey();
       }while(test=='i');
       pLCD->clear();
       delay(3000); //This one work well
       pLCD->print("test = ");
       pLCD->print(test);

    }

    void testWtrLvlSens(Water_Lvl_Sensor* pWLS,LiquidCrystal* plcd)
    {
      int wtrLvl;
      wtrLvl = pWLS->getCurrentWaterLvlValue();
      plcd->setCursor(0,1);
      plcd->print("wtrLvl = ");
      plcd->print(wtrLvl);

    }

Here is an extract from my cpp file:

    #include <Arduino.h>
    #include "sensors.hpp"

    /********************************************
    *   CLASS WATER LvL SENSOR DESCRIPTION      *
    ********************************************/
    ///Constructor
    //-- Assign pin number (analog & digital)
    //-- Define pinMode for VCC + set to low
    //-- read and store actual waterLevelValue as initial val
    Water_Lvl_Sensor::Water_Lvl_Sensor(int anPinNb, int DigPinNb)
    {
      //Variable used for millis
      unsigned long prevTime;
      unsigned long currentTime;
      const unsigned long delayTime = 100;

      Serial.begin(9600); //to debug

      //Assign analog and digital pin numbers
      analogPinNumber = anPinNb;
      VCC_digitalPinNumber = DigPinNb;
      pinMode(VCC_digitalPinNumber, OUTPUT); //Digital pin to power the sensor
      digitalWrite(VCC_digitalPinNumber,HIGH);//Turn sensor ON before reading initial value

      //delay(100); //not working ???
      prevTime = millis(); //get and store actual time
      do
      {
        currentTime = millis(); //get actual time
        Serial.println(currentTime); //print actual time (debug only)
      }while(currentTime<(prevTime+delayTime)); //while time spent < 100

      currentValue = analogRead(analogPinNumber); //read analog value

      digitalWrite(VCC_digitalPinNumber,LOW); //turn sensor OFF
      historyValue = currentValue; //init history val
      minValue = 0; //default value - sensor dry
      maxValue = 520; //default value - sensor under water
    }

Does anyone has a solution?

I hope I've given enough details. If not, please feel free to ask.

Thanks!

body:
The Arduino framework does some initializing for you before going into `setup()` and `loop()`, for example configuring Timer0 correctly for `millis()`, `delay()` and siblings. This is done in the `main()` function, which then after the first initializing calls `setup()` and `loop()`.

But the creation of globally defined objects (and thus the execution of their constructors) is done even before the `main()` function. At that time neither `millis()`, nor `delay()` will work, since the hardware Timer0 is needed to be configured correctly for them to work. The hardware timer generates interrupts with a specific frequency and in the corresponding ISR (Interrupt Service Routine) the variable for `millis()` is incremented. If the Timer0 isn't configured, it's interrupt cannot trigger and thus `millis()` will stay zero. So you cannot do all that in the constructor of the object, or you always need to create the object in `setup()` or `loop()`.

For this very reason most hardware related Arduino libraries use a `.begin()` method to initialize the hardware related stuff. That function can be called on the global object in the `setup()` function, when everything else is already configured correctly.

**What to do now?** Create a `.begin()` method for your class. Move all the code from the constructor (except for the pin number assignment) into this `.begin()` function. And then call that function in `setup()`.


message:
How do I find out the maximum current through VIN on a NodeMCU board?

I read this answer https://arduino.stackexchange.com/a/51878 to a different, but related question. It seems like VIN on the NodeMCU is directly or via diode connected to the USB connector.

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

Image source: https://arduino.stackexchange.com/a/76119

I'm going to run my NodeMCU with a 5 V power supply connected to the USB connector. And I also need approximately 5 V for another part. So I was thinking of connecting it to VIN of the NodeMCU. So I don't want to power the NodeMCU from VIN, but I want to draw power from VIN for another part.

Is that a bad move or perfectly fine? And if it's okay, how do I find out the maximum current? Because I think the line from USB connector to VIN has some limits, so to not damage the board?

body:
Just found at least a partial answer in this answer https://arduino.stackexchange.com/a/61030 to a different question:

> The component that blew up is a diode. It is designed to protect the USB from voltage being injected into the board. That diode can handle an absolute maximum of 1A. (...) the ESP8266 itself can take more than half that 1A power budget when communicating.

That sounds to me that beginning at about 500 mA, I will risk damaging the NodeMCU if I use VIN as a power supply. So to play it safe, I should probably stay below 250 mA...? Just a guess though. Not a perfect answer yet.


body:
You cannot power items from the VIN pin of the NodeMCU V3.

The power circuit is 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/wXlJs.png)

<!-- End schematic -->

As you can see no current can flow out of the VIN pin because of diode D2.

You could, though, draw current out of the VU pin, though (situated at the top left of the board when the text is normally oriented) which is directly connected to the USB port's 5V pin.  How much current can you draw? Well, there's nothing in the circuit to limit it, so whatever the USB port that the board is connected to will provide (less enough to run the ESP8266 module).

If you want to draw 1A through the VU pin and the power supply is rated for 2A there should be no problem. The traces for the VU pin are *reasonably* chunky.

A better solution though would be to power the NodeMCU board and your external components through separate power feeds from the power supply - that way there can be no interference from the board.


message:
Where are source files for Due?

Where are the source files containing the definitions and the HAL functions located for the Due?

I am trying to do CMSIS programming.

body: The Arduino Core for supporting Arduino Due is called ArduinoCore-Sam, which can be found at https://github.com/arduino/ArduinoCore-sam, inside the `system` directory, you will find the CMSIS device driver.


message:
Trying to program a Led Counter Want a Led to flash every 5 minutes however it flashes twice every second (Noob)

Heres the code i've Wrote i feel like the issue lies in how ive used the if statement

    int ledPinS = 13; //Classifies pin 13 as Connected to an LED
                    //Flashes every second
    int ledPinM = 12; //Classifies pin 13 as Connected to an LED
                    //Flashes every minuite

    byte seconds;

    byte minutes;

      void setup() {
       pinMode(ledPinS, OUTPUT);
       digitalWrite(ledPinS, LOW);
       pinMode(ledPinM, OUTPUT);
       digitalWrite(ledPinM, LOW);
      }

        void loop() {
         while (seconds<=59){//flash every second and reset when Seconds =59
         delay(900);
         digitalWrite(ledPinS,HIGH);
         delay(100);
         digitalWrite(ledPinS,LOW);
         seconds++;
        }
     delay(200);   // flash ledPin M Once when Seconds = 59
     digitalWrite(ledPinM,HIGH);
     delay(100);
     digitalWrite(ledPinM,LOW);
     seconds = 0;
     minutes++; // add a minute
     if(minutes=5){ // if minutes = 5 flash ledPinM twice and reset
              delay(200);
            digitalWrite(ledPinM,HIGH);
            delay(100);
            digitalWrite(ledPinM,LOW);
            delay(200);
            digitalWrite(ledPinM,HIGH);
            delay(100);
            digitalWrite(ledPinM,LOW);
            minutes = 0;
        }
    }

Any Help would be Appreciated.

body:
Although your code is formatted horribly, it does appear to be mostly correct.

I also  recommend making your pin numbers "const int". This tells the compiler that they cannot be changed. Otherwise you could change those values in your code accidentally.

You also have un-initialized variables. Best practice would be to declare and initialise them at the same time. E.g.

    byte seconds = 0;

Props for adding comments, though. Well done there.

You need an extra equals sign in your if statement.

    if (minutes = 5) {

should be

    if (minutes == 5) {

Classic mistake. We've all done it. You are assigning the value of 5 to minutes instead of checking for equality. This will always return true.


message:
How to save sensor value in EEPROM? (ESP8266)?

I would like to save the height of a tank in case of power outage with EEPROM and every time I reboot the board. However, I could not do so after using EEPROM.commit() , EEPROM.get and EEPROM.put as the reading of the height tank changes every time I tried to reboot it . Am I using it wrongly?

I used EEPROM.get , EEPROM.put , EEPROM.commit in the void setup section so that it will save the data during boot up. However, the tank height just change whenever I changed to a different tank with different height after boot up.

How could I recalibrate the height of the tank if I would like to change to another tank one day, can I just click the RST button on the ESP8266 board?

Thank you

```
#include <LiquidCrystal_I2C.h>  //1602 LCD library
#include <Wire.h>
#include <EEPROM.h>
#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>  //NodeMCU ESP8266 library
#include <BlynkSimpleEsp8266.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);

WidgetLED led1(V2);

char auth[] = ""; //Enter your Auth token
char ssid[] = ""; //Enter your WIFI name
char pass[] = ""; //Enter your WIFI password

BlynkTimer timer;
bool pinValue = 1;

long duration;
int distance;
int percentage;
int addr=0;
float tankheight, val;

#define trig D7
#define echo D8
#define relay D5

void setup() {
  Serial.begin(9600);
  EEPROM.begin(512);
  pinMode(trig, OUTPUT);
  pinMode(echo, INPUT);
  pinMode(relay, OUTPUT);
  Wire.begin(D2, D1);
  lcd.init();
  lcd.backlight();
  Blynk.begin(auth, ssid, pass);
  digitalWrite(trig, LOW);
  delayMicroseconds(4);
  digitalWrite(trig, HIGH);
  delayMicroseconds(10);
  digitalWrite(trig, LOW);
  duration = pulseIn(echo, HIGH);
  tankheight = duration * 0.034 / 2;
  Serial.print("Tank height");
  Serial.print(tankheight);
  EEPROM.put(addr, tankheight);
  EEPROM.commit();
  val=EEPROM.get(addr, tankheight);
  Serial.print("Addr");
  Serial.print(val);
  timer.setInterval(1L, Wlevel);
  digitalWrite(relay, HIGH);
}

BLYNK_CONNECTED(){
  Blynk.syncAll();

  }

BLYNK_WRITE(V0) {
  pinValue = param.asInt();

}

void loop() {
  Blynk.run();
  timer.run();
  WiFi.setSleepMode(WIFI_NONE_SLEEP);

}

void Wlevel(){  // Initialize detecting water level and relay)
  {
  digitalWrite(trig, LOW);
  delayMicroseconds(4);
  digitalWrite(trig, HIGH);
  delayMicroseconds(10);
  digitalWrite(trig, LOW);
  duration = pulseIn(echo, HIGH);
  distance = duration * 0.034 / 2;
  percentage= map(distance,val,10 ,0, 100);

  Blynk.virtualWrite(V1, percentage);

  if(percentage<0)
  {
    percentage = 0;
  }
  else if(percentage>100)
  {
    percentage = 100;
  }

 }

 if (pinValue == 1)
    {
       if (percentage < 100)
       {
          digitalWrite(relay, LOW);
          Serial.print("Water level:");
          Serial.print(percentage);
          Serial.print("%");
          Serial.println(" Pump is ON");
          led1.on();
          lcd.setCursor(0,0);
          lcd.print("Water Lvl:");
          lcd.print(percentage);
          lcd.print("%  ");
          lcd.setCursor(0,1);
          lcd.print("Pump: ON  (AUTO)");

       }

       else
       {
          digitalWrite(relay, HIGH);
          Serial.println("Water level is 100%   Pump is OFF");
          led1.off();
          lcd.setCursor(0, 0);
          lcd.print("Water Lvl:");
          lcd.print(percentage);
          lcd.print("%  ");
          lcd.setCursor(0,1);
          lcd.print("Pump: OFF (AUTO)");

       }
    }
   else
    {
      digitalWrite(relay, HIGH);
      Serial.print("Water level:");
      Serial.print(percentage);
      Serial.print("%");
      Serial.println("System is OFF, Check Blynk");
      lcd.setCursor(0,0);
      lcd.print("Water Lvl:");
      lcd.print(percentage);
      lcd.print("%  ");
      lcd.setCursor(0,1);
      lcd.print("System is OFF   ");
      led1.off();

    }

   }

body:
Use a different button - you may have to wire something up...

In the loop, read the button and only if it is pressed should you re-calibrate and set the value to eeprom.  You can do it in setup too but then you would have to reboot with the button pressed to trigger re-calibration.

You can also read a serial command in the loop.  Anything external that can be triggered with a separate intent to re-calibrate would work.  A power outage resembles the normal reset too much.  To execute different behavior in two different scenarios, you must be able to detect which scenario you are in.


message:
How Arduino IDE work with ESP32?

I understand how compiler compile our code to make binary code. Then we can use avr gcc to upload bin code to atmega chips via programer (USB ISP) or via USB serial (required bootloader).
I'm using ESP32 for a while and notice they work in difference way. As far as I know
1. It  not required Arduino  bootloader.
2. It not reset when re-open serial monitor.
3. It use external memory chip.
4. It have boot and reset button
5. The USB Serial connect to ESP32 and we can upload bin code with it. (maybe the only way)
6. In IDE it run python scrip (esptool.py)
I wonder how the process going and how each element work for its part for completely understand the process.

body:
The ESP32 has a bootloader that uses serial embedded in its internal ROM. Whether that bootloader runs or not depends on the state of certain IO pins when the ESP32 starts up.

Those states are controlled by a small circuit that is triggered by the serial control lines (DTR and RTS).

On the Arduino there isn't that requirement, and the bootloader always runs when the chip resets, so a much simpler circuit is used to trigger a reset using just the DTR signal.

So for an Arduino whenever the serial port is opened the DTR signal resets the board. But for the ESP32 the RTS signal also has to be asserted along with the DTR signal in the right sequence to both set the correct IO pins and to reset the chip.

Whether the target device has internal flash or an external flash chip makes no difference. It is the bootloader's job to get the data into that flash. The AVR chips have a way of interfacing with the internal flash (ISP) to program it without a bootloader, but the ESP32, as it has external flash, doesn't need that (you can interface directly with the flash chip if you so wish).

The software on the PC that communicates with the bootloader has to speak the "language" the bootloader expects. Each family of chips has its own bootloader (some don't even have a bootloader, but that's another story) which speaks its own language. On the AVR chips that's usually a variant of the STK500 protocol, and the program `avrdude` is what communicates with it to send the program to flash. On the ESP32 (and the ESP8266 too) it's `esptool.py` that does the job. On chipKIT boards it's `pic32prog`. On Digipark it's `micronucleus`. There's as many upload programs as there are families of boards. Some programs, like `avrdude` and `pic32prog` are more flexible and can also talk to hardware programmers (USBASP, PICkit2 etc), but in general the upload program is written specifically for a particular bootloader.


message:
LCD TFT 2.4"" changes the values of analog read of Arduino Mega

I have a Arduino Mega with LCD TFT 2.4"" with reading 5v signal on A8 pin (Arduino mega pin) from a raspberry pi (just to test). They are grounded together. When the Arduino is without the LCD, the analog reading works fine (4.8V,same from multimeter). But when I assembly the LCD, even if I just assembly VCC and ground, the analog read increasce around of 0.2V measure. I already tried to change the voltage input with a potentiometer and I still receiving a measure error of 0.2V.  External energy supply to the LCD makes the things works, but I wouldn't like to have a external supply just to the screen.

What I'm doing wrong or what I can do ?

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

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

body:
 * The short answer is to beef up your power supply:

Don't use small batteries or power supplies.  For instance use D Size Cells instead of 9 Volt Cells.  Or use a 3 Amp power supply instead of a 100mAmp power supply.

 * The longer answer:

Make sure you have mitigated any power problems.  Like long or thin power lines.  Long or thin wires have more resistance.  And the more current you pull over that resistance the less voltage you will have at the far end.  Remember it follows the rule:

Voltage = Resistance * Current
------------------------------

 * Probably the best answer:

Check the ADC specification of the processor and make sure your voltage reference is not adversely affected by power fluctuations.  Some processors, like most used on Arduinos, have the ability to switch between internal references and external references.  Most designers who really need a good ADC response will design an external reference and instruct the processor to use the external over the internal reference.  For most Arduinos the function to call to switch references is ["analogReference()"][1].  You can read more about this command and external references [here][2].

  [1]: https://www.arduino.cc/reference/en/language/functions/analog-io/analogreference/
  [2]: https://support.arduino.cc/hc/en-us/articles/360018922239-What-is-the-AREF-pin-for-


body:
MCUFriend went through a number of revisions of the same 2.4" TFT shield over time. I guess it depended on what TFT screens they could get hold of cheapest at any given moment. I have two versions here, neither of which are the same as yours. Both have their own voltage regulator onboard for the 3.3V power (which yours doesn't). Both of them also have resistors present on the cathode of the back light - *which yours doesn't.*

I would imagine for this revision they mistakenly though the TFT screen's back light didn't require any current limiting resistors and omitted them, with the end result that connecting the TFT screen to the Arduino drags down the 5V voltage to that of the combined forward voltage of the LEDs in the back light circuit.

In short: your TFT screen is designed badly. Fixing it would require modifying the shield on a trace-level basis. Not easy.


message:
Adding an Interrupt to ATtiny45 with Arduino

I recently wrote a simple script to...we'll say, "flash some LED's" and uploaded it to an attiny45. In short, the script cycles through 3 LED's and turns them on for a specified frequency, in a specified direction. With a button, I can cycle through different modes. There are 7 modes (default (LED's OFF), then 3 different speeds forwards and 3 different speeds backwards).

The script works fine-ish, however I've noticed that in order to read from the button input properly, the function that turns the LED's ON and OFF must be completed, meaning that for the longer cycles, the user may have to hold the button until the function completes. This is further complicated during the shorter cycles, where the input may detect multiple button-presses (despite adding a delay following the digital read.

NOTE: I could just make the delay longer, but this doesn't fix the issue during lower frequencies, when the function may take multiple seconds to complete.

I feel the best way to sort this (though I'd be open to other ideas) is to use the attachInterrupt() function; however, it doesn't work. The button no longer works and I'm not sure why.

    // Pin Variables
    int led1 = 2;
    int led2 = 3;
    int led3 = 4;
    int leds[] = {led1, led2, led3};
    int modePin = 0; // (physical pin 5 on the IC)

    // Mode Speeds and setting
    int fastTime = 100;
    int mediumTime = 300;
    int slowTime = 1000;
    int offTime = 100;
    int mode = 0;

    void setup() {
      for (int i=0; i<3; i++){
        pinMode(leds[i], OUTPUT);
        digitalWrite(leds[i], LOW);
      }
      attachInterrupt(modePin, callMode, RISING);
    }

    void loop() {
      // If we get here, reset and go back to default (all LED's OFF)
      if (mode >= 7) {
        mode = 0;
      }
    }

    void callMode(){
      ++mode;
      //TIME: 1000, 300, 100 (milliseconds)
       switch (mode) {
         case 0:
           // Default, OFF
           for (int i=0; i<3; i++){
             digitalWrite(leds[i], LOW);
           }
           break;
         case 1:
           // Forward, Fast
           ledMode(fastTime, offTime, true);
           break;
         case 2:
           // Forward, Medium
           ledMode(mediumTime, offTime, true);
           break;
         case 3:
           // Forward, Slow
           ledMode(slowTime, offTime, true);
           break;
         case 4:
           // Backwards, Fast
           ledMode(fastTime, offTime, false);
           break;
         case 5:
           // Backwards, Medium
           ledMode(mediumTime, offTime, false);
           break;
         case 6:
           // Backwards, Slow
           ledMode(slowTime, offTime, false);
           break;
         case 7:
           // Return to Zero
           for (int i=0; i<3; i++){
              digitalWrite(leds[i], LOW);
           }
           mode = 0;
           break;
       }
    }

    void ledMode(int onTime, int offTime, bool forward){
      if (forward) {
        for (int i = 0; i <= 2; i++) {
          digitalWrite(leds[i], HIGH);
          delay(onTime);
          digitalWrite(leds[i], LOW);
          delay(offTime);
        }
      }
      else {
        for (int i = 2; i >= 0; i--) {
          digitalWrite(leds[i], HIGH);
          delay(onTime);
          digitalWrite(leds[i], LOW);
          delay(offTime);
        }
      }
    }

NOTE: callMode() and ledMode() are only split up into different functions because I know that the function passed to attachInterrupt() cannot contain any delays(). So each time the button is pressed, the mode variable should increment and then the switch-statement should cause the next mode to run. When we reach 7, let's reset to zero and enter the default/OFF mode.

I've been racking my head for a few days on this and not sure what the problem is. Perhaps I can only use the attachInterrupt() function to some other pin? Perhaps I'm not using that function correctly?

Thank you in advance for any and all help you can provide.

-Joe

body:
Interrupts are overkill for this kind of ultra-slow problems, and they
can introduce some extra complexity. Here the best solution seems (to me
at least) to lie in the approach of the [Blink Without Delay][bwod]
Arduino tutorial. Obviously, it must be adapted. In that tutorial, the
system switches between only two states (LED off or on). Here the
cycling of the LEDs goes through six phases:

0. all LEDs are off
1. LED[0] is on
2. all LEDs are off
3. LED[1] is on
4. all LEDs are off
5. LED[2] is on

The basic algorithm is the same: when `millis()` tells us it is time to
move to the next phase, we do so and update the state of the LEDs.

Note that I numbered the phases in such a way that the last bit
(`phase&1`) tells us whether an LED is on, and in that case the
remaining bits (`phase>>1`) hold the index of the LED that is on.

Here is how to cycle the LEDs at a fixed speed:

```c++
if (millis() - last_change >= phase_time) {
    last_change += phase_time;

    /* If an LED is on, turn it off. */
    if (phase & 1)
        digitalWrite(leds[phase >> 1], LOW);

    /* Move to the next phase. */
    if (++phase >= 6) phase = 0;

    /* Turn on the LED if needed. */
    if (phase & 1)
        digitalWrite(leds[phase >> 1], HIGH);
}
```

On top of this you need a [finite state machine][fsm] that cycles
between the different modes (speeds and directions). In order to avoid
code repetition, I would split this mode into a “state” that can OFF,
FORWARD or BACKWARDS, and an index into an array of delay times (with 0,
1, 2 meaning fast, medium and slow, respectively).

Putting it all together (warning: not tested):

```c++
const uint8_t leds[] = { 2, 3, 4 };
const uint32_t times[] = { 100, 300, 1000 };

void setup() {
    for (int i = 0; i < 3; i++)
        pinMode(leds[i], OUTPUT);
}

enum { OFF, FORWARD, BACKWARDS } state = OFF;  // global state
uint8_t time_idx;      // index in times[] (0 = fast)
int8_t phase;          // 0 = all off, 1 = led[0] on, 2 = all off...
uint32_t last_change;  // last time the phase changed

void loop() {

    /* Change mode on button press. */
    if (button_pressed()) {
        if (state == OFF) {
            state = FORWARD;
            time_idx = 0;  // start fast
        } else {
            time_idx++;    // slow down
            if (time_idx >= 3) {  // change direction or stop
                time_idx = 0;
                if (state == FORWARD)
                    state = BACKWARDS;
                else              // state is BACKWARDS
                    state = OFF;
            }
        }
    }

    /* Cycle the LEDs. */
    if (state != OFF && millis() - last_change >= times[time_idx]) {
        last_change += times[time_idx];

        /* If an LED is on, turn it off. */
        if (phase & 1)
            digitalWrite(leds[phase >> 1], LOW);

        /* Move to the next phase. */
        if (state == FORWARD) {
            if (++phase >= 6) phase = 0;
        } else {  // BACKWARDS
            if (--phase < 0) phase = 5;
        }

        /* Turn on the LED if needed. */
        if (phase & 1)
            digitalWrite(leds[phase >> 1], HIGH);
    }
}
```

I did not write the `button_pressed()` function, which is meant to
debounce the button and detect the “just pressed” transition. It is left
as an exercise to the reader (or you can just use a [debouncing
library][Bounce2]).

[bwod]: https://www.arduino.cc/en/Tutorial/BuiltInExamples/BlinkWithoutDelay
[fsm]: https://majenko.co.uk/blog/finite-state-machine
[Bounce2]: https://github.com/thomasfredericks/Bounce2


message:
Fail upload sketches to ESP8266 only on Ubunto 20.04.3

I installed a fresh copy of Ubuntu 20.04, and Arduino IDE1.8.16. At the beginning adding user to `dialout` group enabled uploading sketch to Aruino AVR family, and ESP32, but still ESP8266 gives this error:

    Sketch uses 260889 bytes (24%) of program storage space. Maximum is 1044464 bytes.
    Global variables use 27980 bytes (34%) of dynamic memory, leaving 53940 bytes for local variables. Maximum is 81920 bytes.
    esptool.py v3.0
    Serial port /dev/ttyUSB0
    Connecting........_____....._____....._____....._____....._____....._____....._____
    Traceback (most recent call last):
      File "/home/guy/.arduino15/packages/esp8266/hardware/esp8266/3.0.2/tools/upload.py", line 66, in <module>
        esptool.main(cmdline)
      File "/home/guy/.arduino15/packages/esp8266/hardware/esp8266/3.0.2/tools/esptool/esptool.py", line 3552, in main
        esp.connect(args.before, args.connect_attempts)
      File "/home/guy/.arduino15/packages/esp8266/hardware/esp8266/3.0.2/tools/esptool/esptool.py", line 529, in connect
        raise FatalError('Failed to connect to %s: %s' % (self.CHIP_NAME, last_error))
    esptool.FatalError: Failed to connect to ESP8266: Timed out waiting for packet header
    esptool.FatalError: Failed to connect to ESP8266: Timed out waiting for packet header

So I tried to erase flash using `esptool.py` :

    guy@desktop:~$ esptool --chip  auto --port /dev/ttyUSB0 erase_flash
    esptool.py v2.8
    Serial port /dev/ttyUSB0
    Connecting........_____....._____....._____....._____....._____....._____....._____

    A fatal error occurred: Failed to connect to Espressif device: Timed out waiting for packet header

Since AVR's and ESP32 work properly using USB's and ACM's I can guess that is is not a problem with the ability to access serial comm.

What might it be ?

body:
There is something wrong with some new kernels of Ubuntu 20.04 LTS, interfering with ESP8266 core uploading process

`5.4.0-88-generic #99-Ubuntu SMP Thu Sep 23 17:29:00 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux`

I had the same issue and downgraded the kernel to

`5.4.0-86-generic #97-Ubuntu SMP Fri Sep 17 19:19:40 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux`

solved the issue

---
---

The issue happens to ESP8266 core uploading process, with the following tested Ubuntu cores

- `linux-5.11.0-37-generic`
- `linux-5.4.0-89-generic`
- `linux-5.4.0-88-generic`

and tested OK with

- `linux-5.11.0-38-generic`
- `linux-5.11.0-36-generic`
- `linux-5.8.0-48-generic`
- `linux-5.4.0-90-generic`
- `linux-5.4.0-86-generic`

---

### Temporarily fix

To temporarily fix the issue by using working kernel, e.g. `linux-5.4.0-86-generic`

A. Select from GNU GRUB boot menu

- Advanced options for Ubuntu
  - Ubuntu, with Linux 5.4.0-86-generic

- If you don't have that kernel, install by

```
sudo apt install linux-image-5.4.0-86-generic
```

- Reboot and select `5.4.0-86-generic` from GNU GRUB boot menu

---

---

### To save the selected GRUB settings

More info [**GRUB Simple-configuration**](https://www.gnu.org/software/grub/manual/grub/grub.html#Simple-configuration)

1. Edit `/etc/default/grub` by

```
$ sudo gedit /etc/default/grub
```

2. Add to the file

```
 GRUB_DEFAULT=saved
 GRUB_SAVEDEFAULT=true
```

3. Activate the change so that last selected value is used for the next boot.

```
$ sudo update-grub
```

### Update

Just testing OK with latest kernel

- `linux-5.11.0-38-generic`
- `linux-5.4.0-90-generic`

It seems recent kernel release has fixed the issue