# Question
Title: How to handle class initialization when using brace-enclosed initializer lists
I'm working with a custom C++ library, CPSTL, for Arduino, which includes a `cpstd::vector` class that is designed to work with `cpstd::initializer_list`, `cpstd::initializer_list` is supposed to mimic `std::initializer_list`.

However, I'm having trouble initializing a `cpstd::vector` using brace-enclosed initializer lists.

I've looked up many sources online, and it seems there is not a lot of information in the topic, but came up to things such as FastArduino: initializer list, and Arduino STL: Initializer list. Giving me hopes that it is actually possible. (I can't use those libraries, because they lack the build system generation tools on the library I am developing, they also lack on customizability, and also as a good learning experience)

I've tried various approaches, but I keep getting the error:

> could not convert '{0, 1, 2, 3, 4}' from 'brace-enclosed initializer list' to 'cpstd::vector'.

Here's an example of the code that's causing the issue:

```
    cpstd::vector<unsigned char> myVector = {0, 1, 2, 3, 4};

```

I have already implemented a custom `cpstd::initializer_list` and constructor that should handle this, but the issue persists. Is there something specific to the Arduino environment that could be causing this issue?

Additional Information:

* I have verified that the `cpstd::initializer_list` is correctly defined and included in my code.
* The `cpstd::vector` class is included and accessible.
* I have reviewed my `cpstd::vector` class, and the constructor for `cpstd::initializer_list` is correctly implemented.
* While reading the error log, I noticed that `std::initializer_list` constructor has two parameters, a pointer to the data, and also a variable telling the length of the braced enclosed list, however I noticed that the list ends up casting to a single parameter, hence having no possible constructor to call

***What could be causing this issue, and how can I resolve it to initialize `cpstd::vector` using brace-enclosed initializer lists in the Arduino environment? I think the main issue is with boards that have no STL support. (i.e. AVR based boards)***

I've came to the conclusion that it will not be possible to create such constructors/operators due to compiler limitations, I think I've tried anything that came to mind. But I don't want to give up on this without knowing if there is a workaround.

**edit (removed previous code snippets for clarity, added minimal code example reproducing the error) :**

minimal sketch reproducing the error:

```
#include <Arduino.h>
#include <stddef.h>

namespace cpstd {

  template<typename T>
  class initializer_list {
  public:
    using value_type = T;
    using reference = const T&;
    using const_reference = const T&;
    using size_type = size_t;
    using const_iterator = const T*;

  private:
    const_iterator _M_array;
    size_type _M_len;

    constexpr initializer_list(const T* array, size_type size) noexcept
      : _M_array(array), _M_len(size) {}

  public:
    constexpr initializer_list() noexcept
      : _M_array(nullptr), _M_len(0) {}

    constexpr size_type size() const noexcept {
      return _M_len;
    }
    constexpr const_iterator begin() const noexcept {
      return _M_array;
    }
    constexpr const_iterator end() const noexcept {
      return _M_array + _M_len;
    }
  };
}

template<typename T>
class exampleClass{
  protected:
    T buffer[10];
    size_t len;

  public:
    exampleClass(): len(0) {}
    exampleClass(cpstd::initializer_list<T> il){
      len = il.size();
      for(size_t i = 0; i < len; i++){
        buffer[i] = *(il.begin()+i);
      }
    }

    exampleClass& operator=(cpstd::initializer_list<T> il){
      len = il.size();
      for(auto i = il.begin(); i < il.end(); i++){
        buffer[i] = *i;
      }
    }

    size_t size() const {return len;}
    T data(size_t x) const {return buffer[x];}
};

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);

  exampleClass<uint8_t> myObject = {0,1,2,3};

  Serial.println(myObject.size());
  Serial.println(myObject.data(0));
  Serial.println(myObject.data(1));
  Serial.println(myObject.data(2));
  Serial.println(myObject.data(3));

}

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

}

```

# Answer
> 0 votes
So I have been messing around with the minimal example code and found a working solution, I'll post the solution just in case someone finds themselves having the same issue on the future, the only downside is that it feels a bit hacky to my taste, I still wonder if there is a better solution. And would gratly appreciate any feedback.

I found out that the compiler does not ackowledges the initializer\_list class for braced enclosed initializers if the class is not under the namespace std.

The way I came arround this problem lies on using the preprocessor directive below:

```
#if __has_include(<initializer_list>)

```

With this line conditional compilation takes place, and we can specify what to do whenever std::initializer\_list is present or not.

* If std::initializer\_list is not present an implementation is provided.
* cpstd::intitlizer\_list is only a template alias of std::intitializer\_list

minimal sketch with the solution:

```
#include <Arduino.h>
#include <stddef.h>

namespace std {

  template<typename T>
  class initializer_list {
  public:
    using value_type = T;
    using reference = const T&;
    using const_reference = const T&;
    using size_type = size_t;
    using const_iterator = const T*;

  private:
    const_iterator _M_array;
    size_type _M_len;

    constexpr initializer_list(const T* array, size_type size) noexcept
      : _M_array(array), _M_len(size) {}

  public:
    constexpr initializer_list() noexcept
      : _M_array(nullptr), _M_len(0) {}

    constexpr size_type size() const noexcept {
      return _M_len;
    }
    constexpr const_iterator begin() const noexcept {
      return _M_array;
    }
    constexpr const_iterator end() const noexcept {
      return _M_array + _M_len;
    }
  };
}

namespace cpstd {
  template<class T>
  using initializer_list = std::initializer_list<T>;
}

template<typename T>
class exampleClass{
  protected:
    T buffer[10];
    size_t len;

  public:
    exampleClass(): len(0) {}
    exampleClass(cpstd::initializer_list<T> il){
      len = il.size();
      for(size_t i = 0; i < len; i++){
        buffer[i] = *(il.begin()+i);
      }
    }

    exampleClass& operator=(cpstd::initializer_list<T> il){
      len = il.size();
      for(auto i = il.begin(); i < il.end(); i++){
        buffer[i] = *i;
      }
    }

    size_t size() const {return len;}
    T data(size_t x) const {return buffer[x];}
};

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);

  exampleClass<uint8_t> myObject = {0,1,2,3};

  Serial.println(myObject.size());
  Serial.println(myObject.data(0));
  Serial.println(myObject.data(1));
  Serial.println(myObject.data(2));
  Serial.println(myObject.data(3));

}

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

}

```

---
Tags: arduino-uno, arduino-mega
---


# Question
Title: Triggering a picture with esp32-cam and GPIO13
I'm trying to trigger a picture using the GPIO13 of an esp32-cam, AI Thinker model. I'm using that example as a base: https://randomnerdtutorials.com/esp32-cam-pir-motion-detector-photo-capture/ but instead of the PIR/Transistor combination, I'm using a press button with a pull-up resistor that pulls the GPIO13 pin down when pressed, simulating the PIR signal. I'm feeding the esp-32 cam with a 5V power supply and the button circuit with the 3.3v pin of the esp32, all grounded. All hardware, SD card and so on is tested ok, I got the right voltages and I can see the GPIO13 Pin going to ground on my scope, but I just doesn't work. Any ideas? Edit 1: I'm using the ESP32-CAM-MB USB Board

# Answer
> 0 votes
Checking the specs of the cam board, I see that `GPIO13` has the function `HS2_DATA3`, suggesting that the SD card is using that pin (which is also corroborated by this article.)

This may or may not be a problem, as the state of `GPIO13` is only relevant for sleep/wakeup when the chip is sleeping, and only relevant for SD card access when the chip is running; but there is an external addon: your pullup resistor on the button is still there when the chip is running. The PIR module from the tutorial that you're trying to replace probably has an open collector output (floating when inactive, pulled LOW when active).

My best hunch is to get rid of the pullup resistor on your button, so that the pin is floating during SD card access.

There still is the possibility that you then interfere with the SD card data when you keep the button pressed. If that is the case, you may need to put a resistor in *series* with the button, so that the wake-up signal is weaker than the SD card data signal (start at 100KOhm and reduce until wake-up works).

If that isn't it, the question is lacking details. As you did not even post a description of what exactly "just does not work", first thing would be to produce a minimal sketch just to test sleep/wakeup via GPIO13 and post that here.

---
Tags: esp32, esp32-cam
---


title: "if" condition problem / question

text:
# Question
Title: "if" condition problem / question
I'm new to Arduino and my question is rather theoretical. I have an Arduino Nano board (Atmega168 processor), a button, a display. I have written a button handler that does not stop code execution. My idea is: poll the button in "loop" cycle, and if it is pressed, perform `k++`. When `k` exceeds a specified value, perform `cnt++` and print it on the display.

Code example №1 works correctly. I get 1 -\> 2 -\> 3 -\> ...:

```
void loop() {
 if (digitalRead(button_pd) == LOW) {
    k = k + 1;
    if (k >= 20) {
      k = 0;
      cnt = cnt + 1;
    }
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print(cnt);
  }
}

```

Code example №2 is incorrect. I get 16 -\> 27 -\> 40 -\> ... Seems like not `cnt` is printed, but `k`.

```
void loop() {
  if (digitalRead(button_pd) == LOW) {
    k = k + 1;
    if (k >= 20) {
      k = 0;
      cnt = cnt + 1;
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print(cnt);
    }
  }
}

```

Here's my program:

```
#include <LiquidCrystal_I2C.h>

#define button_pd 6

LiquidCrystal_I2C lcd(0x27, 16, 2);

int k = 0;
int cnt = 0;

void setup() {

  pinMode(button_pd, INPUT_PULLUP);

  lcd.init();
  lcd.backlight();
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(cnt);

}

void loop() {

  // button handler

}

```

My question is. Why examples №1 and №2 work differently?

# Answer
> 4 votes
The timings are different.

Every operation on the LCD takes time. This:

```
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(cnt);

```

involves some I2C communication, and thus takes orders of magnitude more time than `k++;`.

On the first version of your `loop()`, these operations are performed on each iteration, while the button is being pressed. On the second version, they are performed only when `k` reaches 20, thus twenty times less often. The second version thus runs twenty times faster... too fast for the LCD to correctly refresh and show all the values it is being asked to display.

I recommend you do not rely on loop counting for controlling timings. Instead, use the Arduino function specifically designed for time management. For example, if you want to increment the counter every 200 ms, you should record the time when the button is pressed (the falling edge of the signal), and increment `cnt` 200 ms later:

```
uint8_t previous_state;  // previous state of the button
uint32_t press_timestamp;  // time when the button was pressed

void loop() {
    uint32_t now = millis();
    uint8_t state = digitalRead(button_pd);
    if (previous_state == HIGH && state == LOW)  // falling edge
        press_timestamp = now;
    previous_state = state;
    if (state == LOW && now - press_timestamp >= 200) {
        cnt = cnt + 1;
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print(cnt);
    }
}

```

# Answer
> 1 votes
Thanks. Somehow code example №3 works correctly. I have used a library for timer and simplified code from the answer above.

