message:
How to fix "expected primary-expression before '%' token" error code?

I'm trying to use this code to get temperature and humidity values from DHT11 sensor and send it to Python and I need to write the temperature and humidity values in the same line. But I keep getting the error code

> expected primary-expression before '%' token

How can I fix this?

    #include <dht.h>
    #include <stdio.h>
    int a = 0;
    int b = 0;
    char buffer [64];

    dht DHT;

    #define DHT11_PIN 7

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

    void loop(){
      a = DHT.temperature;
      b = DHT.humidity;
      int chk = DHT.read11(DHT11_PIN);
      sprintf(buffer, %d %d, a, b);
      Serial.print(buffer);
      delay(1000);
    }

body:
You are missing quotes on the second parameter of `sprintf`:

```
sprintf(buffer, "%d %d", a, b);
```


sender: user

message:
End stops for stepper motor

I need to add some end stops to this stepper motor code. I'm using one axis of a joystick to control a carriage that goes back and forth on a long screw. I have hall switches for both ends, I just want it to stop going in that direction when it triggers the switch.

I didn't write this code but it would work great if I could just add the end stops. If I have the switches connected to pins 2 and 3.

How could I write something like: if pin 2 goes high, stop motor in that direction, and then the same for pin 3 in the opposite direction?

```c++
#include <AccelStepper.h> // accelstepper library
AccelStepper stepper(1, 8, 9); // direction Digital 9 (CCW), pulses Digital 8 (CLK)

//Pins
const byte Analog_X_pin = A0; // x-axis readings
const byte enablePin = 7;

//Variables
int Analog_X = 0;             //x-axis value
int Analog_X_AVG = 0;         //x-axis value average
  //----------------------------------------------------------------------------
void setup() {
  Serial.begin(9600);
  //----------------------------------------------------------------------------
  //PINS
  pinMode(Analog_X_pin, INPUT);
  pinMode(enablePin, OUTPUT);
  //----------------------------------------------------------------------------
  InitialValues(); // averaging the values of the 3 analog pins (values from potmeters)
  //----------------------------------------------------------------------------
  // Stepper parameters
  // setting up some default values for maximum speed and maximum acceleration
  stepper.setMaxSpeed(2000);     //SPEED = Steps / second
  stepper.setAcceleration(1000); //ACCELERATION = Steps /(second)^2
  stepper.setSpeed(1000);
  delay(1000);
}

void loop() {
  ReadAnalog();
  stepper.runSpeed(); // step the motor (this will step the motor by 1 step at each loop indefinitely)
}

void ReadAnalog() {
  if (abs(Analog_X-Analog_X_AVG) > 50) {
    digitalWrite(enablePin, HIGH);  // enable the driver
    stepper.setSpeed(5*(Analog_X-Analog_X_AVG));
  } else {
    digitalWrite(enablePin, LOW);   // disable the driver
    stepper.setSpeed(0);
  }
  // Reading the potentiometer in the joystick:
  Analog_X = analogRead(Analog_X_pin);
  // if the value is 25 "value away" from the average (midpoint), we allow the update of the speed
  // This is a sort of a filter for the inaccuracy of the reading
  if (abs(Analog_X-Analog_X_AVG) > 50) {
    stepper.setSpeed(5 * (Analog_X-Analog_X_AVG));
  } else {
    stepper.setSpeed(0);
  }
}

void InitialValues() {
  //Set the values to zero before averaging
  float tempX = 0;
  //----------------------------------------------------------------------------
  // read the analog 50x, then calculate an average.
  // they will be the reference values
  for (int i = 0; i<50; i++) {
    tempX += analogRead(Analog_X_pin);
    delay(10); //allowing a little time between two readings
  }
  //----------------------------------------------------------------------------
  Analog_X_AVG = tempX/50;
  //----------------------------------------------------------------------------
  Serial.print("AVG_X: ");
  Serial.println(Analog_X_AVG);
  Serial.println("Calibration finished");
}
```

sender: assistant

body:
This is what I came up with. Note that the ReadLimits function is called after ReadAnalog and before runSpeed. In that order the stepper will not move in the direction of the limit switch, if it is pressed.

PS since you used `setAcceleration`, don't you need to call `run` instead of `runSpeed`?

```lang-cpp
void loop()
{
  ReadAnalog();
  ReadLimits();
  stepper.runSpeed(); //step the motor (this will step the motor by 1 step at each loop indefinitely)
}

void ReadLimits()
{
  if( digitalRead(2)==LOW && stepper.speed()>0 )//read input, assuming they have pull-up resistors.
  {
    stepper.setSpeed(0);
  }

  if( digitalRead(3)==LOW && stepper.speed()<0 )//read input, assuming they have pull-up resistors.
  {
    stepper.setSpeed(0);
  }
}
```

**edit** to avoid some confusion; here is the entire code with my suggestion embedded:
```lang-cpp
#include <AccelStepper.h> // accelstepper library
AccelStepper stepper(1, 8, 9); // direction Digital 9 (CCW), pulses Digital 8 (CLK)

//Pins
const byte Analog_X_pin = A0; // x-axis readings
const byte enablePin = 7;

//Variables
int Analog_X = 0;             //x-axis value
int Analog_X_AVG = 0;         //x-axis value average
  //----------------------------------------------------------------------------
void setup() {
  Serial.begin(9600);
  //----------------------------------------------------------------------------
  //PINS
  pinMode(Analog_X_pin, INPUT);
  pinMode(enablePin, OUTPUT);
  //----------------------------------------------------------------------------
  InitialValues(); // averaging the values of the 3 analog pins (values from potmeters)
  //----------------------------------------------------------------------------
  // Stepper parameters
  // setting up some default values for maximum speed and maximum acceleration
  stepper.setMaxSpeed(2000);     //SPEED = Steps / second
  stepper.setAcceleration(1000); //ACCELERATION = Steps /(second)^2
  stepper.setSpeed(1000);
  delay(1000);
}

void loop()
{
  ReadAnalog();
  ReadLimits();
  stepper.runSpeed(); //step the motor (this will step the motor by 1 step at each loop indefinitely)
}

void ReadLimits()
{
  if( digitalRead(2)==LOW && stepper.speed()>0 )//read input, assuming they have pull-up resistors.
  {
    stepper.setSpeed(0);
  }

  if( digitalRead(3)==LOW && stepper.speed()<0 )//read input, assuming they have pull-up resistors.
  {
    stepper.setSpeed(0);
  }
}

void ReadAnalog() {
  if (abs(Analog_X-Analog_X_AVG) > 50) {
    digitalWrite(enablePin, HIGH);  // enable the driver
    stepper.setSpeed(5*(Analog_X-Analog_X_AVG));
  } else {
    digitalWrite(enablePin, LOW);   // disable the driver
    stepper.setSpeed(0);
  }
  // Reading the potentiometer in the joystick:
  Analog_X = analogRead(Analog_X_pin);
  // if the value is 25 "value away" from the average (midpoint), we allow the update of the speed
  // This is a sort of a filter for the inaccuracy of the reading
  if (abs(Analog_X-Analog_X_AVG) > 50) {
    stepper.setSpeed(5 * (Analog_X-Analog_X_AVG));
  } else {
    stepper.setSpeed(0);
  }
}

void InitialValues() {
  //Set the values to zero before averaging
  float tempX = 0;
  //----------------------------------------------------------------------------
  // read the analog 50x, then calculate an average.
  // they will be the reference values
  for (int i = 0; i<50; i++) {
    tempX += analogRead(Analog_X_pin);
    delay(10); //allowing a little time between two readings
  }
  //----------------------------------------------------------------------------
  Analog_X_AVG = tempX/50;
  //----------------------------------------------------------------------------
  Serial.print("AVG_X: ");
  Serial.println(Analog_X_AVG);
  Serial.println("Calibration finished");
}
```


message:
Atmega328 and ADXL335 - is the right choice for vibration analysis?

I'm planning to use the ATMEGA328 and the ADXL335 accelerometer to monitor the bearing and gears vibration of a industrial extractor that works at maximum speed of 3000rpm at 380VAC - 50Hz .

The main scope of this monitoring is to get continuously the vibration readings and apply the FFT transform in order to identify if there is something that is not running well.

My primary concerns are regarding the sampling speed of the ATMEGA328P: i've tried to identify the needed sampling speed but i'm a little bit confused about the relation of motor/gear speed and the ADC sampling speed of the ATMEGA...also, the ADXL is the right choice?

body:
First of all, 3000 RPM is only 50 Hz, so sampling is not a problem for the fundamental frequency.  But you usually want to see harmonics, to pick up gear tooth issues, etc.
I suggest using my Daqarta software with a sound card to do your initial testing.  It already does everything you need, including waveform, spectrum, and spectrogram displays plus a lot more.  You can use it free for 30 sessions or 30 days, then the sound card inputs are no longer supported.  By that time you should have a good idea about what you need.  As it turns out, Daqarta also supports Arduino, and that does *not* end with the trial period.  So you may be able to do everything with an Arduino, for free.  The Daqarta site also has a contact page, and I am glad to answer questions and provide specific help for any issues that arise.  That include free users.


body:
> My primary concerns are regarding the sampling speed of the ATMEGA328P

The ATmega328 can sample up to **\~10ksps (kilo-samples-per-second) in normal configuration and at 10-bit ADC resolution**, or reliably and with good (near 10-bit) resolution **up to \~50ksps if you speed up the ADC clock**. You can get even faster if you want to sacrifice a lot on sample resolution, but at faster speeds this processor is too slow to even reliably grab the data and transmit it or store it, so you should go to a much much beefier and better microcontroller, such as a 32-bit Arduino Zero, Portenta, or non-Arduino STM32 or something.

## Example of speeding up the ATmega328 to sample up to \~50kHz:

See [my library here](https://github.com/ElectricRCAircraftGuy/eRCaGuy_analogReadXXbit/blob/Version_2/examples/General/NewAnalogRead_basic_demo/NewAnalogRead_basic_demo.ino), and [my initial article on it here](https://www.electricrcaircraftguy.com/2014/05/using-arduino-unos-built-in-16-bit-adc.html).

```
#include <eRCaGuy_NewAnalogRead.h>

void setup()
{
    adc.setADCSpeed(ADC_FAST); // now analogRead() will operate up to ~50 kHz
}

void loop()
{
    // these readings can now be done up to ~50 kHz
    uint16_t reading = analogRead(A3);
}
```

I don't remember the exact details of configuring the ADC clock, but it's all in the ATmega328 datasheet, and in my code--which you can study at the library link above, and you can look at Nick Gammon's website on it here: https://www.gammon.com.au/adc.

## How fast do you need to sample? Only you can answer that question.

Perhaps you read some academic paper that says that vibrations of 102kHz on a 5cm diameter motor made of material X can cause microfractures in the material if exposed for 100 hours. Well, in this case, you need to sample at *at least* 204kHz (2x the frequency of interest) to see if 102kHz vibrations exist.

Or, perhaps you just want to use FFT to determine the RPMs of the motor since it will almost certainly have a dominating frequency at its rotational frequency due to imperfect balance of the motor. In that case, sampling at 2x the max RPM (but in samples _per second_, not minute) is sufficient. You stated a max rotational speed of 3000 RPM, so that's `3000 rot/min x 1 min/60 sec = 50 Hz`. *To detect your RPM, therefore, by sampling vibration, you need to sample at least 2x as fast as this, or 100 Hz or higher.*

Remember, this is all [Nyquist frequency stuff](https://en.wikipedia.org/wiki/Nyquist_frequency). All that the Nyquist frequency says is [in my own words]:

> you can only detect a frequency up to 1/2 as high as your sampling rate

...or otherwise stated [in my own words]:

> you must sample at 2x whatever frequency it is you are trying to measure

Any sample rate lower than this, and you get aliasing and it is mathematically and physically impossible to determine if a higher frequency exists. Any frequencies higher than 1/2x your sample rate which *appear* to exist in your FFT analysis _must_ be thrown out, as they are invalid.

So, *what max vibrational frequency do you need to measure?* That's for you to find out. If you're looking to find gear tooth wear (ex: a broken, cracked, or missing gear tooth), you can come up with some estimations based on number of teeth per rotation, and knowing your motor's max rotational speed in rotations per second.

Example: assuming 32 teeth per revolution, you will be rotating at 3000 rot/min / 60 sec/min = 50 rot/sec x 32 teeth/rot = 1600 teeth/sec. But, to identify a broken tooth maybe you need to do a waveform analysis of the *shape* of the wave over that broken tooth, so you should sample at 5x to 10x that rate, or perhaps 1600 teeth/sec x 10 samples/tooth = 16000 samples/sec = 16 kSps. But...5 samples per tooth might be enough, or only 8 kSps...

See how some of this analysis might work? _You have to figure out what it is you're trying to figure out, and sample accordingly._ _If you don't know what you're trying to figure out, just sample as fast as you can and then with that data try to see what you can figure out from what you just sampled!_ Such are the ways of engineering and curious minds! :)

---

With that being said, assuming you use my library's `adc.setADCSpeed(ADC_FAST);` trick, you can sample 1 channel up to 50kHz or 3 channels up to 50/3 = \~16kHz, meaning **the max vibrational frequency you can detect with FFT for 3 channels is \~8kHz with an ATmega328.** Is that enough?

BUT, you will have jitter problems unless you put the ADC into continuous sample mode at a fixed interval, and you cannot sample all 3 channels at once, so there will naturally be an offset between them all, as they happen in sequence one after the other.

---

## How fast can the ADXL335 sample? (ie: what's its "bandwidth", or frequency response?)

As for the ADXL335, its [datasheet](https://www.analog.com/media/en/technical-documentation/data-sheets/adxl335.pdf) reveals it to be an analog 3-axis accelerometer, not a digital one, so you are limited by:

1. how fast the ADC you have on your microcontroller can sample the sensor (we already came up with \~16khz (kSps)/channel, for 3 channels, above) and
2. what the ADXL335's _bandwidth_, or max frequency response, is.

The datasheet (see image below) says you get a bandwidth of **0.5 Hz to 1600 Hz** for the X and Y axes, and **0.5 Hz to 550 Hz** for the Z axis, _all depending on the chosen bypass capacitors, cx, cy, and cz you choose for it._ See the image and highlighting below.

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

[Bandwidth](https://en.wikipedia.org/wiki/Bandwidth_(signal_processing)) means simply [in my own words]:

> _Bandwidth_ is the maximum frequency at which a device can respond to changes in the thing is it measuring (ex: an accelerometer to changes in acceleration).

By definition, a bandwidth for a low-pass filter, or a sensor responding to a high-frequency input, is equal to the frequency at which point the measurement of the thing being measured is attenuated by **3 db**, or in other words, is 1/sqrt(2) = 0.707 times as big as the actual thing being measured. So, if the bandwidth of an accelerometer is 50 Hz, then that means if it tries to measure a 50 Hz vibration, then the measurement it outputs at that frequency is attenuated to 0.707x as large as the actual amplitude of that vibration. Therefore, it is said that this sensor cannot be reliably used to measure higher frequencies than this. Note that since `Power = V^2/R`, and the 0.707 rule applies to voltage, the attenuation is 0.707^2 = 0.5 for power.

If you bought your ADXL335 sensor from Adafruit here for $15 (https://www.adafruit.com/product/163), they state:

> The XYZ filter capacitors are 0.1uF for a 50 Hz bandwidth

...which means they chose capacitors to give it a **50 Hz bandwidth, or frequency response**. This means the sensor is limited to reliably measuring vibrations only up to 50Hz. You should sample at least 2x this bandwidth then in order to adequately capture frequencies up to that value, again, based on Nyquist. This means **for this Adafruit version of the device and with these chosen bypass capacitors you can sample at 100 Hz or higher to detect vibrations up to 50 Hz (that's Hertz, _not_ kiloHertz!)**. Even if you sample much much faster, the maximum reliable frequency this device can measure is only up to 50 Hz before attenuation of its measurements becomes a significant concern. Whether sampling at 100 Hz or 1000 Hz, the frequency this sensor can measure, in this configuration, is only up to **50 Hz**, which is only 50/sec x 60sec/min = 3000 RPM if your goal is to just detect the rotational frequency, but not any higher-frequency vibrating modes, for your device.

A 50 Hz bandwidth (max frequency response), FYI, is optimized to reduce sample noise _for handheld tilt-based game controllers_, as it intentionally attenuates any frequencies above 50 Hz, and 50 Hz input from a human is a good expectation for human control signals. You might sample this sensor for such a game controller anywhere from 50 Hz to 1 KHz, but again, it can't detect vibrations any faster than about 50 Hz. So, **the Adafruit version of the ADXL335 is optimized to be used to make home-made tilt-based hand controllers for games, toys, smart devices, radio control devices, etc.**

## Extra note on sampling frequency

Even though the Nyquist frequency says you only need to sample **2x** the frequency of interest _to detect the frequency of interest through FFT or similar_, you need to realize that if you ever want to _plot_ a given signal or inspect its shape or waveform, you should sample at least **5x** to **10x** as fast as the frequency of the signal you are trying to record and inspect.

This is how oscilloscopes are rated. A "100 Mhz" bandwidth oscilloscope will have a sample rate of at least 5x to 10x that, or 500 MSps (Mega-samples-per-second) to 1 GSps (Giga-samples-per-second). This makes sense because the purpose of an oscilloscope is to plot waveform _shapes_, and that requires at least 5 to 10 points per period, or 5x to 10x the sample rate of the rated bandwidth in order to display a reasonably-nice picture of the waveform.

For pure FFT or frequency analysis, where you just want to know the _frequency_ of the thing being measured, but don't need to know how the waveform _looks_, a sample rate exactly 2x or higher than the frequency of the thing being measured is physically and mathematically sufficient.

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


message:
How to put a condition on HTTP.POST?

I set my code to if it executes HTTP.POST, the count will reset / back to zero, but I noticed that even it returns other http code than 201 (-1 or 500), the count still resets.

How to put a condition here that `if httpResponseCode = 201 (successful), then reset (total = 0;) else http.end().`

Thanks!

```c++
void loop () {
  if ((millis() - lastTime) > timerDelay) {
    if (WiFi.status() == WL_CONNECTED) {
      HTTPClient http;
      http.begin(serverName);

      http.addHeader("Content-Type", "application/json");
      char temp[32];
      snprintf(temp, 32, "{\"amount\":\"%.2f\"}", total);
      int httpResponseCode = http.POST(temp);

      Serial.print("HTTP Response code: ");
      Serial.println(httpResponseCode);
      Serial.println(total);
      total = 0;

      http.end();
    }

void count () {
  total += rainrate;
}
```

body:
You mean something like this?

```
if( httpResponseCode==201 )
  total = 0;
```

Your entire code would then become:

```lang-cpp
void loop () {

  if ((millis() - lastTime) > timerDelay) {

    if(WiFi.status()== WL_CONNECTED){
      HTTPClient http;

      http.begin(serverName);

      http.addHeader("Content-Type", "application/json");

      char temp[32];
      snprintf(temp, 32, "{\"amount\":\"%.2f\"}", total);
      int httpResponseCode = http.POST(temp);

      Serial.print("HTTP Response code: ");
      Serial.println(httpResponseCode);
      Serial.println(total);

      if( httpResponseCode==201 )
        total = 0;

      http.end();
    }

void count () {
 total += rainrate;
}

```


message:
Problem with a function having a parameter with a default value

I've got a problem using a default value for a function parameter.

This code gives *"'blink' was not declared in this scope"*:

```c++
void loop(void) {
  blink(12, 2, 1000);
}

void blink(const uint8_t led, int num, const uint16_t l = 12) {
  Serial.println(led);
  Serial.println(num);
  Serial.println(l);
}
```

but it works if I don't assign a default value to the "l" arg:

```c++
void blink(const uint8_t led, int num, const uint16_t l) {
```

or if I put the blink function before the loop:

```c++
void blink(const uint8_t led, int num, const uint16_t l = 12) {
  Serial.println(led);
  Serial.println(num);
  Serial.println(l);
}

void loop(void) {
  blink(12, 2, 1000);
}
```

body:
If you use a function after you call it in the same file, you have to (or at least it is better) to add a so called 'forward declaration' before calling it. The best place is before the first function, and in your case it should look like:

    void blink(const uint8_t led, int num, const uint16_t l);

You can omit the `= 12` or not.


body:
It's just a failing of the Arduino build process to generate prototypes (function *declarations*) for functions that have default argument values.  There's otherwise nothing wrong with what you're doing.  Not in my opinion anyway.  The build process sometimes chokes on function or class templates as well.  The answer to these sorts of problems is probably that these features are not considered part of the Arduino "language".

Just a reminder: In C++ a function *declaration* needs to have been seen in order to generate a call to it.  A *definition* will serve *as* a declaration.  In either case, one must have been seen before the call site.  Generating declarations where needed is, perhaps, the greater part of what the Arduino build process does that can be said to make the Arduino "language" different from plain C++.

The following were generated by working out of /tmp/default-param with the "input" being default-param.ino, running:

```bash
arduino-cli -b arduino:avr:uno build --build-path /tmp/build
```

and inspecting /tmp/build/sketch/default-param.ino.cpp which I'm calling "output".  You can use the same process if you want to see exactly what the build process is doing to your code.

Non-default argument
--------------------
This input:

```c++
void setup() {
    func(11);
}
void loop() {}
void func(int xyzzy) {}
```

generates:

```c++
#include <Arduino.h>
#line 1 "/tmp/default-param/default-param.ino"
#line 1 "/tmp/default-param/default-param.ino"
void setup();
#line 4 "/tmp/default-param/default-param.ino"
void loop();
#line 5 "/tmp/default-param/default-param.ino"
void func(int xyzzy);
#line 1 "/tmp/default-param/default-param.ino"
void setup() {
    func(11);
}
void loop() {}
void func(int xyzzy) {}
```

The build process has inserted a valid C++ function declaration prior to the call site, so the compiler is happy.

With default argument
---------------------

But this input:

```c++
void setup() {
    func(11);
}
void loop() {}
void func(int xyzzy = 7) {}
```

generates:

```c++
#include <Arduino.h>
#line 1 "/tmp/default-param/default-param.ino"
#line 1 "/tmp/default-param/default-param.ino"
void setup();
#line 4 "/tmp/default-param/default-param.ino"
void loop();
#line 1 "/tmp/default-param/default-param.ino"
void setup() {
    func(11);
}
void loop() {}
void func(int xyzzy = 7) {}
```

No declaration prior to the call site this time, so the compiler is not happy with this generated code.

Build process
-------------

The build process is a rather ugly... process... that scrapes the output of the compiler and generated ctags to build include paths and to try to generate forward references for things.  Sometimes, it just gets it wrong.  I'm not sure what the *exact* error is in the build process, but it is probably just a failure to match the error caused by calling an undeclared function with its matching entry in the ctags.  You can try reading through the [build process documentation][1] to make sense of this.  Ultimately though, you may have to read the source to arduino-cli/arduino-builder to get to exact cause.

Non-.ino (and non-.pde) files more or less go through the build process unscathed.  So, if you really want default arguments, you can make use of and .h file for your function prototype/declaration and a .cpp file for its body and follow the normal rules of C++.

Using your own declaration
--------------------------

You can just make your own declaration for it.  Doing so makes it not detect an error on that line.

```c++
void func(int xyzzy = 7);

void setup() {
    func(11);
}
void loop() {}
void func(int xyzzy) {}
```

Output:

```c++
#include <Arduino.h>
#line 1 "/tmp/default-param/default-param.ino"
void func(int xyzzy = 7);

#line 3 "/tmp/default-param/default-param.ino"
void setup();
#line 6 "/tmp/default-param/default-param.ino"
void loop();
#line 7 "/tmp/default-param/default-param.ino"
void func(int xyzzy);
#line 3 "/tmp/default-param/default-param.ino"
void setup() {
    func(11);
}
void loop() {}
void func(int xyzzy) {}
```

As you can see it generates a proto type for whatever reason.  But not one that conflicts with your own.

---

It is probably better if you want to make use of default arguments to just use headers and .cpp file for those functions that have them so that you're not subject to changes in the ability of arudino-cli/arduino-builder to handle them.

  [1]: https://arduino.github.io/arduino-cli/latest/sketch-build-process/


message:
Weird char on a 20X4 LCD

I'm trying to make an RC controller.

I have a problem with my LCD.

[![Lcd with japanese and indescribable char like][1]][1]

I have already double-checked the wiring and the connections are great.

I made a PCB with Kicad and order it to JLCPCB. I have some mistake, you can see the soldered wire.

[![PCB designed with kicad and made by JLCPCB][2]][2]

[![Schema Kicad][3]][3]

Before the PCB, I did my project with a breadboard and it worked fine.

```c++
const String menuElem[4] = {"Models", "Trims", "Reverse command", "Channel"};

const int rs = 3, en = 4, d4 = 5, d5 = 6, d6 = 7, d7 = 8;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

void menu() {
  lcd.clear();
  //lcd.setCursor(0,0);
  //byte pos = 0;
  //int sizeOfanArray = *(&array + 1) - array;
  byte menuElemLength = *(&menuElem + 1) - menuElem;
  for (byte i = 0; i < menuElemLength; i++) {
    lcd.setCursor(2, i);
    lcd.println(menuElem[i]);
  }
  showMenuNav(currentMenuPos);
}
```

  [1]: https://i.stack.imgur.com/CUKhu.jpg
  [2]: https://i.stack.imgur.com/5RAHg.jpg
  [3]: https://i.stack.imgur.com/RhCZQ.png

body:
Your code to calculate the length of your `String`s does not make sense. The `String` type is an object type. The addresses of your String objects will not match the length of the charcters in those strings. You should use an array of C strings as suggested by Juraj, and then you should use `strlen()` to get the length of those strings (C strings have a null terminating byte, and `strlen()` uses that null to calculate the length. Note that C strings can't handle Unicode.)

The String type is best avoided on Arduino anyway, as String objects tend to fragment the extremely limited heap memory on Arduino devices and cause out-of-memory crashes.


message:
OTA update - sodaq board (arduino M0 compatible)

I am trying to perform a firmware update from an SD card, on a [Sodaq Sara AFF board][1]. If i use the SDU.h library in my sketch, it fails the board check. See [this link][2] please.

I have edited the SDU.cpp myself to force the selection of `ARDUINO_SAM_ZERO`. It is now :

    __attribute__ ((section(".sketch_boot")))
    unsigned char sduBoot[0x6000] = {
      #include "boot/mzero.h"
    };

I have increased the size to 6000 otherwise it was complaining `too many initializers`.

I also have changed the SD_SS_PIN to match my pin on the `SDUboot.ino`, under `extras`. Afterwards, i recompiled it with `build.sh` in the same folder.

But I am unable to perform the firmware update. After power cycling the board (original code: the blink example, target update: blink with a faster rate) - the original firmware remains.

I exported the firmware using arduino IDE -> export compiled bynary, and tested both versions with and without bootloader.

Any help would be appreciated.

  [1]: https://support.sodaq.com/Boards/Sara_AFF/
  [2]: https://forum.arduino.cc/index.php?topic=500626.0

body:
**SOLVED!**

I have compiled my own SDUBoot.ino with fixed `SDU_START 0x2000` and for SODAQ Sara (`boot/sodaq_sara.h`). My sketch with `#include "SDU.h"` compiles successfully. The board package is also installed in Arduino (http://downloads.sodaq.net/package_sodaq_samd_index.json). Here my code with changes (base is SodaqCore-samd-1.8.6-sodaq from Github):

File `libraries/SDU/extras/SDUBoot/SDUBoot.ino`:

    #include <SD.h>
    #include <FlashStorage.h>

    #define SDU_START    0x2000
    #define SDU_SIZE     0x4000

    #define SKETCH_START (uint32_t*)(SDU_START + SDU_SIZE)

    #ifndef SDCARD_SS_PIN
    #define SDCARD_SS_PIN 10
    #endif

    #define UPDATE_FILE "UPDATE.BIN"

    FlashClass flash;

    // Initialize C library
    extern "C" void __libc_init_array(void);

    int main() {
      init();

      __libc_init_array();

      delay(1);

      if (SD.begin(SDCARD_SS_PIN) && SD.exists(UPDATE_FILE)) {
        File updateFile = SD.open(UPDATE_FILE);
        uint32_t updateSize = updateFile.size();
        bool updateFlashed = false;

        if (updateSize > SDU_SIZE) {
          // skip the SDU section
          updateFile.seek(SDU_SIZE);
          updateSize -= SDU_SIZE;

          uint32_t flashAddress = (uint32_t)SKETCH_START;

          // erase the pages
          flash.erase((void*)flashAddress, updateSize);

          uint8_t buffer[512];

          // write the pages
          for (uint32_t i = 0; i < updateSize; i += sizeof(buffer)) {
            updateFile.read(buffer, sizeof(buffer));

            flash.write((void*)flashAddress, buffer, sizeof(buffer));

            flashAddress += sizeof(buffer);
          }

          updateFlashed = true;
        }

        updateFile.close();

        if (updateFlashed) {
          SD.remove(UPDATE_FILE);
        }
      }

      // jump to the sketch
      __set_MSP(*SKETCH_START);

      //Reset vector table address
      SCB->VTOR = ((uint32_t)(SKETCH_START) & SCB_VTOR_TBLOFF_Msk);

      // address of Reset_Handler is written by the linker at the beginning of the .text section (see linker script)
      uint32_t resetHandlerAddress = (uint32_t) * (SKETCH_START + 1);
      // jump to reset handler
      asm("bx %0"::"r"(resetHandlerAddress));
    }

File `libraries/SDU/extras/SDUBoot/build.sh`:

    #!/bin/sh -x

    ARDUINO=arduino
    SKETCH_NAME="SDUBoot.ino"
    SKETCH="$PWD/$SKETCH_NAME"
    BUILD_PATH="$PWD/build"
    OUTPUT_PATH="../../src/boot"

    if [[ "$OSTYPE" == "darwin"* ]]; then
     ARDUINO="/Applications/Arduino.app/Contents/MacOS/Arduino"
    fi

    buildSDUBootSketch() {
     BOARD=$1
     DESTINATION=$2

     $ARDUINO --verify --board $BOARD --preserve-temp-files --pref build.path="$BUILD_PATH" $SKETCH
     cat "$BUILD_PATH/$SKETCH_NAME.bin" | xxd -i > $DESTINATION
     rm -rf "$BUILD_PATH"
    }

    mkdir -p "$OUTPUT_PATH"

    buildSDUBootSketch "SODAQ:samd:sodaq_sara" "$OUTPUT_PATH/sodaq_sara.h"

File `libraries/SDU/src/SDU.cpp`:

    #include <Arduino.h>

    #include "SDU.h"

    __attribute__ ((section(".sketch_boot")))
    unsigned char sduBoot[0x4000] = {
      #include "boot/sodaq_sara.h"
    };

Sketch file `sdu_test.ino`:

    #include <Arduino.h>
    #include "SDU.h"

    #if defined(ARDUINO_SODAQ_SARA)
    #define DEBUG_STREAM SerialUSB
    #else
    #error "Please select the SODAQ SARA as your board"
    #endif

    #define DEBUG_STREAM_BAUD 115200

    String message;

    void setup() {
      // Start communication.
      DEBUG_STREAM.begin(DEBUG_STREAM_BAUD);

      while (!DEBUG_STREAM) {
        // Wait for Serial Monitor to be opened.
      }

      message += "Sketch compile date and time: ";
      message += __DATE__;
      message += " ";
      message += __TIME__;

      // print out the sketch compile date and time on the serial port
      DEBUG_STREAM.println(message);
    }

    void loop() {
      // add you own code here
    }

File `arduino/50/.arduino15/packages/SODAQ/hardware/samd/1.8.6/variants/sodaq_sara/linker_scripts/gcc/flash_with_bootloader.ld` add these lines:

    KEEP(*(.sketch_boot))

    . = ALIGN(0x2000);

here:

    ...
    SECTIONS
    {
     PROVIDE(__sodaq_firmware_state = ORIGIN(FLASH) - 0x100);

     .text :
     {
      __text_start__ = .;

      KEEP(*(.sketch_boot))

      . = ALIGN(0x2000);
      KEEP(*(.isr_vector))
      ...

On SD card (formatted as FAT32) I have stored the renamed file `UPDATE.bin` **without** bootloader of the compiled sketch file. Pin **D10** is connected and used as chip select CS.

Build boot hex files:

    $ cd libraries/SDU/extras/SDUBoot
    $ ./build.sh

Version **1.8.6-sodaq** has these missing lines on [arduino_zero][1] variant but not on [sodaq_sara][2] variant.

  [1]: https://github.com/SodaqMoja/SodaqCore-samd/blob/v1.8.6-sodaq/variants/arduino_zero/linker_scripts/gcc/flash_with_bootloader.ld#L70-L72
  [2]: https://github.com/SodaqMoja/SodaqCore-samd/blob/v1.8.6-sodaq/variants/sodaq_sara/linker_scripts/gcc/flash_with_bootloader.ld#L71


message:
Accessing funcition in object via `->` is crashing (resetting) Arduino

I have several classes that call each other running on an Arduino Mega. I am using the `ArduinoSTL` library to get the std library, most notably the std::vector.

The core problem is as follows: my `Manager` object that is created in the Arduino global space, is called in the `loop()`. The `Manager` object in one of it's functions spawns a derived object `Derived derived` (the constructor also takes a pin int and a delay value, but just simplifying for now) and calls a function in it `derived.startExecution()`. All is happy. Then I store a pointer to the object into a `std::vector<base*> myVector` via `myVector.push_back(&derived)`. All is happy. As long as I don't leave the function, I can then take the pointer out of the vector container and call another function in the object. For example: `myVector.back()->continueExecution()` and all is great. Now the problem. If I copy paste the line `myVector.back()->continueExecution()` into a different function, the Arduino restarts. I'm losing my sanity here. I know that the issue is not the pointer, but the call to the function using the pointer. Using println & delay(500), in a new function inside the Manager I can do the following without issue (no restart):

 - retrieve pointer from vector. All good.
 - assign pointer from vector to a temporary pointer type to be able to refer to that pointer. All good
 - calling the function in the object causes instant Arduino Hardware reset (not a single line will execute in the function that is called).

All this leads me to the conclusion that calling the function in the object is causing a problem. I rewrote a simplified version of the code below, and it executes well on this website (please see: https://godbolt.org/z/G3x556), but on the Arduino it crashes.

What can I do to understand why the object crashes the program? how can I validate that the object is OK prior to calling the function? Why does the call to the function in an object that should be alive crashes the system? why does the call work in the function which stored it in the vector, but not in a different function? How can I answer these questions. I have hit a limit on ideas. Thank you for your time!

My code simplified:

    #include <iostream>
    //#include <ArduinoSTL.h> //commented out to work on website
    #include <vector>

    //base class is used to be able to push everything into a std::vector
    //in ArduinoSTL lib.
    class Base
    {
        public:
            virtual void continueExecution()
            { std::cout << "Base" << std::endl; }

            // a polymorphic class MUST have a virtual destructor
            virtual ~Base(){};
    };

    //lots of these classes will exist one day if I keep at this grind
    class Derived : public Base
    {
        public:
            Derived()
            {
                std::cout<< "Derived constructor" << std::endl;
            }

            void startExecution()
            {
                std::cout << "Derived object, start function"<< std::endl;
                //start work
            }

            void continueExecution()
            {
                //continue when time has eleapsed
                std::cout << "Derived continueExectution " << std::endl;
            }
    };

    class Manager
    {
        public:
            void beginExecutingDerivedObject()
            {

                //derived object
                Derived derivedObj;

                derivedObj.startExecution();

                myVector.push_back(&derivedObj);

                //if I run the line that crashes the code below this
                //comment, all is OK. But that is not where it is needed.
                myVector.back()->continueExecution();
            }

            void finishExecutionOfDerivedObject()
            {
                //CODE CRASH HERE. The moment the function is called, a reset
                //occurs.
                myVector.back()->continueExecution();

                //any code here may appear on the console, but it's just a
                //memory dump. By this point, the Arduino has thrown up it's arms.
            }

        private:
            //create vector
            std::vector<Base*> myVector;
    };

    //main is actually the arduino loop()
    int main()
    {
        //this manager class is in the sketch global space
        Manager manager;

        //this is called by a function call in the loop()
        manager.beginExecutingDerivedObject();

        //this is also called by a function call in the loop()
        manager.finishExecutionOfDerivedObject();
    }

body:
`Derived derivedObj;` is a local variable. It's deleted when the function exits. You have saved a pointer to it, but with that object now gone your pointer points to nothing of any interest - so doing *anything* with it is doomed to failure.

Instead you need to create a `new` object on the heap, which will already be a pointer:

```c++
Derived *derivedObj = new Derived();
derivedObj->startExecution();
myVector.push_back(derivedObj);
```

And then be sure to `delete` any objects you remove from the vector or you'll have lost that memory forever.


message:
How do I program an LCD screen and do I need an Arduino

I am trying to create a small device with a screen that tells the date and time. I am thinking of using a UCTRONICS 0.96 Inch OLED Module (type that on Amazon). I am very new at coding, and I know more about electrical engineering, so I have a few questions.

1. Do I need an Arduino that big to power this screen or any screen? I am trying to put this in a compact housing

2. How do you set up the screen and code it to tell the time and date

3. Is there a better screen for me to pick that is easier to work with, or is there a screen that comes programmed telling the time and date

Can someone help, please?

body:
The [screen you reference][1] is an input only device, that is, it accepts output from other sources and presents the information. It is not, per se, a stand-alone computer for processing information in the manner you describe.

[![OLED display][2]][2]

Image above courtesy linked Amazon site.

One option you can consider is a device known as [Sparkfun Microview][3].

[![sparkfun microview][4]][4]

Image above courtesy to linked Amazon site.

This device is an integrated Arduino with OLED display. That's only half the objective. You'll also have to have a programming interface (referenced on the site) as well as an external input for RTC (real time clock). Rather than provide a link, an Amazon search for "Arduino RTC" returns many options. Kit form (assembly required (minor soldering), fully assembled, with and without battery.

All of the above requires, at a minimum, a power source for the Microview and a breadboard on which to make the connections. One can, of course, design a PCB to consolidate the components.

The programming portion is easily accomplished (relative reference) by researching that aspect via the internet. There are tutorials for the Microview, which by necessity include Arduino programming, as well as supplemental tutorials for the RTC. Sparkfun is known (by me) for providing good online support via these tutorials.

If you decide to travel this route to your goal, you may have Arduino specific questions which would be acceptable to this SE.

  [1]: https://www.amazon.com/UCTRONICS-SSD1306-Self-Luminous-Display-Raspberry/dp/B072Q2X2LL
  [2]: https://i.stack.imgur.com/MXaM3.png
  [3]: https://www.amazon.com/SparkFun-MicroView-OLED-Arduino-Module/dp/B01BHGY8WG/
  [4]: https://i.stack.imgur.com/mtqEi.png


body:
OLED screen is really good looking for both indoor and outdoor and I think you have made a good choice.

You need the following things to complete your project easily.

 1. Display (which you have already found one
 2. Arduino (why? easy to program, lots of libraries available, and also tutorials)
 3. RTC - Real-time clock - This is another IC (DS1307, for example)

Arduino need not be UNO. You can use ATTiny85 MCU. the programming will be the same as how you program a UNO. ATtiny85 has no builtin I2C, but the libraries are there to emulate I2C to be connected to OLED displays.

If you want to avoid the third option, go with internal timekeeping alone. But, over a week, you will see the time difference (the internal clocks of the MCU are not accurate, so the time will lead or lag over a period of time)

have you thought about a keypad or a single button to give the option to the user to set the time?


message:
How to access GPS location without internet

I need to provide a basic geolocation service for my clients. I built a location service based on the phone geolocation. It works great, not a problem. My problem is that some of my clients don't have an internet connection.

I know there is a company like Geotab that can provide these types of services.

If I want to build my own (very basic one), how can I make my DIY (Arduino based) GPS communicate with my web servers?

body:
If you want to send data to a server on the internet, you will need an internet connection, or at least a connection to a internet gateway.

Which type of connection you use, and how you set up that connection, depends on distance, speed, and coverage you need.

Probably the most universal for your application, in the sense that it will work wherever a phone would work, is to use a GSM/GPS module with an Arduino. You can google around for such modules; there are many. Note that you will need a SIM card for every module you use.

The GSM-bit of the module can then be used as a modem to communicate with your server over TCP/IP. There are many examples showing how to do that on the interwebs, so I won't go there.

If this doesn't help you enough, please add more detail to your question and I will edit the answer.


message:
MAX30102 showing Heart rate: 0.00bpm / SpO2: 0%

I am using a MAX30102 to monitor SpO2 and heart rate using the https://github.com/oxullo/Arduino-MAX30100 library and the minimal example, but it is not showing any value change.

It only shows zero and in the library tester example it is also showing a timeout error for die temperature.

I removed all 3 pull up registers and given 5 v supply.

[![MAX30102][1]][1]

Please help to get correct result; I will be thankful.

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

body:
To identify the issue, run I2C Scanner and check the address of this module on the Serial Monitor.

If the I2C Scanner program is not able to detect the module, then either the module is defective or connections are wrong.

If the I2C Scanner program is able to identify the sensor, then check with other libraries.


message:
Mkr1000 Wifi Configuration

Is there a package similar to esp8266 WifiManager that supports wifi configuration for Arduino mkr1000?
I have searched everywhere and I got nothing

body:
I'll release a new [**WiFiManager_Generic_Lite**](https://github.com/khoih-prog/WiFiManager_Generic_Lite), with functionality similar to [**WiFiManager_NINA_Lite**](https://github.com/khoih-prog/WiFiManager_NINA_Lite), to provide support specifically to **MKR1000 using WiFi101**, as well as other generic boards (nRF52, SAMD, SAM-DUE, STM32, Teensy, AVR, etc.) using generic WiFi Shields (AT-command, WiFiNINA, etc.) within several days.

Please hold on,

---
---

The new library has just been released : [**WiFiManager_Generic_Lite** in GitHub](https://github.com/khoih-prog/WiFiManager_Generic_Lite) as well as Platform.io [**WiFiManager_Generic_Lite** in PIO](https://platformio.org/lib/show/11761/WiFiManager_Generic_Lite).

The following 2 examples are created specially for you to use and test

1. [MKR1000_WiFi101](https://github.com/khoih-prog/WiFiManager_Generic_Lite/tree/main/examples/MKR1000_WiFi101)
2. [MKR1000_WiFi101_MQTT](https://github.com/khoih-prog/WiFiManager_Generic_Lite/tree/main/examples/MKR1000_WiFi101_MQTT)

Please test and post your feedback here. Post issues, certainly many with this new library, on [**WiFiManager_Generic_Lite issues**](https://github.com/khoih-prog/WiFiManager_Generic_Lite/issues)

Cheers,


message:
Cannot program two arduinos at the same time because they both use the same COM port

I am not able to program my second arduino because they both use the same com port. In other words this picture says it all:

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

In order to upload my sketch I have to disconnect one arduino. How can I tell windows to use a different COM port?

It will be nice if I do not have to disconnect one arduino evey time I want to upload a sketch. I already restarted my computer and I get the same problem.

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

body:
I did not knew I could change the port on windows. This is how I did it thanks to @Majenko's comment.

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

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


message:
D1 mini esp8266 error: esptool.FatalError: Failed to connect to ESP8266: Timed out waiting for packet header

I am pretty sure this device worked yesterday. I tried to short GPIO0 to ground (flash), nothing.
I have a second ESP that uploads fine, but this one does not.

Is their another way to get this bootloader to open up? Or am I the owner of a brand new door stop?

body: I'm not sure if this will help EVERYONE, but I hope it at least helps someone.  I had the same issue with several different boards (3 Nano's, 2 NodeMCU ESP8266's, and 1 Uno).  I searched and searched for an answer and I kept reading about this pin or that pin being "pulled low" or "pulled hi" interfering with uploading sketches.  Well, since I couldn't find a solid answer anywhere I decided to disconnect all of the peripherals hooked to my board (except for powers and grounds) and Wah Laa!!!  The sketch uploaded like it was supposed to.  So, I believe if you just unhook all of the sending and receiving pins from all of your peripherals during upload, the sketch should upload just fine.  I hope this helps you.


message:
16x2LCD Display serial read extra character

I get extra character (frowning face) when sending a text over the serial monitor(see attached image)

[![extra character][1]][1]
[![serial monitor][2]][2]

When empty string is sent over the serial monitor, the LCD display still shows the extra character of frowning face.

How do I get rid of the extra character?

I use the tutorial code below and change nothing in the code.
https://www.arduino.cc/en/Tutorial/LibraryExamples/LiquidCrystalSerialDisplay/

    #include <LiquidCrystal.h>

        // initialize the library by associating any needed LCD interface pin
        // with the arduino pin number it is connected to
        const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
        LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

        void setup() {
          // set up the LCD's number of columns and rows:
          lcd.begin(16, 2);
          // initialize the serial communications:
          Serial.begin(9600);
        }

        void loop() {
          // when characters arrive over the serial port...
          if (Serial.available()) {
            // wait a bit for the entire message to arrive
            delay(100);
            // clear the screen
            lcd.clear();
            // read all the available characters
            while (Serial.available() > 0) {
              // display each character to the LCD
              lcd.write(Serial.read());
            }
          }
        }

  [1]: https://i.stack.imgur.com/nceQm.jpg
  [2]: https://i.stack.imgur.com/sHize.png

body:
The LCD display acts a bit different to a normal console. For instance, it does not recognize the newline character and uses the corresponding ASCII code (10) like a normal letter. Depending on the letter map of your display (for which there are several variants on the market) this will print a more or less random character. To avoid this, you have to strip the last letter from the input string before sending it to the display.

For the same reason, sending an empty string does nothing, since an empty string sends no letters. To clear individual characters in the display, you have to overwrite them with a space.


message:
Is there a 3.3V and 12V 18650 circuit?

Is there an all in one circuit which regulates charging, protects and steps up/down an 18650 battery to 12V and 3.3V at the same time, so I can power a sensor and my ESP32?

body: I would suggest using a 12V controller, and then adding a 3.3V switching regulator using the 12V supply. That would be 2 off-the shelf components and you're done.


message:
What's wrong with the ACS712 sensor?

I have two ACS712 sensors, one rated for 5A, another—for 20A.

I wanted to test how precise they are, and played with different devices (in my case, old PC fans). I copy-pasted the source code [from here](https://www.seeedstudio.com/blog/2020/02/15/acs712-current-sensor-features-how-it-works-arduino-guide/), and changed only the `Vref` value as expected, so that I get a measurement of zero when there is no current. I double-checked, the value remains zero for both ACS712 sensors. The sensor (or the multimeter) is connected in series. Only one sensor (or multimeter) is connected at the same time.

Here's the data I get. Values in parenthesis correspond to the percentage of the value compared to the one got with a multimeter.

| Setup | Measured by
a multimeter | Measured by
ACS712 5A | Measured by
ACS712 20A
| - | -:| -:| -:|
| Old CPU fan | 87 mA | 73 mA (84%) | 49 mA (56%) |
| UPS fan rated 1.9 W | 174 mA | 170 mA (97%) | 97 mA (55%) |
| Two fans together | 0.25 A | 244 mA (98%) | 146 mA (55%) |
| Server fan rated at 0.6 A | 0.49 A | 463 mA (95%) | 268 mA (55%) |
| Three server fans | 1.35 A | 1,293 mA (96%) | 683 mA **(51%)** |

While the 5A variant seems to be slightly off (another possibility would be that the multimeter is off and the ACS712 measurements are exact), things are very different for the 20A-rated counterpart: its values are wrong initially, **and for higher current, they are getting wronger**.

Why is it so? Is it broken, or have I missed something?

body:
Your problem is that you are trying to measure motes of dust with a yard stick. The yard stick is great at measuring things in inches and feet, but when you want to find the size of something that's around 1mm in size all you can say is "it's less than an inch" or "smaller than an eighth of an inch".

You have to remember that a 20A sensor has to fit that whole range of 0-20A - that's 0-20,000mA into half the range of the ADC. That's at most 512 graduations on an Arduino, and since you can usually count on "±1 LSB quantisation noise" you really only get half that as a usable value. So you're looking at a resolution of about 40mA at best with an accuracy of  ±40mA. When you want to measure small currents they're just going to get lost in the lack of resolution. At 100mA you're still only in the range of just "There might be a current there, somewhere".

For measuring current you need to size your sensor / shunt appropriately to the range of the currents you're sensing. If you're working with small variations in a large DC current then pre-conditioning the sensing to change the offset and amplify the interesting part of the signal is required, so that the signal isn't swamped by the underlying offset. If you're working with small currents then you require a sensor / shunt that gives you an appropriate signal for that current range.

Additionally, different variants of the sensor [have different sensitivity][1]: 185 mV/A for the 5A model, and 100 mV/A for the 20A model. The code you are using doesn't take this in account. Using the correct sensitivity, the last value in your table, 683 mA, becomes 1,264 mA (683×185/100=1264). This is close enough, if you consider the ±40mA accuracy.

  [1]: https://www.electronicshub.org/interfacing-acs712-current-sensor-with-arduino/


message:
ESP send string to Arduino

I'm trying to send a string from an ESP32 to an Arduino. I'm using a level shifter, where the Uno is now the Mega (since I couldn't get the Uno to work).

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

RX0 is now RX1, connected to UART2 of ESP32.

```c++
// Master sender ESP32

#include <HardwareSerial.h>

void setup() {
  // Serial.begin(115200);
  Serial2.begin(9600, SERIAL_8N1, 16, 17);
  delay(100);
}

void loop() {
  String shape = "1,2,3";
  Serial2.println(shape);
  delay(500);
}
```
---
```c++
//Receiver Mega

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  Serial1.begin(9600);
  Serial.begin(19200);
  delay(100);
}

void loop() {
  if (Serial1.available()) {
    String received = "";
    received = Serial1.readString();
    Serial.println(received);
  }
}
```

Is there something in either sketch that should be changed?

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

body:
readString**Until**('\n')

    //Receiver Mega

    void setup() {
      pinMode(LED_BUILTIN, OUTPUT);
      Serial1.begin(9600);
      Serial.begin(19200);
      delay(100);
    }

    void loop() {
      if (Serial1.available()) {
        String received = "";
        received = Serial1.readStringUntil('\n');
        Serial.println(received);
      }
    }

It's about how `Serial.readString()` works: it reads from the serial port forever in this case. It stops reading if the serial interface is given a time-out. There are two possibilities:
 * use `readStringUntil()` on the receiver
 * call `mySerial.setTimeout(300);` (from `setup()`) to set a 300ms (for instance, as long as it's significantly less than 1000) time out on the receiver — it defaults to one second!


message:
Which Arduino for many analogue sensors (and WiFi)?

For context, I come from a very software-heavy background so I know very little about hardware.

I'm looking to build a system that requires at least 6 sensors (pH, electrical conductivity, humidity, temperature, light intensity, flow rate), and I want to send all of this input over WiFi at ~10 minute intervals. Most of these sensors will be analogue.

I noticed that for example the Arduino Uno only has 6 analogue inputs. Plus from research, I would need to connect a WiFi module to the Uno which seems too much of a hassle and added cost.

I'm looking at the ARDUINO NANO 33 IOT right now. It seems perfect for what I want to do since it's cheap, has 8 analogue pins, and has WiFi out-of-the-box. Is my reasoning correct in choosing this Arduino? I'm wondering why something with WiFi capability and more pins is cheaper than the Uno.

Thanks in advance!

body:
For short answer: Just use NodeMCU ESP32 or any ESP32 dev board.

TLDR;

[![ESP32 dev board pinout][1]][1]

ESP32 is actually a wifi module but has very powerful processor (240MHz max), way more faster than Arduino Uno (atmega328 @16MHz). Because of this, wifi comes as natural for ESP32.

You can even buy ESP32 dev board around US$10 (include shipping) while the esp32 module itself costs only $5

Arduino UNO 33 IOT is simply SAMD21 (@48MHz) with external wifi module. This wifi module alone costs about US$10. This configuration is similar to Arduino UNO + wifi shield but of course cheaper because you don't need an extra costly shield for wifi.

The expensive wifi shield is actually HDG204 wifi SIP (system in package) + 32-bit AVR AT32UC3C1512C (66MHz max). Pretty much the wifi shield piggy back on Arduino UNO is 4 times faster than 8-bit micro atmega328 of Arduino UNO. So... it's pricey.

*Edit:*

ESP32 has 2x 12-bit ADC with 16 channels exposed out to IO pin on most of ESP32 dev board.

If you just read some temperature sensors, range finder sensors, humidity sensors... You are good with most of ADC inside microcontrollers these days. Unless you are building instrumentational device, well, this is a whole different story.

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


body:
Doesn't matter the number of analog pins if you're doing 10 minute polls.

Run the power to each sensor from its own digital pin. Connect the sensor outputs to a single analog pin. Note that any analog pin can be used as a digital pin, but not vice-versa.

Start with all sensors turned off (ie. the individual digital power pins turned `LOW`). When you poll, turn `HIGH` a single sensor's digital pin, read the output on the analog pin, and then power back down the sensor. Move on to sensor two, sensor three etc.

This is pretty much multiplexing the analog pin. I do this all the time in my indoor grow room environment automation systems.

Typically I use Wemos D1 minis for the task, or NodeMCU-12e devices. The last batch of D1 minis I paid less than $10 for five of them, shipping and taxes included. Both devices I mentioned have wifi and bluetooth inherent. I even reprogram them over the air (OTA).


message:
Programming AT24C16 EEPROM with Arduino Nano

I have been trying to program an [AT24C16 EEPROM][1] and have set up a circuit as per the attached image.

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

I have been using the following Arduino code:

```c++
#include <Wire.h>

#define disk1 0x50    //Address of 24LC256 eeprom chip

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

  unsigned int address = 10;

  writeEEPROM(disk1, address, 72);
  Serial.println(readEEPROM(disk1, address), DEC);
}

void loop(){}

void writeEEPROM(int deviceaddress, unsigned int eeaddress, byte data )
{
  Wire.beginTransmission(deviceaddress);
  Wire.write((int)(eeaddress >> 8));   // MSB
  Wire.write((int)(eeaddress & 0xFF)); // LSB
  Wire.write(data);
  Serial.println(Wire.endTransmission());

  delay(5);
}

byte readEEPROM(int deviceaddress, unsigned int eeaddress )
{
  byte rdata = 0xFF;

  Wire.beginTransmission(deviceaddress);
  Wire.write((int)(eeaddress >> 8));   // MSB
  Wire.write((int)(eeaddress & 0xFF)); // LSB
  Serial.println(Wire.endTransmission());

  Wire.requestFrom(deviceaddress,1);

  if (Wire.available()) rdata = Wire.read();

  return rdata;
}
```

Unfortunately I only ever receive '255' in the serial monitor suggesting that no data has been written.

The code was from [this][3] tutorial which explains how the wiring on pins 1-3 governs the address of the chip.

  [1]: http://ww1.microchip.com/downloads/en/devicedoc/doc0180.pdf
  [2]: https://i.stack.imgur.com/yK4gd.jpg
  [3]: https://www.hobbytronics.co.uk/arduino-external-eeprom

body:
Well, I think I see part of what is happening.  I'm not sure to what degree this is an Arduino problem, but it may be of some use to someone wanting to interface this chip with an Arduino.  So, here's what I see:

You're writing to the chip just fine so far as I2C is concerned.  But the content of what you're writing is not exactly correct to the chip itself.

You have:

```c++
Wire.beginTransmission(deviceaddress);
Wire.write((int)(eeaddress >> 8));   // MSB
Wire.write((int)(eeaddress & 0xFF)); // LSB
```

Which is intuitive, but unfortunately not how the AT24C16 apparently works.   To be clear, the tutorial you've referenced uses the 24LC256, which *does* use the addressing scheme above.  But you're not using that chip.

The chips in the series covered by the AT24LC16 datasheet need progressively larger EEPROM addresses for the larger memory sizes.  As the size of the chip increases they are effectively stealing configurable bits from the A0, A1, A2 pins and repurposing them as part of the EEPROM address **encoded into** the I2C address.  You'll see that the for up to the 2Kbit/256byte/8-bit addressable EEPROM, all of A0, A1, A2 can be used to set the I2C address (to have multiple of these chips).  By the time you work your way up to the 16kbit/2kbyte/11-bit addressable chip, all of the A0, A1, A2 are specified as **no connect**; the datasheet says that *can* be connected to ground.  The reason for doing this probably just for controlling noise.

The chip expects only the lower 8 bits of the EEPROM word address to be sent in the data portion of the I2C write (or "dummy" write).  But the bits in excess of 8-bits, the upper 3-bits for your 11-bit addressable, are expected to be encoded into the I2C address itself, like so:

```c++
const uint8_t i2c_base_address = 0x50;
const uint8_t upper_three_eeprom_adress_bits = (eeaddress >> 8) & 0x7;
const uint8_t i2c_address = i2c_base_address | upper_three_eeprom_adress_bits;
Wire.beginTransmission(i2c_address);
Wire.write(eeaddress & 0xFF); // address LSB
```

---

The datasheet speaks of "BYTE WRITE" where single bytes per I2C write transactions are written to EEPROM.  And it speaks of "PAGE WRITE" where an entire page payload is sent, 16-bytes for your model.  Because you are sending two bytes as part of data portion of the I2C write, **you are doing neither of these things**.  The chip's notion of "current address" is updated differently for "byte" vs "page" writes.

If I had guess, they didn't want there to be a qualitative difference in handling 1 vs 2 byte I2C write transactions or alternately between 15 (page size minus one) vs 16 (page size) byte I2C write transactions.  So, they just decided anything in the middle ground between a single byte write and an entire page write should be ignored, so no EEPROM write operation carried out.


body:
In response to the answer from @timemage I updated my code which now allows me to read and write to the EEPROM chip as intended. Here is the code just in case anyone else wants it quickly:

    #include <Wire.h>

    #define disk1 0x50    //Address of eeprom chip

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

      unsigned int address0 = 0;

      writeEEPROM(disk1, address0, 1);

      Serial.println(readEEPROM(disk1, address0), DEC);
    }

    void loop() {}

    void writeEEPROM(int deviceaddress, unsigned int eeaddress, byte data )
    {

      const uint8_t i2c_base_address = 0x50;
      const uint8_t upper_three_eeprom_adress_bits = (eeaddress >> 8) & 0x7;
      const uint8_t i2c_address = i2c_base_address | upper_three_eeprom_adress_bits;
      Wire.beginTransmission(i2c_address);
      Wire.write(eeaddress & 0xFF); // address LSB

      Wire.write(data);
      Wire.endTransmission();

      delay(5);
    }

    byte readEEPROM(int deviceaddress, unsigned int eeaddress )
    {
      byte rdata = 0xFF;

      const uint8_t i2c_base_address = 0x50;
      const uint8_t upper_three_eeprom_adress_bits = (eeaddress >> 8) & 0x7;
      const uint8_t i2c_address = i2c_base_address | upper_three_eeprom_adress_bits;
      Wire.beginTransmission(i2c_address);
      Wire.write(eeaddress & 0xFF); // address LSB

      Wire.endTransmission();

      Wire.requestFrom(deviceaddress, 1);

      if (Wire.available()) rdata = Wire.read();

      return rdata;
    }


message:
Using Arduino as a standalone compiler

I mostly program in C/C++ so I conviniently have a GCC compiler for all my compilations. I was wondering if there is a special compiler for Arduino that can be used just like the GCC Compiler? Because just taking a .ino sketch and passing it to the comiler with a few arguments will be a lot easier for me that all those things in the IDE, and furthermore I use Sublime Text as my text editor. And making a C program work in Sublime is as simple as providing it a path to the compiler. So I would like a portable smaller version of the Arduino Compiler that is NOT the whole IDE folder. Hope I get nice answers!! Thanks in advance.

body:
This is not an answer that fully meets what you ask, but it is too big for a comment, and it helps you somewhat, at least using your Sublime editor.

What annoys me most in the Arduino IDE is the lack of supporting multiple files (having horizontal tabs make the number of files to see max 6 or 7, and using .h/.cpp files easily goes most beyond that number).

My preference is using Visual Studio as editor and I do. In your case you can use Sublime editor. Make sure that the .ino file doesn't change (i.e. only make a forward to your C++ classes or code in other classes). This is to prevent synchronization problems between the Arduino IDE and Visual Studio.

Simultaneously start up the Arduino IDE, and do the compilation from here. Only read the .ino file, while the other files are in the same directory (structure), and can be edited by Sublime editor.

So it doesn't use GCC, but the Arduino IDE is only used for compiling/running, and all editing work is done on your editor.

Besides that, in Visual Studio I created (at least for one project) stubs so I can run it on the PC as well as 'test' project. For this you can use your gcc compiler.


body:
First of all: The Arduino IDE brings its own GCC compiler. It is a version, that can compile for the AVR platform (don't know, if the standard version is capable of that).

When you activate verbose output for compilation in the preferences of your Arduino IDE, you can actually see, what calls to GCC the IDE is doing. You could use that to replicate it.

If you only want to use the sublime text editor for programming and not rebuilding the compilation environment of Arduino for fun (which I wouldn't able to help with), you might wanna have a look at the [Arduino-cli][1]. It gives you a tool to invoke important function, that normally the IDE does, via commandline (like installing cores and libraries, compiling and uploading). Thats what I'm currently using with sublime for programming in Arduino. It allows me to invoke building an uploading from sublime without having the Arduino IDE open.

If you want to go that way, here are the sublime-build files, that I use for my Arduino Nanos and ATtiny84s. Maybe you can adapt them for your needs. (Note: I omitted multiple variants, that I use to upload on different com ports, because the com port is the only thing, that changes there. Also I'm on Ubuntu, so on Windows or Mac it might look a bit different)

For the Nano:

    {
        "cmd" : ["arduino-cli compile --fqbn arduino:avr:nano"],
        "working_dir": "$file_path",
        "shell":true,
        "file_patterns":["*.ino"],
        "variants": [
            {
                "cmd" : ["arduino-cli compile --fqbn arduino:avr:nano && arduino-cli upload -v --fqbn arduino:avr:nano:cpu=atmega328old --port /dev/ttyUSB0"],
                "working_dir": "$file_path",
                "shell":true,
                "name": "Compile & Upload ttyUSB0"
            }
        ]
    }

For the ATtiny84:

    {
        "cmd" : ["arduino-cli compile --fqbn ATTinyCore:avr:attinyx4:chip=84"],
        "working_dir": "$file_path",
        "shell":true,
        "file_patterns":["*.ino"],
        "variants": [
            {
                "cmd" : ["arduino-cli compile --fqbn ATTinyCore:avr:attinyx4:chip=84 && arduino-cli upload -v --fqbn ATTinyCore:avr:attinyx4:chip=84 --programmer arduinoasisp --port /dev/ttyUSB0"],
                "working_dir": "$file_path",
                "shell":true,
                "name": "ATtiny84: Compile & Upload ttyUSB0"
            }
        ]
    }

  [1]: https://arduino.github.io/arduino-cli/installation/


body: If you are working in Windows, I recommend VS2019 Community Edition (free) plus the Visual Micro extension.  Gives you all the intellisense features of VS, tabbed edit windows, the works.  I came to the Arduino world from Windows programming with C++ & C#, so I was already familiar with the Visual Studio line of IDE's, but I wouldn't have it any other way now.


message:
Is my 8x8 led matrix module broken?

I have an Arduino Mega set up with an 8x8 led matrix as laid out in this circuito.io project: https://www.circuito.io/static/reply/index.html?solutionId=6013e67aeaa9ed0030f668fb&solutionPath=storage.circuito.io

[![A screenshot of the wiring diagram][1]][1]

But when I plug in the usb cable, it looks like this:

[![Most of the LEDs appear to be on in some sort of grid pattern][2]][2]

I'm using the default code supplied by circuito.io (this was just meant to be a "hello world" jumping off point)

When I run the code, some of the leds flicker on and off, but the ones that are on in the image tend to stay on regardless.

  [1]: https://i.stack.imgur.com/WdUnn.png
  [2]: https://i.stack.imgur.com/BvjO8.png

body: It's likely that it is just the orientation of the module is wrong. Pull out the LED module, rotate 180 degrees, put it back in and it should work. The dot point should be on the bottom right.


message:
Can Arduino uno adjust input square wave duty, phase and frequency with just timer-counter?

Requirement:

- I have input 4KHz pulse input
- Divide it's frequency in half
- Arbitrarily adjust phase
- Arbitrarily adjust duty
- Out put the modified pulse

My solution (CPU):

    uint8_t cnt = 0;
    uint16_t t1 = 235;
    uint16_t t2 = 5;
    String cmd;

    void setup() {
      pinMode(3, OUTPUT);
      pinMode(2, INPUT);

      Serial.begin(9600);
      delay(500);
      attachInterrupt(digitalPinToInterrupt(2), rising_edge, RISING);
      Serial.println("PWM init");
    }

    void loop() {
      if (Serial.available() > 0) {
        cmd = Serial.readString();

        if (cmd.substring(0,8) == "setdelay"){
          t1 = cmd.substring(9).toInt();
          Serial.print("setting delay to ");
          Serial.print(t1);
          Serial.println(" us");
        }
        else if (cmd.substring(0,7) == "sethigh"){
          t2 = cmd.substring(8).toInt();
          Serial.print("setting high time to ");
          Serial.print(t2);
          Serial.println(" us");
        }
      Serial.flush();
      }
    }
    void rising_edge() {
      cnt = cnt + 1;
      if (cnt >= 2) {                           //divide by 2
        delayMicroseconds(t1);
        digitalWrite(3,HIGH);
        delayMicroseconds(t2);
        digitalWrite(3,LOW);
        cnt = 0;
      }
    }

However this makes heavy use of CPU, and I need to use CPU for something else.Is it possible to implement all this with TC ?

Thanks in Advance !

body:
> this makes heavy use of CPU, and I need to use CPU for something else

The issue with this code is that is heavily uses the CPU for _busy
waiting_ rather than for doing useful work. You should try to get rid of
those waiting loops:

* `Serial.readString()`: see Majenko's blog post [Reading Serial on the
  Arduino][serial]

* `delayMicroseconds()`: for this, you can indeed use a timer.

For the pulse generation, you can keep roughly the same logic as your
existing code: output a single pulse every other time a rising edge is
sensed on the input. This pulse can be conveniently generated by
Timer 1 on pin 9 by using a PWM mode and stopping the timer
after a single cycle. I would use inverting PWM mode, with the timer
starting at zero on the input pulse:

* at `t1` microseconds, a compare match sets the output HIGH

* at `t1+t2` microseconds, the timer overflow sets the output LOW, and
  the overflow interrupt stops and resets the timer

Here is a tentative, untested implementation:

```c++
// Set the pulse timings. To be called from loop() on user's request.
void set_timings(uint16_t t1, uint16_t t2)
{
    uint16_t ocr1a = t1 * 16 - 1;        // initial time in LOW state
    uint16_t icr1 = (t1 + t2) * 16 - 1;  // timer period
    noInterrupts();  // protect critical section
    OCR1A = ocr1a;
    ICR1 = icr1;
    interrupts();
}

// Configure Timer 1. To be called from setup().
void setup_timer() {
    DDRB  |= _BV(PB1);    // set pin digital 9 = PB1 = OC1A as output
    TCCR1A = _BV(COM1A0)  // PWM on OC1A, inverting mode
           | _BV(COM1A1)  // ditto
           | _BV(WGM11);  // mode 14: fast PWM, top = ICR1
    TCCR1B = _BV(WGM12)   // ditto
           | _BV(WGM13)   // ditto
           | 0;           // stopped
    TCNT1  = 0;           // reset
    TIFR1  = _BV(TOV1);   // clear overflow flag
    TIMSK1 = _BV(TOIE1);  // enable overflow interrupt
    set_timings(235, 5);  // initial timings
}

// Interrupt triggered by a rising edge of the input.
void on_rising_edge() {
    static uint8_t count;
    if (++count % 2) return;   // divide by 2
    TCCR1B |= _BV(CS10);       // start timer, clock @ F_CPU
}

// Stop and reset the timer when it overflows.
ISR(TIMER1_OVF_vect) {
    TCCR1B = 0;  // stop
    TCNT1  = 0;  // reset
}
```

[serial]: https://majenko.co.uk/blog/reading-serial-arduino


message:
Ok to Connect 2.9V Stepper to 3.3V pin?

So I have a stepper motor that's rated for 2.9V and 0.8A and I connected it to a L9110 Driver and I wanted to drive it with my arduino. But I don't know how to drive it safely without damaging the motor. I am using the stepper.h library and thought of connecting it to 3.3V pin on the Arduino but I am a bit concerned.. is it Ok to power it with 3.3V if no then What can I do?

Edit: the L9110 module I am using is a dual H Bridge.

Edit2: I was Indead Powering the Stepper and the Module directly from the arduino.. luckily the arduino survived.

Edit3: So I didn't have a 3V power supply so I used a Voltage Divider with a 9V battery and connected the L9110s module with the battery (after its voltage divided) and the module powers on.. but when the arduino starts driving the stepper the module's led starts Flickering instead of staying on and the stepper doesn't turn... I don't know what is the problem.

body:
Motors draw a LOT of current compared to CMOS circuits.

The 3.3V output on most Arduinos can only provide a very small amount of current. The Arduino Uno, for example, says it only provides a max of 50mA from its 3.3V regulator. Your motor driver probably needs >10X more than that.

The overload protection on the Arduino's voltage regulator will probably kick in and cause it to shut off. It might take a while to cool down before 3.3V output comes back. I've heard that the protection on Arduino knockoffs doesn't always work, so you could also fry the voltage regulator if you try to draw too much from it.

Bottom line: **Don't do that.**

Get a high current supply for your motor driver.


message:
unable to modify NTPClient to use static IP address

I tried the example  File > Examples > ESP8266WiFi > NTPClient which requests the current time and it worked fine.  Then I tried to modify it so that the ESP8266 would have a static IP address on my home network.  I added the following lines before  **void setup()**

    IPAddress staticIP(192, 168,   0, 159);
    IPAddress  gateway(192, 168,   0,   1);
    IPAddress   subnet(255, 255, 255,   0);

Then, in  **void setup()**     I added a line and commented out the original line like this

    //  WiFi.mode(WIFI_STA);
    WiFi.config(staticIP, gateway, subnet);

After running the sketch after I did this, it connected to my home network without any problems (as it did before).  But this time, after it prints the message **sending NTP packet...** to the serial monitor, it just says **no packet yet**.  This process is repeated every 10 seconds, but it never comes back with the time.

My troubleshooting efforts have been to uncomment the original line and comment out the line I added above.  This restores the sketch to its working condition.  I have done this several times over the past three days and the same thing always happens.

If I subscribed to conspiracy theories, I might think that some DHCP zealots are behind this.  Unfortunately, I can't come up with a better explanation.  So to ask just one question, "How can I get my ESP8266-01, flashed with Arduino 1.8.10, running on a Windows 8.1 laptop, to have a static IP on my home network and fetch current NTP timestamps from the internet?

(for reference, this is the sketch in question)

    /*

      Udp NTP Client

      Get the time from a Network Time Protocol (NTP) time server
      Demonstrates use of UDP sendPacket and ReceivePacket
      For more on NTP time servers and the messages needed to communicate with them,
      see http://en.wikipedia.org/wiki/Network_Time_Protocol

      created 4 Sep 2010
      by Michael Margolis
      modified 9 Apr 2012
      by Tom Igoe
      updated for the ESP8266 12 Apr 2015
      by Ivan Grokhotkov

      This code is in the public domain.

    */

    #include <ESP8266WiFi.h>
    #include <WiFiUdp.h>

    #ifndef STASSID
    #define STASSID "peopleMightFreakIfIuseMyRealInfo"
    #define STAPSK  "dontHaveAsecurityPanicAttack"
    #endif

    const char * ssid = STASSID; // your network SSID (name)
    const char * pass = STAPSK;  // your network password

    IPAddress staticIP(192, 168,   0, 159);
    IPAddress  gateway(192, 168,   0,   1);
    IPAddress   subnet(255, 255, 255,   0);

    unsigned int localPort = 2390;      // local port to listen for UDP packets

    /* Don't hardwire the IP address or we won't get the benefits of the pool.
        Lookup the IP address for the host name instead */
    //IPAddress timeServer(129, 6, 15, 28); // time.nist.gov NTP server
    IPAddress timeServerIP; // time.nist.gov NTP server address
    const char* ntpServerName = "time.nist.gov";

    const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message

    byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets

    // A UDP instance to let us send and receive packets over UDP
    WiFiUDP udp;

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

      // We start by connecting to a WiFi network
      Serial.print("Connecting to ");
      Serial.println(ssid);
    //  WiFi.mode(WIFI_STA);
      WiFi.config(staticIP, gateway, subnet);
      WiFi.begin(ssid, pass);

      while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
      }
      Serial.println("");

      Serial.println("WiFi connected");
      Serial.println("IP address: ");
      Serial.println(WiFi.localIP());

      Serial.println("Starting UDP");
      udp.begin(localPort);
      Serial.print("Local port: ");
      Serial.println(udp.localPort());
    }

    void loop() {
      //get a random server from the pool
      WiFi.hostByName(ntpServerName, timeServerIP);

      sendNTPpacket(timeServerIP); // send an NTP packet to a time server
      // wait to see if a reply is available
      delay(1000);

      int cb = udp.parsePacket();
      if (!cb) {
        Serial.println("no packet yet");
      } else {
        Serial.print("packet received, length=");
        Serial.println(cb);
        // We've received a packet, read the data from it
        udp.read(packetBuffer, NTP_PACKET_SIZE); // read the packet into the buffer

        //the timestamp starts at byte 40 of the received packet and is four bytes,
        // or two words, long. First, esxtract the two words:

        unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
        unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
        // combine the four bytes (two words) into a long integer
        // this is NTP time (seconds since Jan 1 1900):
        unsigned long secsSince1900 = highWord << 16 | lowWord;
        Serial.print("Seconds since Jan 1 1900 = ");
        Serial.println(secsSince1900);

        // now convert NTP time into everyday time:
        Serial.print("Unix time = ");
        // Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
        const unsigned long seventyYears = 2208988800UL;
        // subtract seventy years:
        unsigned long epoch = secsSince1900 - seventyYears;
        // print Unix time:
        Serial.println(epoch);

        // print the hour, minute and second:
        Serial.print("The UTC time is ");       // UTC is the time at Greenwich Meridian (GMT)
        Serial.print((epoch  % 86400L) / 3600); // print the hour (86400 equals secs per day)
        Serial.print(':');
        if (((epoch % 3600) / 60) < 10) {
          // In the first 10 minutes of each hour, we'll want a leading '0'
          Serial.print('0');
        }
        Serial.print((epoch  % 3600) / 60); // print the minute (3600 equals secs per minute)
        Serial.print(':');
        if ((epoch % 60) < 10) {
          // In the first 10 seconds of each minute, we'll want a leading '0'
          Serial.print('0');
        }
        Serial.println(epoch % 60); // print the second
      }
      // wait ten seconds before asking for the time again
      delay(10000);
    }

    // send an NTP request to the time server at the given address
    void sendNTPpacket(IPAddress& address) {
      Serial.println("sending NTP packet...");
      // set all bytes in the buffer to 0
      memset(packetBuffer, 0, NTP_PACKET_SIZE);
      // Initialize values needed to form NTP request
      // (see URL above for details on the packets)
      packetBuffer[0] = 0b11100011;   // LI, Version, Mode
      packetBuffer[1] = 0;     // Stratum, or type of clock
      packetBuffer[2] = 6;     // Polling Interval
      packetBuffer[3] = 0xEC;  // Peer Clock Precision
      // 8 bytes of zero for Root Delay & Root Dispersion
      packetBuffer[12]  = 49;
      packetBuffer[13]  = 0x4E;
      packetBuffer[14]  = 49;
      packetBuffer[15]  = 52;

      // all NTP fields have been given values, now
      // you can send a packet requesting a timestamp:
      udp.beginPacket(address, 123); //NTP requests are to port 123
      udp.write(packetBuffer, NTP_PACKET_SIZE);
      udp.endPacket();
    }

body:
As well as specifying your IP address and gateway you also have to provide DNS server addresses. These are normally provided by DHCP, and the ESP8266 *doesn't* assume that it's the same as your gateway address when using a static IP address.

Normally you would use your router's IP address as your DNS server address, but you can also use the Google public DNS servers on `8.8.8.8` and `8.8.4.4`.

The full format of the `config` function is:

```c++
  WiFi.config(staticIP, gateway, subnet, dns);
```

where `dns` is, like the other parameters, an `IPAddress`.


body:
If you use Arduino IDE with <ESP8266WiFi.h> there is a different order for the arguments in the config-statement See the comment in the source code: //ESP argument order is: ip, gateway, subnet, dns1
//Arduino arg order is: ip, dns, gateway, subnet.

So after lots of trouble i changed my config in WiFi.config(STATICIP, DNS1, GATEWAY, SUBNET) and everything works smooth now. The comment means that if you use ESP-IDE (?) the argument order is: ip, gateway, subnet, dns1. When you use Aduino IDE (for ESP8266) the argument order is: ip, dns, gateway, subnet._


message:
Printing vairable with U8GLib

I have this code that takes temperature and humidity values from a DHT11 sensor and number of faces from an external python code and prints them on an OLED screen but instead of values of variables it keeps printing 0, how can I solve it? (Sorry some parts are not in English but just consider them as random variable names.)

    //dht11 kodu için ayarlamalar
    #include <dht.h>
    dht DHT;
    #define DHT11_PIN 7

    //ekran için ayarlamalar
    #include "U8glib.h"
    U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE | U8G_I2C_OPT_DEV_0);
    char bufferX [20];
    char bufferY [20];
    char bufferZ [20];

    //fan kodu için ayarlamalar
    int mot1 = 8;
    int mot2 = 9;
    int en1 = 10;
    int dir = 6;
    bool state = true;
    int nob = A0;
    int val = 0;
    int fan_hizi = 0;
    String faces_str;
    int faces;
    float sicaklik;
    float nem;

    void draw(void)
    {
      u8g.setFont(u8g_font_unifont);
      u8g.drawStr( 0, 15, bufferX);
      u8g.drawStr( 0, 30, bufferX);
      u8g.drawStr( 0, 45, bufferY);
      u8g.drawStr( 0, 60, bufferZ);
    }

    void setup() {
      Serial.begin(9600); //iletişim ve dht11 verisi

      // pin ayarları
      pinMode(mot1,OUTPUT);
      pinMode(mot2,OUTPUT);
      pinMode(en1,OUTPUT);
      pinMode(dir,INPUT_PULLUP);
    }

    void loop() {
      //dht11 kodu
      sicaklik = DHT.temperature;
      nem = DHT.humidity;
      delay(1000);

      //iletişim kodu
      if(Serial.available() > 0) {
        faces_str = Serial.readString();
        faces = faces_str.toInt();
      }

      Serial.print(faces);

      //sınırlar
      if(faces == 0 && sicaklik < 25 && nem < 65) {
        fan_hizi = 50;
        digitalWrite(13, HIGH);
        digitalWrite(12, LOW);
      }
      if(faces >= 1 || sicaklik >= 25 || nem >= 65) {
        fan_hizi = 250;
        digitalWrite(13, LOW);
        digitalWrite(12, HIGH);
      }

      //ekran
      sprintf(bufferX, "Yuzler: %d", faces);
      sprintf(bufferY, "Sicaklik: %d", sicaklik);
      sprintf(bufferZ, "Nem: %d", nem);
       u8g.firstPage();
      do {
      draw();
        }
      while ( u8g.nextPage() );
      delay(10);

      //fan kodu
      analogWrite(en1, fan_hizi);
      digitalWrite(mot1, HIGH);
      digitalWrite(mot2, LOW);
      delay(1000);
      digitalWrite(mot1, LOW);
      }

body:
I do not understand, how you initialize the DHT sensor object.
(I wonder why this compiles at all.)

Your way:

    //dht11 kodu için ayarlamalar
    #include <dht.h>
    dht DHT;
    #define DHT11_PIN 7

I would use:

    //dht11 kodu için ayarlamalar
    #include <DHT.h>
    #define DHT11_PIN 7

    DHT dht( DHT11_PIN, DHT11 );

Don't forget to start the DHT object with:

    void setup() {
      // ... code removed for brevity
      dht.begin();
    }

Now use the `dht` object instad of the DHT class.

    sicaklik = dht.readTemperature();
    nem = dht.readHumidity();

You did not specify what libraries you have used. But I tried all DHT libs I could find and none of them compiled with your code without errors.

The following code compiles on my IDE for an arduino UNO having olivers ug8lib and adafruits DHT sensor library installed. BTW: You even did not mention the Arduino/ESP you used. So I guess it is an UNO.

    //dht11 kodu için ayarlamalar
    #include "DHT.h"
    #define DHT11_PIN 7
    DHT dht( DHT11_PIN, DHT11 );

    //ekran için ayarlamalar
    #include "U8glib.h"
    U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE | U8G_I2C_OPT_DEV_0);
    char bufferX [20];
    char bufferY [20];
    char bufferZ [20];

    //fan kodu için ayarlamalar
    int mot1 = 8;
    int m ot2 = 9;
    int en1 = 10;
    int dir = 6;
    bool state = true;
    int nob = A0;
    int val = 0;
    int fan_hizi = 0;
    String faces_str;
    int faces;
    float sicaklik;
    float nem;

    void draw(void)
    {
      u8g.setFont(u8g_font_unifont);
      u8g.drawStr( 0, 15, bufferX);
      u8g.drawStr( 0, 30, bufferX);
      u8g.drawStr( 0, 45, bufferY);
      u8g.drawStr( 0, 60, bufferZ);
    }

    void setup()
    {
      Serial.begin(9600); //iletişim ve dht11 verisi

      // pin ayarları
      pinMode(mot1,OUTPUT);
      pinMode(mot2,OUTPUT);
      pinMode(en1,OUTPUT);
      pinMode(dir,INPUT_PULLUP);
    }

    void loop()
    {
      //dht11 kodu
      sicaklik = dht.readTemperature();
      nem = dht.readHumidity();
      delay(1000);

      //iletişim kodu
      if(Serial.available() > 0)
      {
        faces_str = Serial.readString();
        faces = faces_str.toInt();
      }

      Serial.print(faces);

      //sınırlar
      if(faces == 0 && sicaklik < 25 && nem < 65)
      {
        fan_hizi = 50;
        digitalWrite(13, HIGH);
        digitalWrite(12, LOW);
      }

      if(faces >= 1 || sicaklik >= 25 || nem >= 65)
      {
        fan_hizi = 250;
        digitalWrite(13, LOW);
        digitalWrite(12, HIGH);
      }

      //ekran
      sprintf(bufferX, "Yuzler: %d", faces);
      sprintf(bufferY, "Sicaklik: %d", sicaklik);
      sprintf(bufferZ, "Nem: %d", nem);
      u8g.firstPage();

      do
      {
        draw();
      }  while ( u8g.nextPage() );

      delay(10);

      //fan kodu
      analogWrite(en1, fan_hizi);
      digitalWrite(mot1, HIGH);
      digitalWrite(mot2, LOW);
      delay(1000);
      digitalWrite(mot1, LOW);
    }

I do not have the time to assemble the hardware to try it.
So I can say it compiles, but I can not say it works.

**EDIT:**

Now I found adidax "DHT11 lib". your code compiles with this library. But you forgott to read the values from the sensor, before you read them from the variables.

The following line is missing:

    void loop() {
      //dht11 kodu
      DHT.read( DHT11_PIN ); // <-- this line is missing
      sicaklik = DHT.temperature;
      nem = DHT.humidity;
    ...


message:
Library for working with a 4-digit 7-segment indicator SH5461AS

Good day. Tell me an excellent library for working with a 4-digit 7-segment indicator.
I am currently using `#include <fDigitsSegtPin.h>`

But it does not allow you to display letters, does not allow you to put dots in the right place.
I think it is not flexible.
I want it to be easy enough to control the indicator and have sufficient freedom to choose segments (numbers, letters, dots, dashes). I tend to use the library: "`SevenSeg` library".

Tell me a really good option for my goal, and so that, as always, this library does not slow down all the code

I am using an indicator of the form:
[![enter image description here][1]][1]

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

body:
This one  [tm1637][1] sounds good. I was thinking to use it next time.
**Edit 1:**
Lately posted image suggests that it is without a separate display controller chip, then this [library][2] should work.
**Edit 2:**
This library specific to the SH5461AS display: [Library][3]
 Include these three libraries:

    #include "Segment.h"
    #include "Digit.h"
    #include "Display.h"

Print needs to be in the loop:

    void loop() {
      d.print("1.234"); // Must be looped!
    }

  For disabling decimal points:

    #define DISABLE_DP
The library's Github has very good documentation too

  [1]: https://github.com/bremme/arduino-tm1637/blob/master/README.md
  [2]: https://github.com/DeanIsMe/SevSeg/blob/master/SevSeg.h
  [3]: https://github.com/UniQHW/SH5461AS


message:
Send data from one NodeMCU to another NodeMCU using Serial Communication

i am using NodeMCU (ESP8266) to communicate with another NodeMCU (ESP8266) using Serial Communication. Because i am using ESP-NOW to communicate and ESP-NOW and WiFi can not work together very well so trying with this serial communication option.

Here is how i connected the pins:

       Slave ->   Master
        D1    ->   D2
        D2    ->   D1
        GND   ->   GND

Here is how my sketch looks like:

**Sender.ino**

    #include <Wire.h>

    void setup() {
      Serial.begin(115200);
      Wire.begin(D1, D2); /* join i2c bus with SDA=D1 and SCL=D2 of NodeMCU */
    }

    void loop() {
      // put your main code here, to run repeatedly:
       Wire.beginTransmission(5); /* begin with device address 8 */
       Wire.write("Hello ESP 2");  /* sends hello string */
       Wire.endTransmission();    /* stop transmitting */

       Wire.requestFrom(5, 4); /* request & read data of size 13 from slave */
       while(Wire.available()){
          char c = Wire.read();
        Serial.print(c);
       }
       Serial.println();
       delay(1000);
    }

**Receiver.ino**

    #include <Wire.h>

    void setup() {
     Wire.begin(5);
     Wire.onReceive(receiveEvent); /* register receive event */
     Serial.begin(115200);           /* start serial for debug */
    }

    void loop() {
     delay(100);
    }

    // function that executes whenever data is received from master
    void receiveEvent(int howMany) {
     while (0 <Wire.available()) {
        char c = Wire.read();      /* receive byte as a character */
        Serial.print(c);           /* print the character */
      }
     Serial.println();             /* to newline */
    }

But the communication is not working at all, not sure where i am wrong. It can code wise or may be via connection wise or it might be possible that NodeMCU to NodeMCU connection is not possible at all!

Thank you!

body:
As already stated, your code uses the I2C interface (via the `Wire` library) and not the Serial interface (which is an Arduino term for UART). They work fundamentally different.

As you only communicate between 2 devices, which you both can program yourself. I would ditch the I2C interface. It doesn't give you any advantage here, but some disadvantages (for example, that you can't have real bidirectional communication, as the slave cannot do anything by its own, only, if the master asks for it).

Instead you should use a Serial (UART) interface. As the NodeMCU only has 1 full hardware Serial interface, which you already use for debugging, you could use the `ESPSoftwareSerial` library to create an extra Serial interface via software. It has limitations (in how many interfaces can listen at a time and how fast the communication can go), but most likely this will solve your problem. Also Serial is easier for beginners, than I2C.


message:
Using lambdas as callback functions

Using the [Ticker](https://github.com/bertmelis/Ticker-esp32/blob/master/src/ESP32Ticker.h) library for the ESP32, how can I use a lambda as an argument to the _attach_ method?

    tickerSystemManager.attach(1000, [&](){
      systemManager->sync();
    });

Attempting to use the above, I get the following error:

    Matrx.cpp:11:4: error: no matching function for call to 'Ticker::attach(int, Matrx::setup()::<lambda()>)'
    ...
    Ticker.h:40:8: note: candidate: void Ticker::attach(float, Ticker::callback_t)

How can I capp a lambda into this method?

body:
As @timemage explains in a comment, you cannot pass a capturing lambda
to a function that expects a plain pointer to function. There is,
however, a way out of this: the `Ticker` class provides an overload of
the `attach()` method that allows you to provide a parameter of any type
to tour callback:

```c++
template<typename TArg>
void attach(float seconds, void (*callback)(TArg), TArg arg)
```

You can use this version of `attach()` and provide it both

* a non-capturing lambda that gets a pointer to `systemManager`
* that pointer as a third argument.

**Edit**: I did a few tests, and it seems my compiler cannot properly
perform template argument deduction in this case, but the approach works
if you explicitly specialize the template. Namely:

```c++
tickerSystemManager.attach<typeof systemManager>(
    1000,
    [](typeof systemManager p){ p->sync(); },
    systemManager);
```