```
#include <LiquidCrystal_I2C.h>
#include <millisDelay.h>       // Timer

#define button_pd 6

LiquidCrystal_I2C lcd(0x27, 16, 2);

int k = 0;
int cnt = 0;

//uint8_t previous_state;  // previous state of the button

millisDelay d;

void setup() {
  pinMode(button_pd, INPUT_PULLUP);

  lcd.init();
  lcd.backlight();
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(cnt);
}

void loop() {

    uint8_t state = digitalRead(button_pd);
    if (state == LOW)
        d.start(300);
    //previous_state = state;
    if (d.justFinished()) {
        cnt = cnt + 1;
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print(cnt);
    }

}

```

---
Tags: programming, arduino-nano, c++
---


# Question
Title: Get address of a I2C transaction when multiple addresses are registered
I have an application polling 4 ADCs by I2C. The application shall also write on some ADC registers. In order to test it, I'd like to use a single Arduino UNO, enabling it for receiving I2C messages over 4 different addresses by masking the TWAMR register. In this way I can have 4 ADCs "emulated" on a single Arduino.

When the application asks for a read to Arduino at some address, I'm able to get the value of the required address by reading the TWDR register:

```
void requestEvent(){
  byte addr = TWDR >> 1;
  if (0x4A == addr){ // do something }
  else if (0x4B == addr){ // do something }
  // ...
}

void setup(){
  // ...
  Wire.onRequest(requesEvent);
}

```

However, when the application requests to write something to a certain ADC (with its own address), I'm not able to get the address value in the `onReceive(int)` callback:

```
void receiveEvent(int howMany){
  byte addr = TWDR >> 1; // returns the first byte AFTER the address in the I2C message
}

```

Am I doing something wrong? Is there a way to reach my goal?

Thanks.

Luca

**Edit:**

Reading the ATmega datasheet (sec. 22.9.4, p. 241), the problem with reading the TWDR register is that it contains the last byte received, that in slave receiver mode is not the address but the last data sent by the master.

Anyway, is there any workaround for this problem?

# Answer
Reading the TWDR register in the `onReceive()` callback doesn't give you the address because of the time, that it is called at. The `onReceive()` callback is called when all bytes have already been received and put in the `Wire` libraries internal buffer. Thus in that callback TWDR will still hold the last received data byte.

The `onRequest()` callback on the other hand is called right after the address was received. Thus TWDR still holds the received address.

You will need to modify the Wire library to achieve your goal. Similar to the `onRequest()` callback you can introduce a third kind of callback function, which will be executed after receiving the slave address to save the received address for later use (the address matching is still done via hardware, so you still need to mask the address via TWAMR).

You can find the files for the Wire library inside your used core (for me the Uno uses the path ~/.arduino15/packages/arduino/hardware/avr/1.8.5/libraries/Wire). Look at line 581 of src/utility/twi.c. This is inside the TWI ISR, the `case` clause `TW_SR_SLA_ACK`, which will be executed on address receive/match. Here you can insert your callback function.

If you want to do this in a similar handy way, that the `Wire` library does with the other callbacks, then you need to change a few other things:

1. Insert a function pointer for this at the start of the twi.c file, right besides the other function pointers:

```
 static void (*twi_onSlaveAddressMatch)(uint8_t);

```
2. Add the execution of that function to the case in the ISR described above and provide the content of TWDR (shifted to eliminate the direction bit) as a parameter:

```
 twi_onSlaveAddressMatch(TWDR >> 1);

```
3. Add a function to set the callback function pointer in twi.c:

```
 void twi_attachSlaveAddressMatchEvent( void (*function)(uint8_t) ){
     twi_onSlaveAddressMatch = function;
 }

```
4. Add the callback set function as a function prototype to twi.h:

```
 void twi_attachSlaveAddressMatchEvent( void (*function)(uint8_t) );

```
5. In Wire.h add a function pointer for the new callback and the corresponding service function inside the `private:` section:

```
 static void (*user_onSlaveAddressMatch)(uint8_t);
 static void onSlaveAddressMatchService(uint8_t);

```
6. In Wire.h add a function to set the user callback function to the `public:` section:

```
 void onSlaveAddressMatch( void (*)(uint8_t) );

```
7. In Wire.cpp add the implementation of the service function:

```
 void TwoWire::onSlaveAddressMatchService(uint8_t address){
     if(!user_onSlaveAddressMatch){
         return;
     }
     user_onSlaveAddressMatch(address);
 }

```
8. In Wire.cpp add the implementation of the callback setter function:

```
 void TwoWire::onSlaveAddressMatch( void (*function)(uint8_t) ) {
     user_onSlaveAddressMatch = function;
 }

```

Now you should be able to set a callback for the address receive in your main code and save the address for later use:

```
uint8_t received_address = 0;

void getAddress(uint8_t address){
    received_address = address;
}

void setup(){
    ...
    Wire.onSlaveAddressMatch(getAddress);
}

```

In the `onReceive()` callback you can then check for that global variable.

Note: I have not tested or compiled this. I just looked at the logic of the Wire library and copied the way it already defines its existing callback functions.
> 1 votes

---
Tags: arduino-uno, i2c
---


# Question
Title: I would like to know why my four gear motors are rotating at different speeds when connected to 2 L293D motor drivers, controlled by the arduino
Ignore direction of the motors(for now).

This is my connection diagram. Any and all improvements to this are welcome.

Bottom left motor seems to run at 210-224 rpm
Bottom right motor runs at 160-180 rpm
Top right motor runs at 210-224 rpm
Top left motor runs at 160-180 rpm

Code for running the below setup:

```

// Motor A connections

int enA = 7;

int in1 = 4;

int in2 = 5;

// Motor B connections

int enB = 6;

int in3 = 3;

int in4 = 2;

//Motor c

int enC = 9;

int in5 = 12;

int in6 = 13;

// Motor d connections

int enD = 8;

int in7 = 10;

int in8 = 11;

void setup() {

// Set all the motor control pins to outputs
pinMode(enA, OUTPUT);
pinMode(enB, OUTPUT);
pinMode(in1, OUTPUT);
pinMode(in2, OUTPUT);
pinMode(in3, OUTPUT);
pinMode(in4, OUTPUT);
pinMode(enC, OUTPUT);
pinMode(enD, OUTPUT);
pinMode(in5, OUTPUT);
pinMode(in6, OUTPUT);
pinMode(in7, OUTPUT);
pinMode(in8, OUTPUT);

  // Turn off motors - Initial state
digitalWrite(in1, LOW);
digitalWrite(in2, LOW);
digitalWrite(in3, LOW);
digitalWrite(in4, LOW);
digitalWrite(in5, LOW);
digitalWrite(in6, LOW);
digitalWrite(in7, LOW);
digitalWrite(in8, LOW);
}

void loop() {
  moveForward();
  delay(3000);
  motorOff();
  delay(1000);
}

void moveForward(){

  analogWrite(enA, 200);
  analogWrite(enB, 200);
  analogWrite(enC, 200);
  analogWrite(enD, 200);

  digitalWrite(in1, HIGH);
  digitalWrite(in2, LOW);
  digitalWrite(in3, HIGH);
  digitalWrite(in4, LOW);
  digitalWrite(in5, HIGH);
  digitalWrite(in6, LOW);
  digitalWrite(in7, HIGH);
  digitalWrite(in8, LOW);
}

void motorOff(){
  digitalWrite(in1, LOW);
  digitalWrite(in2, LOW);
  digitalWrite(in3, LOW);
  digitalWrite(in4, LOW);
  digitalWrite(in5, LOW);
  digitalWrite(in6, LOW);
  digitalWrite(in7, LOW);
  digitalWrite(in8, LOW);
}

```

Any change to the code is also welcome.

# Answer
Pins 7 and 8 aren't PWM pins on the UNO. So when you call analogWrite on them with a value greater than 127 it defaults to digitalWrite and just writes those pins HIGH. Pins 6 and 9 are PWM pins, so they are responding as expected to the analogWrite. Since they are outputting PWM and the signal to the other motors is constantly high, they run slower.

You should change your wiring so that all of the enable pins are connected to PWM capable pins. On the Arduino UNO those are pins 3, 5, 6, 9, 10, and 11.
> 2 votes

---
Tags: arduino-uno, motor, l293d
---


title: Esp32 fails to read MH-Z19C sensor

text:
# Question
Title: Esp32 fails to read MH-Z19C sensor
I'm trying to read CO2 data from a MH-Z19C sensor with an ESP32 board but I'm not getting anything. The error code from the library is 2 indicating a timeout (no data received).

Did I get the wiring wrong? I wonder if the sensor is fried ?

Library: MH-Z19 by Jonathan Dempsey

Connections:

* MH-Z19C RX to TX2 (17)
* MH-Z19C TX to RX2 (16)
* MH-Z19C VIN to Power Supply 5V
* MH-Z19C GND to Power Supply 3V

Code:

```
#include <SoftwareSerial.h>
#include <MHZ19.h>
#include <Wire.h>

// pin for uart reading
#define RX_PIN 16  // Rx pin which the MHZ19 Tx pin is attached to.
#define TX_PIN 17 // Tx pin which the MHZ19 Rx pin is attached to.

MHZ19 myMHZ19;
SoftwareSerial mySerial(RX_PIN, TX_PIN);

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

  // Start Co2 sensor
  mySerial.begin(9600);                               // (Uno example) device to MH-Z19 serial start
  myMHZ19.begin(mySerial);                                // *Serial(Stream) refence must be passed to library begin().
  myMHZ19.autoCalibration();                              // Turn auto calibration ON (OFF autoCalibration(false))
}

void loop() {
  // Wait a few seconds between measurements.
  delay(5000);

  int CO2;
  // Request CO2 (as ppm)
  CO2 = myMHZ19.getCO2();
  Serial.println(String(CO2) + " ppm");

  if (myMHZ19.errorCode != RESULT_OK) {
    Serial.print("Failed to receive CO2 value: ");
    Serial.println(myMHZ19.errorCode);
  }
}

```

# Answer
> 1 votes
This is not a Winsen Mh-z19 sensor (or any clone following it's specs) so you won't be able to read data using a mhz19 library. Most probably it's a HC8 sensor and someone would have to rewrite library to get data from it. Here are specs: https://pcus.ru/download/hc8.pdf and some more info: https://spezifisch.codeberg.page/posts/2022-08-23/co2-sensor-reverse-engineering/

---
Tags: sensors, esp32
---


# Question
Title: WiFiClient.cpp:517 flush(): fail on fd 48, errno: 11, "No more processes" what it mean?
Hello i wrote this sketch that upload a temperature reading of a DHT22 sensor to a phpMyAdmin server in localHost, the sketch work fine, the data been upload every 5 min to the server than ESP go t sleep, but every time the code has been executed i have the printout in the console of this error which i don't understand what mean.

```
[  1937][E][WiFiClient.cpp:517] flush(): fail on fd 48, errno: 11, "No more processes"

```

here below my sketch: the sketch include the timer every 5 min to wakeup esp read the temperature and post to the server.

```
#include <Arduino.h>
#include <DHT.h>
#include <Adafruit_Sensor.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <Wire.h>

// FOR T sensor
#define TsensorPin 4
#define DHTTYPE DHT22
DHT dht(TsensorPin, DHTTYPE);
String sensorName = "DHT22";
String sensorLocation = "Casa1";
float h;
float t;
float f;
float hif;
float hic;

// for wifi connection
const char* ssid     = "Captain Spiko";
const char* password = "123456789d";

// server data
const char* serverName = "http://192.168.50.158/esp_web/post_esp.php";
String apiKeyValue = "123456789";

// for awake and sleep
#define uS_TO_S_FACTOR 1000000
#define TIME_TO_SLEEP  300
RTC_DATA_ATTR int bootCount = 0;

void print_wakeup_reason(){
  esp_sleep_wakeup_cause_t wakeup_reason;

  wakeup_reason = esp_sleep_get_wakeup_cause();

  switch(wakeup_reason)
  {
    case ESP_SLEEP_WAKEUP_EXT0 : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
    case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
    case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Wakeup caused by timer"); break;
    case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break;
    case ESP_SLEEP_WAKEUP_ULP : Serial.println("Wakeup caused by ULP program"); break;
    default : Serial.printf("Wakeup was not caused by deep sleep: %d\n",wakeup_reason); break;
  }
}

void readTemperature(){

  h = dht.readHumidity();
  t = dht.readTemperature();
  f = dht.readTemperature(true); // in F

  // Compute heat index in Fahrenheit (the default)
  hif = dht.computeHeatIndex(f, h);
  // Compute heat index in Celsius (isFahreheit = false)
  hic = dht.computeHeatIndex(t, h, false);

  Serial.print(F("Humidity: "));
  Serial.print(h);
  Serial.print(F("%  Temperature: "));
  Serial.print(t);
  Serial.print(F("°C "));
  Serial.print(f);
  Serial.print(F("°F  Heat index: "));
  Serial.print(hic);
  Serial.print(F("°C "));
  Serial.print(hif);
  Serial.println(F("°F"));
}

void activateSleep(){
  Serial.println("Going to sleep now");
  delay(1000);
  Serial.flush();
  esp_deep_sleep_start();
}

bool setupWifi(){
  WiFi.begin(ssid, password);
  Serial.println("Connecting");
  while(WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to WiFi network with IP Address: ");
  Serial.println(WiFi.localIP());

  if (WiFi.status() == WL_CONNECTED){
    return true;
  } else {
    return false;
  }

}

void postData(){
  if(WiFi.status()== WL_CONNECTED){
    WiFiClient client;
    HTTPClient http;
    http.begin(client, serverName);
    http.addHeader("Content-Type", "application/x-www-form-urlencoded");
    // Prepare your HTTP POST request data
    String httpRequestData = "api_key=" + apiKeyValue + "&sensor=" + sensorName
                          + "&location=" + sensorLocation + "&value1=" + String(h)
                          + "&value2=" + String(t) + "&value3=" + String(f) + "";
    Serial.print("httpRequestData: ");
    Serial.println(httpRequestData);
    int httpResponseCode = http.POST(httpRequestData);
    if (httpResponseCode>0) {
      Serial.print("HTTP Response code: ");
      Serial.println(httpResponseCode);
    }
    else {
      Serial.print("Error code: ");
      Serial.println(httpResponseCode);
    }
    http.end();
  }else {
    Serial.println("WiFi Disconnected");
  }
}

/// @brief  Set up
void setup() {

  Serial.begin(115200);
  delay(1000);
  ++bootCount; // tiene il conto dei restart
  Serial.println("Boot number: " + String(bootCount));
  print_wakeup_reason();
  if (setupWifi() == true){
    esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);// set up next wake up after 30 sec
    Serial.println(F("DHTxx test!"));
    dht.begin();
  };

}

/// @brief loop func
void loop() {
  readTemperature();
  postData();
  activateSleep();
}

```

# Answer
> 2 votes
I think you ran into the issue described on Github issues for WifiClient.

A user has loooked into this and found that the error message does not match the problem:

> errno 11 (EAGAIN) happens when you go to read (via BSD recv function) bytes from a stream with MSG\_DONTWAIT flag and there are no bytes to be read. The ESP error string "No more processes" is misleading. It's really "No data available, try again later." or maybe "No data to process".

It seems that there's no fix for the package yet as of today, but another user has posted a derived class that fixes the problem:

> File wifiFix.h:
>
> ```
> #pragma once
>
> class WiFiClientFixed : public WiFiClient {
> public:
>   void flush() override;
> };
>
> ```
>
> File wifiFix.cpp:
>
> ```
> #include <WiFi.h>
> #include <lwip/sockets.h>
> #include "wifiFix.h"
>
> #define WIFI_CLIENT_FLUSH_BUFFER_SIZE    (1024)
>
> void WiFiClientFixed::flush() {
>   int res;
>   size_t a = available(), toRead = 0;
>   if (!a) {
>       return;//nothing to flush
>   }
>   auto *buf = (uint8_t *) malloc(WIFI_CLIENT_FLUSH_BUFFER_SIZE);
>   if (!buf) {
>       return;//memory error
>   }
>   while (a) {
>       // override broken WiFiClient flush method, ref https://github.com/espressif/arduino-esp32/issues/6129#issuecomment-1237417915
>       res = read(buf, min(a, (size_t)WIFI_CLIENT_FLUSH_BUFFER_SIZE));
>       if (res < 0) {
>           log_e("fail on fd %d, errno: %d, \"%s\"", fd(), errno, strerror(errno));
>           stop();
>           break;
>       }
>       a -= res;
>   }
>   free(buf);
> }
>
> ```
>
> File main.cpp:
>
> ```
> #include "wifiFix.h"
> WiFiClient* wifi = new WiFiClientFixed();
>
> ```
>
> Finally, instead of `http.begin(url);`, use `http.begin(*wifi, url);`

# Answer
> 0 votes
In Platformio.ini I changed config to **"platform = espressif32@3.5.0"** from "platform = espressif32". It solved this issue for me

# Answer
> 0 votes
This bug is solved in Espressif Arduino Core 2.0.14 which is out since last month. If you're using PlatformIO add this to your platformio.ini file:

```
platform = https://github.com/tasmota/platform-espressif32/releases/download/2023.10.05/platform-espressif32.zip

```

This is not from the official PlatformIO branch but from Tasmota, a trusted source in the PlatformIO community. See the github site: https://github.com/tasmota/platform-espressif32

---
Tags: esp32, wifi, error
---


title: Print text at any Y-value on SSD1306?

text:
# Question
Title: Print text at any Y-value on SSD1306?
I'm attempting to print several rows of text, at certain Y-values, on an SSD1306 128x64 LCD display.

I'm using the `ssd1306` library by Alexey Dynda. I initially wanted to use the more common LCD libraries out there, such as the Adafruit SSD1306 LCD library, however it unfortunately does not appear I can set custom I2C pins for most such libraries out there, which is required as I'm using a custom board with an ESP32-WROOM-DA chip. The `ssd1306` by Dynda appears to be able to do so.

I have the following example code, which prints 6 lines of text:

```
#include "ssd1306.h"
#include "nano_gfx.h"

const int PIN_I2C_SCL = 16;
const int PIN_I2C_SDA = 13;

void LCDTextDraw(int x, int y, const char* text)
{
  EFontStyle fontStyle;

  ssd1306_printFixed(x, y, text, fontStyle);
}

void LCDRectDraw(int x, int y, int w, int h)
{
  ssd1306_fillRect(x, y, x + w, y + h);
}

void LCDScreenClear(bool fill)
{
  ssd1306_clearScreen();

  if (fill)
    LCDRectDraw(0, 0, 128, 64);
}

void LCDInit()
{
  ssd1306_setFixedFont(ssd1306xled_font6x8);
  ssd1306_128x64_i2c_initEx(PIN_I2C_SCL, PIN_I2C_SDA, 0);
}

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

  pinMode(PIN_I2C_SCL, OUTPUT);
  pinMode(PIN_I2C_SDA, OUTPUT);

  LCDInit();
  LCDScreenClear(true);

  LCDTextDraw(30, 0, "TEST 1");
  LCDTextDraw(30, 10, "TEST 2");
  LCDTextDraw(30, 20, "TEST 3");
  LCDTextDraw(30, 30, "TEST 4");
  LCDTextDraw(30, 40, "TEST 5");
  LCDTextDraw(30, 50, "TEST 6");
}

void loop()
{}

```

With which I wish to print out 6 lines of text, each line evenly vertically spaced out by 10 pixels.

Which produces the following output on my LCD:

As you can see, the text rows are not evenly vertically spaced out as I wish them to be, with a large space between the `TEST 4` and `TEST 5` strings.

After looking at the definition of the `ssd1306_printFixed` function I'm using to print out my text in the example above, it turns out that it can only print rows of text at certain fixed Y-positions:

> @warning ssd1306\_printFixed() can output chars at fixed y positions: 0, 8, 16, 24, 32, etc.
> If you specify \[10,18\], ssd1306\_printFixed() will output text starting at \[10,16\] position.

Hence, I also tried using the `ssd1306_print` function (which uses a cursor to delineate its printing location on the screen), which doesn't have that warning in its header declaration. I replaced my `LCDTextDraw` function with:

```
void LCDTextDraw(int x, int y, const char* text)
{
  ssd1306_setCursor8(x, y);
  ssd1306_print(text);
}

```

However, that still produced the exact same output on my LCD, with the same spacing issues.

What is the proper way to print text rows at any Y-value on an LCD?

Thanks for reading my post, any guidance is appreciated.

# Answer
Turns out using the Adafruit SSD1306 library is much easier than I first thought. One just must specify the I2C pins used with `Wire`, and pass it as reference to the `Adafruit_SSD1306` constructor. Additionally, the Adafruit library doesn't appear to have the uneven vertical spacing issue.

The equivalent code below using the Adafruit library:

```
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

const int PIN_I2C_SCL = 16;
const int PIN_I2C_SDA = 13;

Adafruit_SSD1306 LCD(128, 64, &Wire);

void LCDTextDraw(int x, int y, const char* text, byte size)
{
  LCD.setCursor(x, y);
  LCD.setTextSize(size);
  LCD.print(text);
  LCD.display();
}

void LCDRectFill(int x, int y, int w, int h, int color)
{
  LCD.fillRect(x, y, w, h, color);
}

void LCDScreenClear(bool fill)
{
  LCD.clearDisplay();
  LCD.display();
  LCD.setTextColor(WHITE, BLACK);

  if (fill)
    LCDRectFill(0, 0, 128, 64, 1);
}

void LCDInit()
{
  LCD.begin(SSD1306_SWITCHCAPVCC, 0x3C);
}

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

  pinMode(PIN_I2C_SCL, OUTPUT);
  pinMode(PIN_I2C_SDA, OUTPUT);

  Wire.setPins(PIN_I2C_SDA, PIN_I2C_SCL);
  Wire.begin();

  LCDInit();
  LCDScreenClear(true);

  LCDTextDraw(30, 0, "TEST 1", 1);
  LCDTextDraw(30, 10, "TEST 2", 1);
  LCDTextDraw(30, 20, "TEST 3", 1);
  LCDTextDraw(30, 30, "TEST 4", 1);
  LCDTextDraw(30, 40, "TEST 5", 1);
  LCDTextDraw(30, 50, "TEST 6", 1);
}

void loop()
{}

```

Now produces the desired result:
> 1 votes

---
Tags: lcd, ssd1306
---


title: ESP32 cannot serial monitor

text:
# Question
Title: ESP32 cannot serial monitor
I use esp32 devkit v1 . I code follwing this picture.

```
const int vavle = 1;
int d = 1;

void setup()
{
  Serial.begin(115200);
  delay(2000);
  while (!Serial);
  Serial.println();
  pinMode(vavle,OUTPUT);
  Serial.println(d);
}

void loop()
{
  Serial.print("Open Vavle");
  digitalWrite(vavle,HIGH);
  delay(3000);
  digitalWrite(vavle,LOW);
  delay(1000);
  Serial.print("Close Vavle");
}

```

but serial monitor has error when use serial monitor it show me square . I confirm select true board rate. you can solve this problem .

# Answer
> 1 votes
The GPIO1 pin you are trying to use with `const int vavle = 1;` ... `pinMode(vavle, OUTPUT);` *is* the same pin that carries serial data to the PC.

From the pinout:

Their schematic link is broken, but if you find schematic for pretty much any similar board using this module you'll see GPIO1/U0TXD connected to a serial transceiver chip which is then connected to the USB port.

You need choose some other pin. There are pin guides and official documentation containing the same details that you can use to figure out which GPIO to use. GPIO numbers 16 through 33 inclusive are all output-capable and seem to have no special requirements, so they make sense to choose from.

---
Tags: serial, esp32
---


# Question
Title: ATmega328 drop-in replacement with more flash memory
Is there a ATmega328 drop-in replacement with more flash memory?

Needs to be 28 pin DIL to fit the socket.

Alternatively, is there a board that has the exact dimensions and pins as an Arduino UNO, but with more flash memory?

Everything in my project works fine, but I need more program memory. Can unfortunately not use a different board layout or size.

# Answer
> 2 votes
> Is there a ATmega328 drop-in replacement with more flash memory?

No

> Alternatively, is there a board that has the exact dimensions and pins as an Arduino UNO, but with more flash memory?

Yes, but it'll be probably something with ARM (UNO R4 minima has even 5V ARM), However libraries might be an issue

As for AVRs, there are for example AVR128DA28 but as far as I know, it's definitely not pin compatible.

However you could use some proto board for UNO and wire it up somehow on it. (128kB, 28pin).

Also Atmega644/1284 (in pdip 40) could be used on proto board and it's much more compatible

---
Tags: arduino-uno, atmega328
---


# Question
Title: Give zero volt to specific servo motors in a certain time
I have a robot that uses 4 mechanical arms. Each mechanical arm has 4 "READYTOSKY 30kg" servo motors on them.

At some point, I need to use the absolute maximum force of only two mechanical arms (while the other two will stay still). Even though I do not change the coordinates of the other two mechanical arms (which I am not using),they consume voltage and "take away" the full potential of force from the other two.

Is there a way to stop the voltage consumed by the two other arms just for a brief moment using Arduino code? Shortly afterwards they will get back the voltage they need.

```
    if(level==25)
      {
        pwm.setPWM(12, 0, 200);
        pwm.setPWM(13, 0, 255);
        pwm.setPWM(14, 0, 430);
        delay(100);
        pwm.setPWM(1, 0, 380);
        pwm.setPWM(2, 0, 520);
        delay(500);
        pwm.setPWM(0, 0, 170);
        delay(600);
        stepperten.setCurrentPosition(0);
        while (stepperten.currentPosition() != (-3*200))
        {
        stepperten.setSpeed(-600);
        stepperten.runSpeed();
        }
        steppertwist.setCurrentPosition(0);
        while (steppertwist.currentPosition() != (100))
        {
          steppertwist.setSpeed(200);
          steppertwist.run();
        }
        stepper1.setCurrentPosition(0);
        while(stepper1.currentPosition() != (30))
        {
          stepper1.setSpeed(200);
          stepper1.run();
        }

        pwm.setPWM(1, 0, 295); //THIS IS THE MOMENT I NEED TO STOP VOLTAGE FOR OTHER ARMS
        pwm.setPWM(2, 0, 400); //AND GET THE MAXIMUM VOLTAGE POSSIBLE ON THESE TWO ARMS
        delay(1500);
        pwm.setPWM(12, 0, 125);

        array1[25][0] = 170;
        array1[25][1] = 295;
        array1[25][2] = 400;
        array1[25][3] = 153;
        array4[25][0] = 125;
        array4[25][1] = 255;
        array4[25][2] = 395;
      }

```

# Answer
> 1 votes
If you want to turn off power for some external parts you could try to power them via the digital pins. See this example code:

```
void setup(){
   pinMode(YOUR_ARM_POWER_SUPPLY_PIN, OUTPUT);

   // switch arm on
   digitalWrite(YOUR_ARM_POWER_SUPPLY_PIN, ON);
}

void loop(){
  if(armMustNotUseAnyPower()){
      // switch arm off
      digitalWrite(YOUR_ARM_POWER_SUPPLY_PIN, OFF);
  }

}

```

Keep in mind that the digital Pins cannot output as much power as VCC. But since you drive some servo motors over it I assume they get their power externally anyway. You might need to add some transistor or another way on how to switch the power on and off from the big power source. Hope this helps you in some way.

---
Tags: arduino-mega, stepper, stepper-motor
---


title: Half-duplex for Atmel SAMD21

text:
# Question
Title: Half-duplex for Atmel SAMD21
I'm using an Arduino MKR GSM 1400. I know this board uses the Atmel SAMD21 and the SAMD21 supports half-duplex (USART with full-duplex and single-wire half-duplex configuration). My question is, how can I configure one of the SERCOMs to use it as half-duplex (use one pin for rx and tx)?

# Answer
> 2 votes
> Up to six Serial Communication Interfaces (SERCOM), each configurable to operate as either:
>
> * USART with full-duplex and single-wire half-duplex configuration
> * I2C up to 3.4 MHz
> * SPI
> * LIN slave

It is an error in the overview of the SAM D21 features in the datasheet. The SERCOM is half-duplex for I2C. USART can't be configured half-duplex.

see Application Note about SERCOM configuration

> 1 Introduction to Serial Communication Interfaces (USART, I2C, and SPI)
>
> ... The exchange of data can be half-duplex or fullduplex depending on the serial module specification. ...
>
> 1.1 USART
>
> ... It is full-duplex in operation. ...
>
> 1.2 I2C
>
> ... It is half-duplex in communication. ...

# Answer
> 1 votes
You can use USART in half duplex mode.

SERCOMx.PAD0 or SERCOMx.PAD2 are available for this. Refer to document "AT03256: SAM D/R/L/C Serial USART (SERCOM USART) Driver" section "10. SERCOM USART MUX Settings".

Below is a piece of code for ATXMEGA32E5, SERCOM0, PAD0. I am tested - it works:

Pull-up will help keep the line at 1 when the device’s transmitter is turned off and there is no other transmitter on the line, or it has not turned on yet. In the GPIO setup procedure:

```
// PA08 - SERCOM0/PAD[0]
PORT->Group[0].PINCFG[8].bit.PULLEN=1;    // Pull Enable
PORT->Group[0].PINCFG[8].bit.PMUXEN=1;    // Peripheral Multiplexer Enable
PORT->Group[0].PMUX  [4].bit.PMUXE=0x02;  // PMUX function C - SERCOM0/PAD[0]

```

In the SERCOM setup procedure, configure TX and RX on one pad:

```
while(SERCOM0->USART.SYNCBUSY.reg & 0x07) { ; }
SERCOM0->USART.CTRLA.bit.TXPO = 0x00;   // SERCOM PAD[0] Transmit Data Pinout
while(SERCOM0->USART.SYNCBUSY.reg & 0x07) { ; }
SERCOM0->USART.CTRLA.bit.RXPO = 0x00;   // SERCOM PAD[0] is used for data reception

```

If at the time of your transmission both the receiver and the transmitter are turned on at the same time, you will hear your echo.

When you get up for reception, do not forget to turn off your transmitter so that it does not interfere with reception:

```
SERCOM0->USART.CTRLB.bit.TXEN=0x00; while(SERCOM0->USART.SYNCBUSY.bit.CTRLB ) { ; }
SERCOM0->USART.CTRLB.bit.RXEN=0x01; while(SERCOM0->USART.SYNCBUSY.bit.CTRLB ) { ; }

```

Before transmitting, do not forget to turn on the transmitter:

```
SERCOM0->USART.CTRLB.bit.TXEN=0x01; while(SERCOM0->USART.SYNCBUSY.bit.CTRLB ) { ; }
SERCOM0->USART.CTRLB.bit.RXEN=0x00; while(SERCOM0->USART.SYNCBUSY.bit.CTRLB ) { ; } // If you don't want to receive your own transmission

```

Hope it helps.

---
Tags: communication, atmel, samd21g, mkr-gsm-1400
---


title: Web page using bluetooth?

text:
# Question
Title: Web page using bluetooth?
I have a project where I read 2 sensors using an esp32 and also have an web server. I can connect using mobile phone and display the page where I see info about the sensors (using web sockets to update the info on the page very quickly ) and also send some commands back to esp32. Is working fine, just the issue that when I am connected to esp I don t have internet on my phone anymore (which is a normal thing:) ). My question is if I can achieve same but using bluetooth instead wifi ? Is there any way to have a "web page" using bluetooth ? Thank you

# Answer
No. There is no such facility in Bluetooth to provide such a feature. That's not to say that technically it can't be done, there just isn't any software (a web browser) that would support it.

Instead you would need to use a Bluetooth-enabled app on the smartphone to communicate with the ESP32 over Bluetooth and display the data / provide control natively. Such an app would probably have to be written by you since it would be specific to the way you are working, unless you can find a generic app that lets you design an interface for your project and then communicate using a documented protocol that you would then have to implement on the ESP32.

---

An alternative is to just reverse everything. Instead of having your phone connect to the ESP32 then connect to a webserver on it just have the ESp32 connect to your phone when your phone is set to WiFi Hotspot mode. You can still then get your phone to connect to the webserver on the ESP32, and your phone also has mobile internet. If course, if you are wanting internet through a WiFi connection for your phone then you can't do that. However, your ESP32 can then just also connect to your WiFi router so there is nothing to change on your phone. You just browse to the webserver on the ESP32 through your local WiFi network.
> 3 votes

# Answer
There is an experimental feature called the Web Bluetooth API. You could host a single file on a Webserver which then interacts via Bluetooth with your ESP. Keep in mind that aside from localhost you have to use https as protocol. Here is a Tutorial that shows how you can read and write to Bluetooth caracteristics using JavaScript.
> 2 votes

# Answer
Program your ESP32 to connect to your wifi - it then gets its own IP address on your LAN (e.g. 192.168.1.123 ) - then connect to your ESP from your phone (or anything else on your LAN).

Have you tried micropython? Works amazing on esp32 - makes everything super easy
> 1 votes

---
Tags: bluetooth, esp32, web
---


# Question
Title: Can I use SPI-related pins as a Digital Output?
I am trying to use an esp32 (NodeMCU-32s) as a ringlight controller for my camera. All it should do is sense when an input pin goes low (the camera's output connects to ground when the shutter goes off) which is easy to detect with a simple digitalRead(). If low, then it raises 6 pins with digitalWrite() which are connected to transistors which let current flow from a 24v power supply and light up 6 banks of white LEDs. This entire setup was working great on an esp32wroom I bought from our school's shop - like I said it is very simple - but after ordering more esp32's online, I was greeted with slightly different looking ones that don't behave the same even when running the exact same code. Yes, I have verified that the pinout is the same on these two boards, although the footprint of the online boards (best datasheet I could find linked above) is one breadboard slot thinner.

#### Expected behavior:

I power it on, and nothing should happen until I connect pin 14 to ground, then the lights should turn on for a tenth of a second, then back off.

#### Actual Behavior:

I power it on, 3 banks of lights turn on rather dimmly. The other three stay off. When I connect pin 14 to ground, the three that were off turn on for a tenth of a second, then back off. While they are on, a blue light on the nodemcu-32s dev board turns on as well...

I did some digging:

On this random nerd tutorials website I found code that identifies which pins are your board's default SPI pins and when I ran it, I found that 3 of the 6 pins I was currently using (pins 23, 19, and 5) are SPI-related ones. These were in fact the pins that behaved correctly (they were off until 14 was pulled low.)

I am not sure if this is related to the root cause of my issue or not, but it seems suspicious. Any tips from you wise arduino wizards would be appreciated - this was supposed to be simple!

#### Code:

Below is the code I am using. You can ignore the rgb LED stuff (LED\_PIN, NUM\_LEDS, BRIGHTNESS, etc.) All that matters for what I am trying to get working here are the led banks connected to pins 23, 21, 19, 5, 16, and 2. I intentionally avoided pins 6-11 because many sites were saying to avoid them.

```
#include <Adafruit_NeoPixel.h>

#define LED_PIN 15      // Pin connected to the Data Input of WS2812B
#define NUM_LEDS 24     // Number of WS2812B LEDs in the strip
#define BRIGHTNESS 200  // Set the brightness (0-255)

#define SHUTTER_PIN 14  //Pin connected to the shutter signal of the cameras via 3.5mm jack
Adafruit_NeoPixel strip;

void setup() {
  // setup code here, to run once:
  pinMode(23, OUTPUT); // set each bank of 6 White Leds as outputs
  pinMode(21, OUTPUT);
  pinMode(19, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(16, OUTPUT);
  pinMode(2, OUTPUT);

  // set the shutterPin as a normally-high input
  pinMode(SHUTTER_PIN, INPUT_PULLUP);

  // To control rgb leds
  strip = Adafruit_NeoPixel(NUM_LEDS, LED_PIN, NEO_GRB + NEO_KHZ800);
  strip.begin();
  strip.setBrightness(BRIGHTNESS);
  strip.show();

 // Initialize all pixels to off
  digitalWrite(23, LOW);
  digitalWrite(21, LOW);
  digitalWrite(19, LOW);
  digitalWrite(5, LOW);
  digitalWrite(16, LOW);
  digitalWrite(2, LOW);
}

void loop() {
  //main code here, to run repeatedly:
  // if the shutter signal drops, flash on and off
  if (digitalRead(SHUTTER_PIN) == 0) {
    digitalWrite(23, HIGH);
    digitalWrite(21, HIGH);
    digitalWrite(19, HIGH);
    digitalWrite(5, HIGH);
    digitalWrite(16, HIGH);
    digitalWrite(2, HIGH);
    delay(500);
    digitalWrite(23, LOW);
    digitalWrite(21, LOW);
    digitalWrite(19, LOW);
    digitalWrite(5, LOW);
    digitalWrite(16, LOW);
    digitalWrite(2, LOW);
    delay(500);
  }
}

```

# Answer
From the schematics, I can see that IO2 is for the board's blue LED. So that's probably your first problem... From this PDF, I see that IO21 is VSPIHD, Hold for Flash chips. No good. IO16 is HS1\_DATA4, also used for the Flash chip. Also no good. You'll have to pick other pins.

The other issue is SIX pins supposed to deliver 3.3 volts at the same time. On a small ESP board. Not sure that's gonna happen...
> 2 votes

# Answer
I'm still not quite sure what's going on, but to troubleshoot this I would do the following:

* First of all, verify it's not a faulty board and try it with another one of the new ones that you've got. If that doesn't help, then do the following:
    + Move the digitalWrite-s up, above the NeoPixel initialization code. See if that helps with the start-up.
    + If that doesn't help, add pull-down resistors to the LED outputs (try 10kOhm).
    + The blue LED lights up because GPIO 2's output is connected to it, looking at the schematic on the website you've linked. You might want to switch this one to a different GPIO on the board you're using.
    + Check the transistor circuits for the LEDs that are not functioning correctly. You've not posted anything related to it, so I can't help you much there, but if you do link it we might be able to use that info.
> 0 votes

---
Tags: esp32, nodemcu, spi, digitalwrite
---


# Question
Title: Arduino not reacting sometimes when reading serial commands
When I am sending hex numbers via computer to the arduino leonardo, it sometimes won't react, but the serial monitor says that it was sent. My code;

```
    void setup()
{
  Serial.begin(9600);
  pinMode(9, OUTPUT);
  pinMode(A0, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
}

void loop()
{
  delay(100); // Wait for 100 millisecond(s)
  Serial.println(Serial.read());
  if (Serial.read() == 49) {
    Serial.println("left");
    analogWrite(9, 1023);
    digitalWrite(A0, HIGH);
    analogWrite(10, 1023);
    digitalWrite(11, LOW);
  }
  if (Serial.read() == 50) {
    Serial.println("right");
    analogWrite(9, 1023);
    digitalWrite(A0, HIGH);
    analogWrite(10, 1023);
    digitalWrite(11, LOW);
  }
  if (Serial.read() == 51) {
    Serial.println("backwards");
    analogWrite(9, 1023);
    digitalWrite(A0, LOW);
    analogWrite(10, 1023);
    digitalWrite(11, LOW);
  }
  if (Serial.read() == 52) {
    Serial.println("forwards");
    analogWrite(9, 1023);
    digitalWrite(A0, HIGH);
    analogWrite(10, 1023);
    digitalWrite(11, HIGH);
  }
  if (Serial.read() == 48) {
    Serial.println("stop");
    analogWrite(9, 0);
    digitalWrite(A0, LOW);
    analogWrite(10, 0);
    digitalWrite(11, LOW);
  }
}

```

When I send the numbers 1,2,3,4, and 0, it reads what the command does. Pins A0 and D11 are direction control for the motor controller, and pins D9 and D10 are speed.

# Answer
> 3 votes
> ```
> Serial.println(Serial.read());
> if (Serial.read() == 49) {
>
> ```

You are doing two reads here, not one. So you are reading and displaying, and then reading a **second** byte (not the one you displayed).

Much better would be:

```
int cmd = Serial.read();
Serial.println(cmd);
if (cmd == 49)  {
  ... do something ...
} else if (cmd == 50)  {
  .. do something else ...
}

```

And so on.

Also, why use numbers when you can show the ASCII characters? eg.

```
int cmd = Serial.read();
Serial.println(cmd);
if (cmd == '1')  {
  ... do something ...
} else if (cmd == '2')  {
  .. do something else ...
}

```

You may also want to consider using:

```
if (!Serial.available())
    return;

```

That way you don't test for serial data that does not exist.

Why the delay?

---
Tags: serial, motor, code-review
---


# Question
Title: How can I switch the power on/off to cut BIG currents (200A)?
Context: I have an off-grid cabin with PV powered 12V DC. I want to cut power to an inverter (12V DC -\>220V AC) when I leave by pressing a button as it draws too much in standby.

Most relays I have seen that can be connected to the Arduino typically handle 10A. My inverter draws up to 180A@12V at full power (2000 W), which is way more than anything I have seen. How can I control the power to this inverter?

Someone told me of hacks that utilize the fact that you get manual switches/relays that handle big current, so you can use the Arduino to control a motor pressing the physical switch, but the concept seems somewhat brittle ... Any other takes?

```

            ┌────────────┐
            │  PV array  │
            └──────┬─────┘
                   │
             ┌─────┴───┐
             │ Charger │
           ┌─┴─────────┘
           │
           │
  ┌────────┴──┐         ┌─────────┐
  │ Batteries ├─────────┤Inverter ├────────────┐
  └────────┬──┘         └─────────┘            │
           │                                   │
           │                          ┌────────┴─────┐
           │                          │220V circuit  │
       ┌───┴───────────────┐          │  w/appliances│
Has    │ Fuse box          │          └──────────────┘
on/off │ / 12v distribution│
switch!└───────────────────┘

        ┌──────────────┐
        │12V appliances│
        └──────────────┘

```

# Answer
You might look for something like a "starter relay" for an engine. Those switch on 12 V and can handle currents of 150A and more. I've seen various models on the site of my favorite distributor.

**Check the data sheet to make sure the relay can handle a continuous current of 180A**, as many starter relays can only handle the current for short periods of time (you're not running the starter motor of an engine for more than a few seconds). Other possible types are 12V-industry-rated high-current relays. Also mentioned in a comment above: The hold-current of the relay shouldn't be to big, so you don't waste energy just for the switch.

You might need to use a 2-step solution, to first convert the 5V output of the Arduino to 12 V to control the relay. (use a small relay for this, or just a mosfet).
> 0 votes

---
Tags: relay, switch
---


# Question
Title: Getting a strange symbol when pressing buttons in a USB keyboard connected to the Arduino GIGA R1
I am using the following code:

```
#include "USBHostGiga.h"

//REDIRECT_STDOUT_TO(Serial)
Keyboard keyb;
HostSerial ser;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  while (!Serial);
  pinMode(PA_15, OUTPUT);
  keyb.begin();
  ser.begin();
}

void loop() {
  if (keyb.available()) {
    auto _key = keyb.read();
    Serial.println(keyb.getAscii(_key));
  }
  while (ser.available()) {
    auto _char = ser.read();
    Serial.write(_char);
  }
  //delay(1);
}

```

from here: https://docs.arduino.cc/tutorials/giga-r1-wifi/giga-usb

I am using Arduino GIGA R1 on which I have connected a USB keyboard and I press buttons. I see the results on the Serial. However, I face the following problem: When I press a button, apart of the letter I get also a square next to it. For instance, let's say I press the 'A' letter. In the serial I get 'A' letter + a square symbol. When I press 'B', I get 'B' + a square symbol, etc. I am trying for 2 days to fix it, I tried to read the button as a char array with two positions and delete the \[1\] where the square should be, but nothing worked. The `auto` type is very strange in order to make a type casting, because the Arduino IDE continuously shows me error. I cannot find a way to remove the strange 'square' ASCII character which I take with each letter pressed...The only things I noticed is that the square ASCII character is displayed the time I release the keyboard button, and also it delays to appear when I increase the delay ms in the `delay(...);` command. Has anyone any idea how to solve this?

# Answer
> 0 votes
I don't have GIGA R1, so no practical way to test this. I also cannot explain why it's showing up as square for you. It is common behaviour for character codes that don't have a font glyph to render in that way, but the one in question (null character) does not do that for me under the 1.x 2.x IDEs.

However, the rest of what follows may help.

According to github, the type that is returned by `.read()` is `HID_KEYBD_Info_TypeDef`, so if you want you should be able to:

```
const HID_KEYBD_Info_TypeDef _key = keyb.read();

```

However, there's not much wrong with using `auto` here. So far as I can tell, what you're really receiving is the content of Boot mode HID reports. Not *individual* key information really, but rather the state which may include up to 6 pressed keys. If you're only pressing one key (one *non-shift state key*; as in not "shift", "control", "alt". etc, it shows up in array index 0, which is what getAscii is ultimately interpreting.

So when you release the key (all of them) you are getting a report with nothing (no key code; represented with a zero value) in `keys[0]`, and so there's nothing there from which to get an ASCII code. What it seems to be doing is translating the 0 value that's there into another zero.

So, it would seem all you need to do is check to see if it's a zero after the call to `getAscii`, e.g.:

```
if (keyb.available()) {
  const auto keyboard_input_report /*not really a key*/ = keyb.read();
  const auto first_as_ascii = keyb.getAscii(keyboard_input_report);
  //  where getAscii really means getAsciiCodeOfFirstkeyIfThereIsOneInTheReport
  if (first_as_ascii != 0) {
    Serial.println(first_as_ascii);
  }
}

```

You could to check before translation with `if (keyboard_input_report.keys[0] != 0) {`. However, the former may make more sense. Because not every key on the keyboard will map unto may onto an ASCII code value anyway. E.g. ASCII does not represent the arrow keys, function keys, or page-up/page-down.

In any case, this code may have issues if multiple keys are pressed. It looks like doing so correctly would involve using the internals of `getAscii` to consult the translation tables for all six of the entries in the report's `keys` array.

---
Tags: usb
---


title: Use class object inside an ISR

text:
# Question
Title: Use class object inside an ISR
I have to simulate an ADC that behaves as an I2C slave. The simulated values that the ADC shall expose are sent over serial, saved on an attribute and are requested by a master device over I2C.

A simplified solution is the following. I have a struct `ADC` that describes the converter:

```
struct ADC
{
  uint32_t register_1;
  uint32_t register_2;

  void write_register_1(uint32_t data){
    register_1 = data;
  }

  void write_register_2(uint32_t data){
    register_2 = data;
  }

  uint8_t read(){
    return register_1;
  }

  // some other methods to setup...
};

```

In `loop()`, I read the serial in order to update the `ADC::register` value and in the `onRequest` handler I eventually send the requested data by accessing `ADC::register`:

```
ADC adc{};

void setup(){
  // setup adc, Wire and Serial here
  Wire.onRequest(slaveTransmitterHandler)
}

void loop(){
  if (Serial.available() > 0)
  {
     // read serial, parse received data and check them
     uint32_t data = parse_serial(); // do anything is needed to check data...

     // update adc attribute
     uint8_t oldSREG = SREG;
     noInterrupts(); // disable interrupts to update uint32
     adc.write_register_1(data);
     SREG = oldSREG;
  }
}

void slaveTransmitterHandler(){
  Wire.beginTransmission(ADDRESS);
  Wire.write(adc.read());
  Wire.endTransmission();
}

void slaveReceiverHandler(){
  uint32_t i2c_received_data;
  while (Wire.available){
    // fill i2c_received_data with Wire.read()
  }
  adc.write_register_2(i2c_received_data);
}

```

I'm not sure if I have to declare the `adc` object as `volatile` (this would mean to declare all `ADC` methods and variables as volatile). Is it safe to use an object inside the I2C handler called by the I2C interrupt?

As far as I know, it is not (I can find no reason why it should be different from non-class variables), but I have always worked with non-class variables and never with cpp objects. Also, I can't find any information about this topic.

It could be possible that I'm wrong with the whole design, even if it seems to me to be very consistent. I'm open to change it for something better, so please if this design is nonsense, comment on that! I'm here to learn :)

Thanks.

Luca

**Edit**: Some clarification, since my question seems not to be clear enough: I'm doing HIL simulation, that is simulating the real hardware with its real interfaces with a simulated environment (that includes sensors and actuators). See here for more info.

One of my sensors measures a voltage and stores it in a register of an ADC (that has multiple registers). I'm simulating the behaviour of ADC registers in Arduino, and they shall communicate via I2C with the real hardware.

Hope this is more clear now.

# Answer
If this is a simulation, and not actually using interrupts, then you hardly need to declare anything volatile. However your use of the Wire library makes it look less like a simulation. Personally I think your problem is under-explained. Please post all of your code. If you are simulating you won't need to worry about hardware interrupts. If you are using the Wire library you will.

Your other post Get address of a I2C transaction when multiple addresses are registered seems to be relevant here.
> 0 votes

---
Tags: i2c, interrupt, cpp
---


# Question
Title: Stabilization of HX711 and Faster Sampling. Code improvements
Helllo,
I am using load cells in my research project. I have 4 load cells and have connected 4 HX711 modules (one to each load cell) and have connected them to the arduino uno.

I have taken the example code given for 2 load cells and modified it for 4 load cells. My complete code is available here. The original HX711 2 load cell library example code is available here.

I have referred the source code but still have the following questions:
Q1) The following part of the code:

```
boolean _tare = false; //set this to false if you don't want tare to be performed in the next step
byte loadcell_1_rdy = 0;
byte loadcell_2_rdy = 0;
byte loadcell_3_rdy = 0;
byte loadcell_4_rdy = 0;
while ((loadcell_1_rdy + loadcell_2_rdy + loadcell_3_rdy + loadcell_4_rdy) < 4) { //run startup, stabilization and tare, both modules simultaniously
    if (!loadcell_1_rdy) loadcell_1_rdy = LoadCell_1.startMultiple(stabilizingtime, _tare);
    if (!loadcell_2_rdy) loadcell_2_rdy = LoadCell_2.startMultiple(stabilizingtime, _tare);
    if (!loadcell_3_rdy) loadcell_3_rdy = LoadCell_3.startMultiple(stabilizingtime, _tare);
    if (!loadcell_4_rdy) loadcell_4_rdy = LoadCell_4.startMultiple(stabilizingtime, _tare);
  }

```

Is this written correctly? Can this be removed or is this part necessary?

Q2) I wish to increase the sampling rate so I am going to increase the baud rate to 115200 or higher. Does this have any affect on the previous question? Since, the source code seems to have been written for 10SPS.

# Answer
> -1 votes
It is better to use a chip from Analog Device AD7799. It has relatively high accuracy and no swimming, compared to the HX711. When connecting 2 load cells of 50 kg on the pavement the scheme has an accuracy of 10 grams. I use the AD779x library.h and an example program that appears in the file-examples menu in arduino, after installing the library. When hx-711 is connected to the same the accuracy of my sensors was 30 grams, I measured the accuracy of both ADCs for 10 minutes. I ordered AD7799 on Ali for 2-3$ . You need to take it together with the adapter for the ssop16 c chip the distance between the terminals of the adapter is 0.65 mm. You also need to take "solder paste with solder", because the conclusions are too small and close. I took the SMD capacitors from the damaged matplate, measuring them capacity by tester. When the load cell is warmed up with a hairdryer, the data changes greatly. Perhaps you need to put a digital ds18b20 thermal sensor on the thermal sensor on the thermal watch. With even a short - term when you touch the load cell with your finger, the readings also change greatly due to the sensor warming up from body heat. If you touch through several layers of folded paper, the sensor does not warm up and the readings do not change. Those who will test load cells by pressing them with their finger should remember that in a few seconds, after touching the load cell with their finger, the heat will reach the sensor's sensing element along its metal body and the values will float up or down by tens of grams, depending on the connection scheme, sensor type, duration touching. Press the sensors with any objects, not with your hand directly. L The inductance may or may not be set. It is possible to connect without a reference voltage source TL431, and directly from the arduino 5v with a filter of 2 capacitors (as shown in the diagram). I first connected without it and the readings were quite normal. We need to try... The power source used from Hi-link.

---
Tags: arduino-uno
---


# Question
Title: How do you use two piezos at the same time?
I'm trying to replicate a short music clip with two piezos, and I want them to play at the same time. While the right piezo is playing, I want the left one to still be looping. The problem is, I'm not sure how.

```
//Left hand
const int leftPin = 10; /Left pin
const int leftTones[] = {123.4, 103.83, 138.59, 92.50}; //The looping left tones
const int leftDelays[] = {700, 1300, 900, 900}; //How long those tones last
const int leftNotes = 4; //How many left notes there are

//Right hand
const int rightPin = 2; //Right pin
const int rightTones[] = {739.99, 587.33, 587.33, 659.25, 698.46, //The looping right tones
659.25, 587.33, 554.37, 587.33, 659.25, 739.99, 987.77, 493.88,
554.37, 587.33, 659.25, 587.33, 554.37, 880.00, 783.99, 739.99,
587.33, 587.33, 659.25, 698.46, 659.25, 587.33, 554.37, 587.33,
659.25, 739.99, 987.77, 987.77, 1108.73, 1174.66, 783.99, 739.99,
698.46, 1174.66, 1318.51};
const int rightDelays[] = {700, 1000, 100, 100, 300, 300, 200, //How long those tones last
300, 300, 200, 700, 700, 250, 150, 200, 400, 300, 300, 400, 200,
700, 1000, 100, 100, 300, 300, 200, 400, 300, 200, 700, 700, 300,
200, 400, 300, 200, 400, 300, 200};
const int rightNotes = 40; //How many right notes there are

void setup(){
    pinMode(leftPin, OUTPUT);
    pinMode(rightPin, OUTPUT);
    delay(1000);
}

void loop(){
  for (int i = 0; i < leftNotes; i++){
    tone(leftPin, leftTones[i]);
    delay(leftDelays[i]);
    noTone(leftPin);
  }
  for (int i = 0; i < rightNotes; i++){
    tone(rightPin, rightTones[i]);
    delay(rightDelays[i]);
    noTone(rightPin);
  }
}

```

With this code, the left piezo plays first, and then the right piezo plays. It should be at the same time.

Edited Code:

```
long currentMillis = 0;
long leftPreviousMillis = 0; // previous time for left hand
long rightPreviousMillis = 0; // previous time for right hand

const int leftNotes = 4; // The amount of left notes
const int rightNotes = 40; // The amount of right notes
int leftIndex = 0; // The specific index for the left piezo
int rightIndex = 0; // The specific index for the right piezo
const int leftPin = 10; // The left piezo
const int rightPin = 2; // The right piezo

// The specific left pitches (as float)
const float leftTones[] = {123.4, 103.83, 138.59, 92.50};
// How long the left pitches last for
const long leftDelays[] = {700, 1300, 900, 900};

// The specific right pitches (as float)
const float rightTones[] = {739.99, 587.33, 587.33, 659.25, 698.46, 659.25, 587.33, 554.37, 587.33, 659.25, 739.99, 987.77, 493.88, 554.37, 587.33, 659.25, 587.33, 554.37, 880.00, 783.99, 739.99, 587.33, 587.33, 659.25, 698.46, 659.25, 587.33, 554.37, 587.33, 659.25, 739.99, 987.77, 987.77, 1108.73, 1174.66, 783.99, 739.99, 698.46, 1174.66, 1318.51};
// How long the right pitches last for
const long rightDelays[] = {700, 1000, 100, 100, 300, 300, 200, 300, 300, 200, 700, 700, 250, 150, 200, 400, 300, 300, 400, 200, 700, 1000, 100, 100, 300, 300, 200, 400, 300, 200, 700, 700, 300, 200, 400, 300, 200, 400, 300, 200};

void setup() {
  pinMode(leftPin, OUTPUT);
  pinMode(rightPin, OUTPUT);
  Serial.begin(9600);
  delay(1000);
  tone(rightPin, rightTones[rightIndex]);
  tone(leftPin, leftTones[leftIndex]);
}

void loop() {
  currentMillis = millis();
  // Left hand notes
  if (currentMillis - leftPreviousMillis >= leftDelays[leftIndex]) {
    noTone(leftPin); // Turn off the left note
    leftPreviousMillis = currentMillis;
    leftIndex++;
    if (leftIndex == leftNotes) // Reset left hand index
      leftIndex = 0;
    tone(leftPin, leftTones[leftIndex]); // Turn on the new left note
  }

  // Right hand notes
  if (currentMillis - rightPreviousMillis >= rightDelays[rightIndex]) {
    noTone(rightPin); // Turn off the right note
    rightPreviousMillis = currentMillis;
    rightIndex++;
    if (rightIndex == rightNotes) // Reset right hand index
      rightIndex = 0;
    tone(rightPin, rightTones[rightIndex]); // Turn on the new right note
  }
}

```

I've done some testing, and I think it's a problem with the tones function. Right now, this code only plays the right hand notes. The problem is this part:

```
tone(rightPin, rightTones[rightIndex]);
tone(leftPin, leftTones[leftIndex]);

```

When I do this:

```
tone(leftPin, leftTones[leftIndex]);
tone(rightPin, rightTones[rightIndex]);

```

Only the left hand notes are heard. But, it's not perfect. There's little beeps and buzzes every now and then. This leaves me with the conclusion that if there are two tones at the same time, it only plays the one it reads first. I've tested it with simpler code, and it stands true.

So that begs the question, is it even possible to use two piezos at the same time with one Arduino? I'm testing it with the Arduino simulator tinkercad, so maybe that's the problem? My code works for the left piezo, and the right piezo. But when you put them together, everything messes up.

# Answer
It's always good to look at the documentation when you have a question about how a piece of code works. In this case I looked at the page for the tone function which can be found here. https://www.arduino.cc/reference/en/language/functions/advanced-io/tone/

And the second sentence on that page says it all:

> Only one tone can be generated at a time. If a tone is already playing on a different pin, the call to tone() will have no effect. If the tone is playing on the same pin, the call will set its frequency.
> 0 votes

# Answer
> How do you use two piezos at the same time?

Consider using a finite state machine type of programming method.

As has been discovered, using calls to the delay() function (where the processor does nothing) blocks any other feature of the sketch (user's program). In a finite state machine programming pattern, there are no calls to the delay() function. Instead the sketch's loop() function is allowed to execute as fast as possible. The trick is to control what code is executed in the loop() function based on a state machine. And, in this case, use time to change between different states.

In an Arduino platform (the hardware and software you never or seldom see that makes up an Arduino) a counter is always tracking elapsed time. Use the millis() function to retrieve the current value in milliseconds (1000 milliseconds = 1 second) each time through the loop() function. Consider using a 2 state state machine. In the 1st state get the current counter value, add to it the delay in milliseconds of the next note, start the note playing and finally change the variable tracking states to the 2nd state. The next time through the loop() function, while in the 2nd state, check if the response from calling millis() again is larger then the value saved while in the 1st state. If it is, stop playing the note and change the variable tracking states to the 1st state.

Once working, create a second similar state machine to play the counter melody.

However, as delta-g has pointed out, the library picked out by the O.P. apparently can not play more than one note at a time. But,ve7jro has pointed out that this Arduino tunes library may be able to satisfy the requirement of playing 2 notes at the same time as stated in the O.P.'s question.

Creating a state machine in a invaluable programming lesson. However, this Arduino state machine library is available should the programmer wish to take advantage of it.
> 0 votes

---
Tags: c++, piezo
---


# Question
Title: LILYGO TTGO T-Display cannot detect MPU 6050 Accelerometer, Gyroscope and Temperature Sensor
I've been trying to connect a MPU 6050 Accelerometer, Gyroscope and Temperature Sensor to a LILYGO TTGO T-Display to get readings displayed on the serial monitor (for starters). The wiring is pretty straightforward. I need to power up the MPU6050 with 3V, and connect the SDA and SCL. I followed this tutorial (https://randomnerdtutorials.com/esp32-mpu-6050-accelerometer-gyroscope-arduino/).

This is the code used:

```
#include <Adafruit_MPU6050.h>
#include <Adafruit_Sensor.h>
#include <Wire.h>

Adafruit_MPU6050 mpu;

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

  Serial.println("Adafruit MPU6050 test!");

  // Try to initialize!
  if (!mpu.begin()) {
    Serial.println("Failed to find MPU6050 chip");
    while (1) {
      delay(10);
    }
  }
  Serial.println("MPU6050 Found!");

  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_5_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;
  }

  Serial.println("");
  delay(100);
}

void loop() {
  /* Get new sensor events with the readings */
  sensors_event_t a, g, temp;
  mpu.getEvent(&a, &g, &temp);

  /* Print out the values */
  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");

  Serial.print("Rotation X: ");
  Serial.print(g.gyro.x);
  Serial.print(", Y: ");
  Serial.print(g.gyro.y);
  Serial.print(", Z: ");
  Serial.print(g.gyro.z);
  Serial.println(" rad/s");

  Serial.print("Temperature: ");
  Serial.print(temp.temperature);
  Serial.println(" degC");

  Serial.println("");
  delay(500);
}

```

The pinout config for the TTGO T Display is shown below:

I connected the pins based on this as follows:

TTGO MPU6050

3V ----\> Vcc

G ----\> Gnd

22 ----\> SCL

21 ----\> SDA

But I keep getting the following error on the serial monitor.

```
ets Jul 29 2019 12:21:46

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0030,len:1324
ho 0 tail 12 room 4
load:0x40078000,len:13508
load:0x40080400,len:3604
entry 0x400805f0
Adafruit MPU6050 test!
Failed to find MPU6050 chip

```

What is strange is that the MPU 6050 works perfectly fine with the same pin connection on the normal Node MCU ESP 32 system. Any idea why it won't work on the TTGO?

# Answer
> 0 votes
I had exactly the same error (Failed to find MPU6050 chip)on the same program with the same tutorial. I thought it was this, that, and an act of nature. I hade proven the MPU6050 worked fine and the ESP32 worked fine. EVENTUALLY I realised it was dead simple, the ESP32 ( a cheapo one) had different pinout to the one in the tutorial, SCL,SDA and 3.3v were in the wrong place even though the red LED illuminated on my MPU6050 board. Anyway I wired it correctly and it works just fine and the Webserver one too. I did not do the display one! ( Don't take anything for granted). I do not know which incarnation of the MPU6050 you are using but when using mine (looked identical as the one in the tutorial) on an ESP8266 the I2C addressing was a bit finicky and I had to take the address connection hard to GND with a wire to get it to run consistently, that too caused the same error (Failed to find MPU6050 chip).

---
Tags: i2c, esp32, nodemcu, display, mpu6050
---


# Question
Title: is #ifdef __SD_H__ considered a bad practice?
Say I'm working on a library^**1** to which I want to add support for `SD.h`^**2** but knowing for a fact that many microcotrollers don't support `SD.h` *(therefore they result in compilation errors \[eg. Attiny85\])* I don't want to just `#include <SD.h>` *(or even `#ifndef __SD_H__` then `#include <SD.h>`)* in `Mylibrary.h` and make it totally unusable for some microcontrollers. So I was wondering, is it considered ok to just add the functionality like...

```
// Mylibrary.h

#ifdef __SD_H__
    // Save functionality for those including `SD.h` to their `sketch.ino`
    void Mylibrary::save(String filename){
        SD.open(filename, FILE_WRITE)
        // ...
    }
#endif

```

...without ever including the `SD.h` in `Mylibrary.h` and hence force the user whenever he\she wants to use some SD functionallity, to just include `SD.h` in his\her `sketch.ino`? **+***(it sound exhausting to do something like this for every MCU, as an alternative way)*

\[**1**\] *(in my case this library)*
\[**2**\] *(in my case something related to this)*
**PS.** The reason I'm asking is because I don't remember seeing it anywhere being used that way and I'm slightly confused as to if this is the right or wrong thing to do so

# Answer
Yes, it is in general a bad practice to use include guard define to detect if the header file is included. It will work only in a header file in a compilation unit which includes the detected header file.

In Arduino all ino files of the sketch are one compilation unit. But every C or C++ file is a separate compilations unit. They would not 'see' the include guard from an include in the ino file(s).

If you want to use the include guard define, don't relay on it exclusively. Use your own define and set it if you detect the include guard. This way user can set it if theirs SD library has a different name for the include guard.

```
#ifdef __SD_H__
#define XY_USE_SD_LIB
#endif

#ifdef XY_USE_SD_LIB
    // Save functionality for those including `SD.h` to their `sketch.ino`
    void Mylibrary::save(String filename){
        SD.open(filename, FILE_WRITE)
        // ...
    }
#endif

```

I use this in my popular ArduinoOTA library here.

There is other way to detect includes and it works across compilation units, but it doesn't work on all Arduino platforms. It is the `__has_include` 'directive'. I use it here.
> 7 votes

# Answer
I don't think this will work, however you could try it and see. Just set the board type to something that doesn't support SD.h.

My problem would be that your library is a separate compilation unit (ie. file) that would be compiled against the things *you* put as header files.

If your library user uses SD.h in the main .ino file, then your library (which is compiled separately) would not know about that. In other words, it wouldn't know whether or not to *implement* the Mylibrary::save function.

I think a fairly simple solution would be to put a define in the include file for your library, eg.

```
#define USE_FILE_SAVING false

```

Then check that in your code. You don't need a whole list of MCUs, just inform the user that if they want file saving implemented to change that one line.

---

For more information see How the IDE organizes things
> 2 votes

---
Tags: programming, library, c-preprocessor
---


# Question
Title: Compilation error: 'Serial' does not name a type
```
#include <IRremote.h>

IRrecv IR (11);

Serial.begin(9600);

void setup() {
  // put your setup code here, to run once:
  IR.enableIRIn();
}

void loop() {
  // put your main code here, to run repeatedly:
  if (IR.decode()){
    Serial.println(IR.decodedIRData.decodedRawData, HEX);
    delay(1500);
    IR.resume();
  }
}

```

# Answer
In C & C++, executable statements must be within a function. Your third statement, `Serial.begin(9600);` is (or should be) executable but since it is outside any function, the compiler tried to interpret it as a declaration - thus, the error.
> 2 votes

---
Tags: arduino-uno, serial
---


# Question
Title: Using Adafruit RTClib without fragmenting the heap
I'm getting ready to add DS1307 support to my Arduino app, and was *horrified* when I looked at the sourcecode for the RTC\_DS1307 class in Adafruit's RTClib library...

```
DateTime RTC_DS1307::now() {
  uint8_t buffer[7];
  buffer[0] = 0;
  i2c_dev->write_then_read(buffer, 1, buffer, 7);

  return DateTime(bcd2bin(buffer[6]) + 2000U, bcd2bin(buffer[5]),
                  bcd2bin(buffer[4]), bcd2bin(buffer[2]), bcd2bin(buffer[1]),
                  bcd2bin(buffer[0] & 0x7F));
}

```

... and realized that it appears to be instantiating a new throw-away DateTime object on the heap every time you call now()... which AFAIK, is the **ultimate** Arduino C++ taboo.

I was about to tear into the class and rewrite it to reuse a singleton DateTime object that gets created once and reused forever... but then I remembered about return value optimization.

**Is** this actually a scenario where RVO will automagically kick in to save the day and prevent a heap-allocation (by pre-allocating space for the DateTime object on the caller's stack prior to calling `now()`), or is this library indeed doing something as taboo as I think it is?

# Answer
I wrote a minimal sketch that calls `RTC_DS1307::now()`, disassembled it, and here is what I saw:

* The caller allocates 6 bytes on the stack for holding the return value.
* It writes the address of this stack location in the register pair r25:r24, as per the AVR calling convention,1 then calls `RTC_DS1307::now()`.
* As the callee computes the fields of the resulting `DateTime` (by means of inlined calls to `bcd2bin()`), it writes them directly into the caller's stack frame, with no intermediate copy in RAM.

This looks to me like return value optimization.

**However**, in order to witness this behavior, I had to call `RTC_DS1307::now()` *twice*. If the method is called from a single place within the sketch, the compiler inlines it, and there isn't even a function call to begin with.

Then, of course, the heap is never touched.

1 *You would expect the `this` pointer to be passed as the first argument, in r25:r24. It would seem it has been optimized out, which makes sense given that there is only one `RTC_DS1307` object in the whole sketch.*
> 5 votes

# Answer
I think you are confusing the stack and the heap. For something to appear in the heap you would expect to see the words `new` or `malloc` which I don't see.

What is happening here is that a DateTime object is being created (in the stack frame of the current function) by `RTC_DS1307::now` which is being (presumably) copied into a variable of that type in the caller's stack frame when the function returns.

No memory is being wasted here.

---

> it appears to *literally* be instantiating a new throw-away DateTime object on the heap

What gives you that idea? The heap is not involved without you using `new` or `malloc`.

---

The heap is a block of memory used for dynamic memory allocation by using `malloc` or `new`, generally speaking. Typically it will be allocated past the place in RAM where variables are allocated (ie. after all the variables) and grow upwards, whereas the stack will be allocated at the end of available memory and grow downwards. Thus they don't clash until they collide, either by using too much stack (eg. by recursive function calls) or by allocating too much of the heap (by repeatedly calling `malloc` and without calling `free`).

When you use the heap, by using `malloc` you will get a *pointer* which you can then use, and pass around. That memory which you have reserved is yours until you free it, by literally calling `free`. In C++ something very similar is done by using `new` and `delete`.

If you don't call `malloc` or use `new` then you aren't using the heap, end of story.
> 4 votes

---
Tags: c++
---


title: Debouncing a button with interrupt

text:
# Question
Title: Debouncing a button with interrupt
I tried to follow the answer here: https://arduino.stackexchange.com/a/18545/51302

Unfortunately I can only get the interrupt to go once (on serial monitor is the time of that first interrupt), then nothing. I know this has already been answered but I don't understand the mistake and would appreciate help.

What I'm trying to do: get a button to set an interrupt to trigger foo and thus write the steps on the monitor.

I've left remarks to try and explain what I try to do, so it would be easier to understand what I left out or used incorrectly. Thanks.

```
#define IRF520 A2
#define BUTTON 3
static unsigned long last_press = 0;
static bool button_state = HIGH;             //pull up resistor
volatile bool interrupt_flag = 0;            //when the interrupt fires, button press or noise
bool is_pressed = false;                     //after checking that the button was really pressed
bool was_pressed = false;                    //last state of the button
unsigned long button_pause_duration = 20;        //pause required to accept press in ms
unsigned long interrupt_time=0;

void button_interrupt() {
  interrupt_flag = true;                      //can be a false alarm
  Serial.print("interrupt time: ");         //this is the onlt step that works
  Serial.print(millis());
  Serial.print("\n");
}

void setup() {
  Serial.begin(9600);
  pinMode(IRF520, OUTPUT); //A2 controls IRF520
  pinMode(BUTTON, INPUT_PULLUP);  //pin D2 and D3 are sutible for interrupts
  attachInterrupt(digitalPinToInterrupt(BUTTON), button_interrupt, FALLING);
}

void debounce_button() {
  if (digitalRead(BUTTON) != button_state) {
    button_state = digitalRead(BUTTON);         //if button changed state remember the new state
    interrupt_time=millis();
  }
  if (button_state == LOW) {
    last_press = millis();
    Serial.print("last_press was updated to: ");
    Serial.print(last_press);
    Serial.print("\n");
  } else {
    last_press = 0;
    interrupt_flag = false;
  }
  if ( last_press && (millis() - last_press) > button_pause_duration) {
    last_press = 0;     //set to 0 for the next check
    is_pressed = true;   //button was really pressed
    Serial.print("last_press was set to 0 and is_pressed to true - BUTTON WAS PRESSED at: ");
    Serial.print(millis());
    Serial.print("\n");
  }
}

unsigned int foo(bool is_pressed) {
  if (is_pressed) {
    Serial.print("foo is active, MOSFET does its thing");
    Serial.print("\n");
    }
  }
}

void loop() {
 if(interrupt_flag){
    Serial.print("the button is now being pressed: ");
    Serial.print(millis());
    Serial.print("\n");
 }
 debounce_button();
 foo(is_pressed);
}

```

# Answer
So, I grabbed a Mega and several pushbutton switches (one of which turned out to be a push-on, push-off, much to my bemusement), and ginned up a small Arduino program to illustrate an interrupt-driven button debounce technique. Please feel free to point out any and all errors ;-)

Here is a small program to debounce any momentary contact switch. The Mega interrupt line (pin 2, interrupt 0) triggers on any low-to-high or high-to-low transition. the interrupt service routine (ISR) simply sets a flag to TRUE and exits. If multiple interrupts occur before the loop() function can service the flag, the second and subsequent ISR calls do nothing (well, they set the flag, but since it was already set...). The loop() code looks for a set flag, and if it finds one, generates a 50uSec pulse on a selected pin, delays 100mSec, resets the flag, and exits. As long as the switch's contact bounce activity ceases before the 100mSec delay expires, one and only one pulse per transition will be generated. YMMV.

```
/*
Small program to demonstrate switch debounce technique using an interrupt
The ISR is called for low-to-high and high-to-low transitions, and may get
called multiple times per button press.  However, the code in loop() ensures
that each transition produces one and only one pulse per transition, assuming
the typical 10-20 mSec max bounce duration.

Note that if the line 'delayMicroseconds(50); //used to show multiple bounces'
is used instead of the line 'delay(100);//ignore bounces for 100mSec', then
multiple contact bounces will each generate their own 50uSec pulse.  This is
useful for O'scope diagnosis if you happen to have one.
*/

#include <elapsedMillis.h>
#include <PrintEx.h> //allows printf-style printout syntax

StreamEx mySerial = Serial; //added for printf-style printing

//pin assignments
const int LED_PIN = 13;
const int BUTTON_PIN = 2;
const int BUTTON_STATE_PIN = 3;

//variables
bool buttonState = 0;
bool blinkState = 0;

// ================================================================
// ===               INTERRUPT DETECTION ROUTINE                ===
// ================================================================

volatile bool Interrupt = false;     // indicates whether MPU interrupt pin has gone high
void BtnInterrupt()
{
    Interrupt = true;
}

// ================================================================
// ===                      INITIAL SETUP                       ===
// ================================================================

void setup() {
    // configure pins
    pinMode(LED_PIN, OUTPUT);
    pinMode(BUTTON_PIN, INPUT_PULLUP);
    pinMode(BUTTON_STATE_PIN, OUTPUT); //scope monitor pin
    digitalWrite(BUTTON_STATE_PIN, LOW);

    buttonState = digitalRead(BUTTON_PIN);
    mySerial.printf("Initial button state is %s\n", buttonState == LOW ? "LOW" : "HIGH");
    attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), BtnInterrupt, CHANGE);
}

// ================================================================
// ===                    MAIN PROGRAM LOOP                     ===
// ================================================================

void loop()
{
    if (Interrupt)
    {
        digitalWrite(BUTTON_STATE_PIN, HIGH);
        delayMicroseconds(50);
        digitalWrite(BUTTON_STATE_PIN, LOW);
        //delayMicroseconds(50); //used to show multiple bounces
        delay(100);//ignore bounces for 100mSec
        Interrupt = false;
    }
}

```

Here are two O'scope screen grabs. One shows the pulse train generated by a single button transition with a 50uSec delay, and the other shows the same switch with the 100mSec delay. In both photos, the horizontal time scale is 500uSec/cm
> 8 votes

# Answer
I *think* the problem is that you only trigger the interrupt when the button is pressed (interrupt FALLING)

Therefore, there is no opportunity to call debounce when the button is released.

Therefore, there is no way to change the button state variable back to HIGH (I.e. when the button is released).

To verify the hypothesis or gain some other insights, I suggest trying to put a debug statement in your loop similar to the following

```
  If (millis () >= debugTime) {
       DebugTime = millis() + 1000:   // output every second...
       Serial.print("value of button state is: ");
        Serial.println(button_state);
      // and a few other variables.
  }

```

I will leave it to you to properly declare debugTime (unsigned long) and choose a few other key variables (maybe interrupt flag) to print in the debug message block.

And i think you already have done so, but also delete the print statements in your ISR.
> 0 votes

# Answer
The problem is that you need to check whether the last interrupt was far enough in the past that the output can be considered stable. The most obvious solution to me is to have the ISR record the time it was called, and the main loop can simply check if that time is sufficiently before the current time. The comparison is very cheap, and doesn't require a delay. The "same record interrupt time and then compare" can cover multiple buttons on MCUs like the ATTINY85 which uses a single shared ISR. The disambiguation etc. resides outside the ISR.
> 0 votes

---
Tags: interrupt, button, debounce
---