title: NodeMCU ESP8266 - Which pins can I use?

text:
# Question
Title: NodeMCU ESP8266 - Which pins can I use?
I'm trying to connect 3 LEDs to a LoLin NodeMCU ESP8266. It seems that several or "all" of the digital pins have some special use that prevents me from using them.

* If I connect the LEDs (and set pinmode to output) to D0, D1 and D2, then the blue bootloading LED will glow constantly, and the code does not seem to run at all (nothing in serial output).
* D3 seems to constantly have high power, regardless what I code it to.
* If I connect the LEDs (and set pinmode to output) to D1, D2 and D4, then the blue bootloading LED will glow constantly, and the serial output is garbled, but I guess the code is running.
* If I connect the LEDs (and set pinmode to output) to D5, D6 and D7, then the blue bootloading LED will glow constantly, and the serial output is garbled, but I guess the code is running.

Yes, I have checked the baud rate, that's not the problem.

What's up with this?

# Answer
This link at projecthub says:

> In order to use digital pins, you should select GPIO numbers. For example, the D7 pin is defined as GPIO13. So you should set up the pin number 13 whenever you want to use D7 in your program. Also, you can use pin D2(GPIO4) as SDA and pin D1(GPIO5) as SCL
> 0 votes

---
Tags: esp8266, nodemcu
---


title: Using MCP23017 to control Servos

text:
# Question
Title: Using MCP23017 to control Servos
Using Servo.h it is possible to run a servo from just about any pin.....obviously the more pins the more servos...hence the question " how can I do this with a MCP23017 ? ". I have searched the web a fair bit but no luck. Is there a modified Servo library out there?? It's such an obvious solution i figure it must have been done before. Any suggestions..Thanks.

# Answer
> 3 votes
> Using Servo.h it is possible to run a servo from just about any pin.....obviously the more pins the more servos...hence the question " how can I do this with a MCP23017?

The Servo library could be modified to allow toggling of GPIO pins on a MCP23017 but there are some issues with timing.

The library uses Timers and Interrupt Service Routines (ISR) to handle the pulse width. The servo pin is toggled in the ISR.

At 100 KHz (100 Kbps) I2C at least 3 bytes need to be transmitted to the MCP230017 to toggle a pin. That is approx. 300 us and not possible to do from the Servo ISR. Another execution pattern is required.

Cheers!

# Answer
> 2 votes
Theoretically, yes. It would be pretty interesting to see, but running multiple servos would account for a huge amount of what you can reasonably do with your code and probably be a huge headache.

Perhaps a better solution would be to use a PWM expander like the PCA9685.

# Answer
> 2 votes
> how can I do this with a MCP23017 ? ".

you can but it would be fairly expensive in processing power, as you need to keep track of both rising and falling edges of every channel at all times, and send the data to the chip -\> may not be doable given i2c's speed limitations.

> I have searched the web a fair bit but no luck.

I wrote a variety of approaches / implementations on driving multiple servo channels off of one timer, with or without output compare, here: https://dannyelectronics.wordpress.com/2017/02/18/driving-multiple-servos-off-a-pic-timer2-ranged-extended/

it will branch out to a few other variants, depending on resources available to you.

# Answer
> 2 votes
For PWM, the MCP23017 would have to be software-driven. I would suggest one of the PCA9685 boards, which give you hardware PWM (and can also provide digital pins). These are a bit more expensive, but very easy to use, and are driven by I2C in the same way.

# Answer
> 1 votes
For example...

```
unsigned long long servo_timing[2]={0,0};
int A_data=0;
void servo_ini()
{
  Wire.beginTransmission(0x20);
    Wire.write(0x00);      // address bank A
    Wire.write(0x00);
    Wire.endTransmission();
}
void servo_set(unsigned int servo_tim,bool servo_mod){
   if(servo_mod==1){
    servo_tim=map(servo_tim,0,180,200,1900);
   }
   //if(servo_vector<=0)/*lcd_tim=650;*/servo_tim=220;/0
   //if(servo_vector==1)/*lcd_tim=1400;*/servo_tim=1000;/90
   //if(servo_vector>=2)/*lcd_tim=2255;*/servo_tim=1870;/180
   if(micros()-servo_timing[0]>servo_tim)
   {
     A_data&=0b11111110;
     Wire.beginTransmission(0x20);
     Wire.write(0x12);      // address bank A
     Wire.write(A_data);
     Wire.endTransmission();
     if(micros()-servo_timing[1]>(20000-servo_tim))
     {
       A_data|=0b00000001;
       Wire.beginTransmission(0x20);
       Wire.write(0x12);      // address bank A
       Wire.write(A_data);
       Wire.endTransmission();
       servo_timing[0]=micros();
       servo_timing[1]=micros();
     }

  }
}

```

# Answer
> 1 votes
I succeeded in pwm (servo control) with mcp23017. Moreover, it is 16ch. The mcp23017 in the Arduino Library also has a wordwrite write, but the frequency still couldn't catch up. There is no choice but to create a library by yourself and generate a pulse of 0.5msec .. 2.5msec in 20msec 50Hz to drive the servo motor. We are currently organizing the library thank you https://twitter.com/chrmlinux03/status/1534834169737789441?s=20&t=EqkVXJ2v1H3i\_tfZsXfjHQ

https://github.com/chrmlinux/

---
Tags: arduino-uno, servo
---


# Question
Title: Is it possible to use assembly with arduino?
I want to learn assembly, but would like to learn by doing, is it possible to learn and make something useful with arduino hardware? I dont know where or how to start something like this.

# Answer
I suggest the ARV libC project as a starting point to HOW to get assmbler code running. And the AVR Instruction Set Manual to get hold of the actual assembler mnemonics.

Maybe also my own AVR Assembly Project might be a helpful starting point with its code available on GitHub.
> 3 votes

---
Tags: arduino-uno, assembly
---


# Question
Title: How to do 'for' loop over inline anonymous array
I have a bunch of pins given names in the header:

```
#define DIP5 53
#define DIP4 52
#define DIP3 51
#define DIP2 50
#define DIP1 49
#define DIP0 48

```

If it's not obvious, I have a bunch of DIP switches connected to digital pins 48..53 on an Arduino Mega2560

In setup(), I need to set them all to INPUT\_PULLUP. I know it would probably be less total effort to just do a series of pinMode commands, like:

```
pinMode(DIP5, INPUT_PULLUP);
pinMode(DIP4, INPUT_PULLUP);
// ... and so on

```

... but I'm trying to enrich my C++ skills & be fancy, so I'm trying to figure out how to declare an anonymous array and foreach through it... something like:

```
for (int pin : {DIP5, DIP4, DIP3, DIP2, DIP1, DIP0}) {
    pinMode(pin, INPUT_PULLUP);
}

```

... which, presumably, the compiler will optimize away into 6 inline pinMode commands anyway, but let me feel good about having pretty source code ;-)

except... when I try it, I get the following error:

`error: deducing from brace-enclosed initializer list requires #include <initializer_list>`

... but when I add `#include <initializer_list>`, I get a different error:

`fatal error: initializer_list: No such file or directory`

**Any ideas what's wrong?**

also... *can* I safely assume that the compiler will just unroll the whole thing behind the scenes, or is there a real risk it will *actually* declare a *real* array in SRAM just to iterate through one time?

# Answer
> I'm trying to enrich my C++ skills & be fancy

The Arduino Mega is probably not the right platform to learn fancy C++. The development environment doesn't support all the modern C++ stuff. In particular...

> `fatal error: initializer_list: No such file or directory`

...it rests on avr-libc, which is a C library with only limited support for C++.

> *can* I safely assume that the compiler will just unroll the whole thing behind the scenes

No, you can't. The Arduino IDE, by default, calls avr-gcc with the `-Os` flag, which means “optimize for code size”. Loop unrolling is the kind of space vs. speed trade-off the compiler is unlikely to do with this optimization setting. You can disassemble the .elf file if you want to know for sure.

> is there a real risk it will *actually* declare a *real* array in SRAM just to iterate through one time?

I suggest you follow jsotola's advice and declare the array yourself. You can declare the array `PROGMEM` if you want to avoid wasting RAM. But given that it need not take more than 6 bytes (as `uint8_t[]`), I would personally not even bother.
> 2 votes

# Answer
Edgar Bonet answers why `for (int pin : {DIP5, DIP4, DIP3, DIP2, DIP1, DIP0}) {` isn't working. What you would get (where supported) with this syntax is an `initializer_list` which itself is not an *array type*, although it is *backed* by an array.

If you really did want to do something *like* that with an AVR-based Arduino you could do:

```
for (int pin : (const int []){DIP5, DIP4, DIP3, DIP2, DIP1, DIP0}) {
    pinMode(pin, INPUT_PULLUP);
}

```

This is technically not standard C++. It is the use of something called a compound-literal, which is being used to make an array typed value. This is a feature of C language feature (from C99 onward), not C++. However, the compiler and its configuration for Arduino allows its use as a language extension.

Should you do this? *Perhaps* not, for the reasons that Edgar, 6v6gt, and jsotola point out. However, this much *can* be done if you really wanted. With respect to what it's doing efficiency-wise, you should test it.
> 1 votes

---
Tags: c++, platformio
---


# Question
Title: Multichannel communication with Arduino and HC-12 transmitter
The HC-12 module has 100 possible channels starting at 433 MHz. Can someone tell me how to program the Arduino to use multiple channels at the same time? My goal is to build an RC transmitter with Arduino and an HC-12 module for a quadcopter. Therefore I need 6 channels, like a normal transmitter does. Thanks in advance!

# Answer
> 2 votes
I believe you are misunderstanding what it means by channels. The HC-12 can transmit on up to 100 channels, which means different frequencies under the 433 MHz band. For example 433.05 MHz or 433.15 MHz. This is so multiple HC-12 modules can be used next to each other and only the module receiving on the channel of the transmitter will receive the data broadcast.

What you need to do for your quadcopter is send an array of bytes that begins with a constant, followed by the data you need (a packet). Example:

```
byte packet[] = {0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}

// in your loop
packet[1] = ; HOW MUCH THE ENGINE IS THROTTLED
packet[2] = ; HOW FAR THE CONTROL TO GO FORWARD IS DEPRESSED
// etc

```

Iterate through this array writing the data through the serial port to the HC-12. Whenever your receiver detects the constant (in this case 0x00) read the values that follow as the controls for the quadcopter.

# Answer
> 0 votes
I'm starting on HC-12 myself and as I understand, you can only access 1 module at a time by selecting each modules individual channel, assuming you have set the modules to separate channels, you cannot receive data from multiple modules even if set to the same channel at the same time, it would just be a jumble of unsortable data. But you may be able to select one channel after another and collect each set of data separately 1 thru 6 and then extract the information you need by using AT+C001,002,etc. Or you could use 1 RX and program the on board arduino to cycle thru the 6 motors sequentially and collect the 6 sets of data that way. this question would be easier to answer with a diagram of you proposed circuit.

---
Tags: arduino-uno, programming, communication
---


title: Tone() function pauses between notes

text:
# Question
Title: Tone() function pauses between notes
I tried to experiment with the `tone()` function that comes with the arduino library.

I played around with the standard code example located here: https://www.arduino.cc/en/Tutorial/BuiltInExamples/toneMelody

This is the code:

```
#include "pitches.h"

int melody[] =
{
  NOTE_C4, NOTE_G3, NOTE_G3, NOTE_A3, NOTE_G3, 0, NOTE_B3, NOTE_C4
};

int noteDurations[] =
{
  4, 8, 8, 4, 4, 4, 4, 4
};

void setup()
{
   for (int thisNote = 0; thisNote < 8; thisNote++)
   {
      int noteDuration = 1000 / noteDurations[thisNote];
      tone(8, melody[thisNote], noteDuration);

      // to distinguish the notes, set a minimum time between them.
      // the note's duration + 30% seems to work well:
      int pauseBetweenNotes = noteDuration * 1.30;
      delay(pauseBetweenNotes);

      // stop the tone playing:
      noTone(8);

   }
}

void loop()
{
  // no need to repeat the melody.
}

```

However, the problem is that there is always a pause between notes. In musical terms, this is called `staccato`. I want to be able to play short melodies where there are no delays between the notes, and one note progresses to the next naturally. By the way, this is called `legato` in music theory.

Now, in this example, the delay between the notes sounds good because this "music piece" is supposed to be played this way. But in every other song that i experimented with, there were always some pauses between notes.

This is what this song sounds like: https://soundcloud.com/nikowow-1/normal

Naturally, my mind went to the `delay(pauseBetweenNotes)` function. So i thought this is what causes the delay between the notes. So i set it up to `0.5`. This is what it sounds like: https://soundcloud.com/nikowow-1/05a

As you can hear, it just speeds up the whole song. The delay between the notes remain, but the whole song is sped up (in a higher tempo, so to speak).

In order to better hear the delay between the notes, please take a listen at the song when i selected a value of `3` \- causing a smaller tempo, so that the delay between the notes can be more easily audible: https://soundcloud.com/nikowow-1/3a-1

I want to create some melodies where there are no delays between the notes and i am stuck.

EDIT: If you remove the delay line alltogether, the song is played so quickly that only a click sound is heard.

# Answer
there is

```
      // to distinguish the notes, set a minimum time between them.
      // the note's duration + 30% seems to work well:
      int pauseBetweenNotes = noteDuration * 1.30;
      delay(pauseBetweenNotes);

```

so the \*1.30 creates the pause.

if you change it to

```
   int pauseBetweenNotes = noteDuration;

```

there will be no pause between notes.

The tone length is specified with the last parameter of the tone() function (`noteDuration` here).
> 3 votes

---
Tags: audio, sound, delay, wave
---


# Question
Title: ESP32 AsyncWebServer with softAP does not serve pages
I'm trying to create a `AsyncWebServer` after enabling the `SoftAP`:

```
#include <Arduino.h>
#include <SPIFFS.h>
#include <WiFi.h>
#include <WiFiAP.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>

WebApp webapp;

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

  File f = SPIFFS.open("/index.html");
  String s = f.readString();
  Serial.println(s);
  f.close();

  WiFi.softAP("ssid", NULL);
  WiFi.softAPsetHostname("ssid");
  Serial.println(WiFi.softAPIP());

  webapp.Begin();
}

void loop()
{
}

class WebApp
{
public:
    WebApp();
    void Begin();

private:
    AsyncWebServer _server;
};

#include "webapp.h"

WebApp::WebApp() : _server(80)
{
}

void WebApp::Begin()
{
  _server.on("/", HTTP_GET, [this](AsyncWebServerRequest *request)
  {
    Serial.println("GET request");
    _server.serveStatic("/", SPIFFS, "/").setDefaultFile("/index.html");
  });

  _server.onNotFound([](AsyncWebServerRequest *request){
    request->send(404);
  });

  _server.begin();
  Serial.println("[WEB] HTTP server started");
}

```

The `SoftAP` brings up the network and I can connect to it (`softAPgetStationNum()` tells me that 1 client is connected). It answers to pings. The `index.html` is stored into the flash (the contents is printed out correctly).

But when I try to open the root page (192.168.4.1) it prints out "GET request" but the browser request timeouts and nothing is received.

Am I missing anything in the code?

# Answer
> 3 votes
The usage of `serveStatic()` is wrong. It's not intended to be used inside a callback. Just place the call in the setup of the webserver, i.e.:

```
void WebApp::Begin()
{
  _server.serveStatic("/", SPIFFS, "/").setDefaultFile("/index.html");

  _server.onNotFound([](AsyncWebServerRequest *request)
  {
    request->send(404);
  });

  _server.begin();
  Serial.println("[WEB] HTTP server started");
}

```

# Answer
> 3 votes
I don't have enough rep to make a comment on your post, but is it possible that when you give the parameter for the function `setDefaultFile()` that the forward slash on `/index.html` is causing the path of the file to be `//index.html` instead of `/index.html`.

Because serveStatic is probably appending the filename of `setDefaultFile()` to the root directory of `/` (the third parameter of `serveStatic()`), you're probably getting an extra character you don't want in your filepath.

**TL;DR** you don't need the `/` in `index.html` for `setDefaultFile()`.

See https://github.com/me-no-dev/ESPAsyncWebServer#serving-files-in-directory for the example.

---
Tags: esp32, web-server, spiffs
---


# Question
Title: Quaternion values from Arduino 9-axis motion shield seem very wrong
I am currently usinga BNO055 sensor fitted on the Arduino Nine-axis motion shield to measure ocean wave heights and periods. To do this, I'd like to use the quaternions provided, however I have a slight issue. A quaternion should be \<cos(theta/2), X*sin(theta/2), Y*sin(theta/2), Z\*sin(theta/2)\>, with X, Y and Z the coordinates of a unit vector and theta the angle of rotation around that vector. Therefore, I expect all three to be inferior to one.

However, when I run a simple code to see the raw data, the W given by my sensor when on the table is 16 375, and X, Y and Z values are in the high hundreds range...

This gives me a wave height of hundreds of thousands of kilometers :slightly\_smiling\_face:

Does anyone know why this happens? Do I need to divide the quaternion by it's norm to get the correct result? Or maybe I am misunderstanding the use of a quaternion?

Oh, and I have calibrated the sensor beforehand

Thanks in advance for your help

# Answer
I am not familiar with this sensor, so I am just guessing.

The sensor is likely giving you fixed-point numbers. Judging from the real part, there are most likely 14 bits right of the implicit radix point. If that is the case, the actual quaternion can be computed as:

```
float w = raw_w / 16384.0;
float x = raw_x / 16384.0;
float y = raw_y / 16384.0;
float z = raw_z / 16384.0;

```

You can check whether this is reasonable by computing the norm, which should be very close to one.
> 1 votes

---
Tags: accelerometer, gyroscope, magnetometer
---


# Question
Title: External Interrupt not working on 3.3V atmega168
I made a 3.3V board and I've put both atmega328p (that I pulled off of a 3.3V pro mini), and an atmega168 that I bootloaded (using USBtinyISP whilst selecting board "Arduino Pro or Pro Mini" and "atmega168 (3.3V, 8MHz") .

Everything works perfectly with the atmega328 - code works and interrupts do as well - which function to pull the Arduino out of sleep when INT0 rises.

However on the Atmega168, the interrupt doesn't seem to work. All the normal code works as expected (communications, instructions etc), just not the interrupt. After the Arduino goes to sleep, I can't wake it since the interrupt isn't working.

Basic code below:

```
#include <avr/sleep.h>//this AVR library contains the methods that controls the sleep modes

byte interruptPin = 2; //Turn board on/off
unsigned long shutDownTimer = 0; // Timer for shutdown

void setup() {
  Serial.begin(57600);
  pinMode(interruptPin, INPUT); //Set pin d2 to input using the buildin pullup resistor
  Serial.println("Starting");

}

void loop() {
  Serial.println("Awake");
  delay(1000);

  // Shutdown control
  if (digitalRead(interruptPin) == LOW ) {
    Serial.println("Shutdown detected");
    shutDownTimer = millis();
    while (digitalRead(interruptPin) == LOW ) {
      if (millis() - shutDownTimer > 1000) {
        Serial.println("sleep mode triggered");
        Going_To_Sleep();
      }
    }
  }
}

void Going_To_Sleep() {
  sleep_enable();//Enabling sleep mode
  delay(1000);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);//Setting the sleep mode, in our case full sleep
  delay(1000); //wait a second to allow the led to be turned off before going to sleep
  attachInterrupt(0, wakeUp, RISING);//attaching a interrupt to pin d2

  Serial.println("Interrrupt attached");//Print message to serial monitor
  sleep_cpu();//activating sleep mode
  Serial.println("just woke up!");//next line of code executed after the interrupt

}

void wakeUp() {
  sleep_disable();//Disable sleep mode
  detachInterrupt(0); //Removes the interrupt from pin 2;
  Serial.println("Interrrupt Fired - wakeup");//Print message to serial monitor

}

```

Instead of using "attachInterrupt(0, wakeUp, RISING);" Ive also tried the following which also don't work:

```
attachInterrupt(INT0, wakeUp, RISING);
attachInterrupt(digitalPinToInterrupt(interruptPin), wakeUp, RISING);
attachInterrupt(32, wakeUp, RISING);  //since its the pin of the chip? Hail Mary
attachInterrupt(2, wakeUp, RISING);  //obviously this won't work, Hail Mary 2

```

I have no idea why the interrupts aren't working. I have an inkling it might be due to something fuse related within the boot loader, but I don't really understand things at that level (Though I'm happy to dive in with some guidance). Any guidance will be appreciated!

# Answer
> 0 votes
According to the datasheet for the Atmega168:

> Note that recognition of falling or rising edge interrupts on INT0 or INT1 requires the presence of an I/O clock, described in Section 6.1 “Clock Systems and their Distribution” on page 23. Low level interrupt on INT0 and INT1 is detected asynchronously. This implies that this interrupt can be used for waking the part also from sleep modes other than idle mode. The I/O clock is halted in all sleep modes except idle mode

In other words, only the LOW interrupt wakes it from sleep.

Having said that, the Atmega328P does wake from sleep with a rising or falling interrupt, as I have previously had confirmed by Atmel, however I can't say for sure that this enhancement (over what is stated in the datasheet) applies to the 168.

You could try doing a bit of testing to confirm that. Maybe rejig so that the interrupt occurs when the signal goes low rather than high, and then use a LOW interrupt and not a RISING one.

Also, don't do serial prints inside an ISR. The modern versions of the library handles that better than in the past, but this may still be an issue. As suggested in a comment, try flashing an LED rather than printing something. Or don't print anything, after all you print something when it wakes up. Why print something extra inside the ISR? That is just asking for trouble.

# Answer
> 1 votes
Depending on what signal you are using to wake the Arduino, you may also find pin change interrupts an alternative to the edge triggered interrupts you are currently using. These are usually more predictable in behaviour and less subject to nuanced interpretations of the data sheets. See https://playground.arduino.cc/Main/PinChangeInterrupt/ for examples of how to use these.

---
Tags: interrupt, bootloader, sleep
---


# Question
Title: PubSub'a - KeepAlive function not as expected
I'm using `PubSubClient` to pub/sub MQTT messages using ESP8266.

As far as I know "Keep-alive" detects when a client went off-line after a period of time.

I'm using library's example `mqtt_ESP8266` with 2 minor adjusments (noted "\<----- 1/2"), to use keepAlive.

1. Timeout was set to 45 sec (`client.setKeepAlive(45);`), in order to be "far enough" from reboot.
2. Pressing on-board Reset button.
3. Although Wifi+MQTT connection establish after 10 sec, and mqtt sends messages as shown `loop`, a "DEAD" publish is sent to designated topic after roughly 45 seconds from (2) , whuch makes no sense since MQTT was reconnected 35 seconds before.

Appreciate assistance, Guy

```
/*
  Basic ESP8266 MQTT example
  This sketch demonstrates the capabilities of the pubsub library in combination
  with the ESP8266 board/library.
  It connects to an MQTT server then:
  - publishes "hello world" to the topic "outTopic" every two seconds
  - subscribes to the topic "inTopic", printing out any messages
    it receives. NB - it assumes the received payloads are strings not binary
  - If the first character of the topic "inTopic" is an 1, switch ON the ESP Led,
    else switch it off
  It will reconnect to the server if the connection is lost using a blocking
  reconnect function. See the 'mqtt_reconnect_nonblocking' example for how to
  achieve the same result without blocking the main loop.
  To install the ESP8266 board, (using Arduino 1.6.4+):
  - Add the following 3rd party board manager under "File -> Preferences -> Additional Boards Manager URLs":
       http://arduino.esp8266.com/stable/package_esp8266com_index.json
  - Open the "Tools -> Board -> Board Manager" and click install for the ESP8266"
  - Select your ESP8266 in "Tools -> Board"
*/

#include <ESP8266WiFi.h>
#include <PubSubClient.h>

// Update these with values suitable for your network.

const char* ssid = "Wifi";
const char* password = "Password";
const char* mqtt_server = "192.168.2.100";

WiFiClient espClient;
PubSubClient client(espClient);
unsigned long lastMsg = 0;
#define MSG_BUFFER_SIZE (50)
char msg[MSG_BUFFER_SIZE];
int value = 0;

void setup_wifi() {

  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

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

  randomSeed(micros());

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

void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();

  // Switch on the LED if an 1 was received as first character
  if ((char)payload[0] == '1') {
    digitalWrite(BUILTIN_LED, LOW);   // Turn the LED on (Note that LOW is the voltage level
    // but actually the LED is on; this is because
    // it is active low on the ESP-01)
  } else {
    digitalWrite(BUILTIN_LED, HIGH);  // Turn the LED off by making the voltage HIGH
  }

}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Create a random client ID
    String clientId = "ESP8266Client-";
    clientId += String(random(0xffff), HEX);
    // Attempt to connect
    client.setKeepAlive(45);  \\ <--------- Line 1
    if (client.connect(clientId.c_str(), "guy", "kupelu9e", "myHome/log", 0, true, \\ < "DEAD")) { \\ <---- Line 2
      Serial.println("connected");
      // Once connected, publish an announcement...
      client.publish("outTopic", "hello world");
      // ... and resubscribe
      client.subscribe("inTopic");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void setup() {
  pinMode(BUILTIN_LED, OUTPUT);     // Initialize the BUILTIN_LED pin as an output
  Serial.begin(115200);
  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
}

void loop() {

  if (!client.connected()) {
    reconnect();
  }
  client.loop();

  unsigned long now = millis();
  if (now - lastMsg > 2000) {
    lastMsg = now;
    ++value;
    snprintf (msg, MSG_BUFFER_SIZE, "hello world #%ld", value);
    Serial.print("Publish message: ");
    Serial.println(msg);
    client.publish("myHome/debug", msg);
  }
}

```

# Answer
This is the correct behavior.

The “last will” message is sent by the broker when it detects that the client has gone away.

When you reset the ESP8266, the original connection to the broker is destroyed. When it restarts, it creates a new, second connection, it does not resume the original connection. So the broker correctly transmits the last will message when the original connection times out.
> 2 votes

---
Tags: esp8266, mqtt
---


title: passive buzzer is drawing 500mA

text:
# Question
Title: passive buzzer is drawing 500mA
I am having a ridiculously hard time trying to make a passive buzzer work correctly on my Seeeduino XIAO.

Here is the buzzer module :

Here is how I believe it works, assuming the SOT23 smd is a PNP transistor? :

I plugged VCC to a +5V rail, GND to the ground rail, and I/O pin to my Seeeduino XIAO's pin 2 (aka "A2 / D2" :

When I write `DigitalWrite(2, LOW)`, I can mesure about 0.4V on pin 2, while `DigitalWrite(2, HIGH)` reads about 3.3V (I assume the 5V rail feeding my Seeeduino XIAO's VCC gets converted to 3v3 through an internal regulator)

I understand I have to oscillate the signal to make this module buzz (remember it is a passive buzzer, or a transducer, whatever it is called), or simply use the `tone()` method, and I eventually managed to make this beep on and off every 1 second successfully during 10 seconds, but what bothers me is that I can NOT turn this module OFF after 10 seconds as a test in my sketch. It stops beeping after 10 sec as expected (`ìf (millis() < 10000) { doBeep(); }` , but it still draws massive current and gets hot after that delay. It's like the PNP transistor never turns off? I tried both digitalWrite HIGH and LOW but no success.

This is driving me crazy. What am I doing wrong?

# Answer
You're right that it's a PNP transistor - the SS8550 to be precise.

And therein lies the problem.

When running at 5V to "make no current flow" through the base the voltage at the base has to be higher than 4.4V (5v - 0.6v), and since you're controlling it from a 3.3V microcontroller that can never happen. So you are right in thinking it never turns off - it never does.

Even when you're "beeping" it it's not turning fully off, so the beep sounds you make will be reduced accordingly.

You should power the board from 3.3V instead of 5V so the PNP can turn off fully. If that is not possible then switching the GPIO pin to INPUT mode will prevent it from driving the PNP thus allowing it to turn itself off.
> 0 votes

---
Tags: buzzer, seeeduino-xiao
---


title: Using Software Serial on Arduino Mega

text:
# Question
Title: Using Software Serial on Arduino Mega
So Im using this sensor: https://wiki.dfrobot.com/Serial\_6\_Axis\_Accelerometer\_SKU\_SEN0386 with this library https://github.com/DFRobotdl/DFRobot\_WT61PC

Im using 2 sensors but got poor frequency on Arduino Uno and decicded to switch to Mega since it supports multiple communications at once.

This code works perfectly fine on Uno, but doesnt on Mega. Of course I tried using this method: https://docs.arduino.cc/built-in-examples/communication/MultiSerialMega and I know I shouldnt be using Software Serial on Mega but **this library has been written using Software Serial and I cant use a different method** (or at least thats how I understand it).

Here is the reason.

```
SoftwareSerial mySerial(10, 11);
DFRobot_WT61PC sensor(&mySerial);

```

So I tried multiple variations of pins (ones supporting UART, pcint, TX/RX) https://docs.arduino.cc/learn/built-in-libraries/software-serial and nothing seems to we working. Also tried removing the SD card reader, tried the original example code. I also tried Hardware Serial as it should be but again, it doesnt support this sensor and ends up resulting in errors(or vice versa). Nothing.

Here is the working Uno code:

```
#include <DFRobot_WT61PC.h>
#include <SoftwareSerial.h>
#include <SPI.h>
#include <SD.h>

#define FILE_BASE_NAME "Pomiar"
#define VCC2 7

const uint8_t CS_PIN = 4;

SoftwareSerial mySerial(2, 3);
SoftwareSerial mySerial2(5, 6);
DFRobot_WT61PC sensor(&mySerial);
DFRobot_WT61PC sensor2(&mySerial2);

File myFile;
File file;

const uint8_t BASE_NAME_SIZE = sizeof(FILE_BASE_NAME) - 1;
char fileName[] = FILE_BASE_NAME "00.txt";

void setup()
{

  pinMode(VCC2,OUTPUT);
  digitalWrite(VCC2,HIGH);

  //Use Serial as debugging serial port
  Serial.begin(9600);
  Serial.print("Initializing SD card...");

  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    while (1);
  }
  Serial.println("initialization done.");

  while (SD.exists(fileName)) {
    if (fileName[BASE_NAME_SIZE + 1] != '9') {
      fileName[BASE_NAME_SIZE + 1]++;
    } else if (fileName[BASE_NAME_SIZE] != '9') {
      fileName[BASE_NAME_SIZE + 1] = '0';
      fileName[BASE_NAME_SIZE]++;
    } else {
      Serial.println(F("Can't create file name"));
      return;
    }
  }

  //Use software serial port mySerial as communication seiral port
  mySerial.begin(9600);
  mySerial2.begin(9600);
  //Revise the data output frequncy of sensor FREQUENCY_0_1HZ for 0.1Hz, FREQUENCY_0_5HZ for 0.5Hz, FREQUENCY_1HZ for 1Hz, FREQUENCY_2HZ for 2Hz,
  //                        FREQUENCY_5HZ for 5Hz, FREQUENCY_10HZ for 10Hz, FREQUENCY_20HZ for 20Hz, FREQUENCY_50HZ for 50Hz,
  //                        FREQUENCY_100HZ for 100Hz, FREQUENCY_125HZ for 125Hz, FREQUENCY_200HZ for 200Hz.
  sensor.modifyFrequency(FREQUENCY_10HZ);
  sensor2.modifyFrequency(FREQUENCY_10HZ);
}

void loop()
{

  long timestamp = millis();

  float acc1;
  float acc2 ;
  float acc3 ;
  float gyro1 ;
  float gyro2 ;
  float gyro3;
  float angle1;
  float angle2;
  float angle3;

  float acc12 ;
  float acc22 ;
  float acc32 ;
  float gyro12;
  float gyro22 ;
  float gyro32 ;
  float angle12 ;
  float angle22;
  float angle32;

  mySerial.listen();
  if (sensor.available()) {

    acc1 = sensor.Acc.X;
    acc2 = sensor.Acc.Y;
    acc3 = sensor.Acc.Z;
    gyro1 = sensor.Gyro.X;
    gyro2 = sensor.Gyro.Y;
    gyro3 = sensor.Gyro.Z;
    angle1 = sensor.Angle.X;
    angle2 = sensor.Angle.Y;
    angle3 = sensor.Angle.Z;

  }

  mySerial2.listen();
  if (sensor2.available()) {

    acc12 = sensor2.Acc.X;
    acc22 = sensor2.Acc.Y;
    acc32 = sensor2.Acc.Z;
    gyro12 = sensor2.Gyro.X;
    gyro22 = sensor2.Gyro.Y;
    gyro32 = sensor2.Gyro.Z;
    angle12 = sensor2.Angle.X;
    angle22 = sensor2.Angle.Y;
    angle32 = sensor2.Angle.Z;

  }

  myFile = SD.open(fileName, FILE_WRITE);

  if (myFile) {
    myFile.print(timestamp);
    myFile.print("|");
    myFile.print(acc1);
    myFile.print("|");
    myFile.print(acc2);
    myFile.print("|");
    myFile.print(acc3);
    myFile.print("|");
    myFile.print(gyro1);
    myFile.print("|");
    myFile.print(gyro2);
    myFile.print("|");
    myFile.print(gyro3);
    myFile.print("|");
    myFile.print(angle1);
    myFile.print("|");
    myFile.print(angle2);
    myFile.print("|");
    myFile.print(angle3);
    myFile.println("");

    myFile.print(timestamp);
    myFile.print("|");
    myFile.print(acc12);
    myFile.print("|");
    myFile.print(acc22);
    myFile.print("|");
    myFile.print(acc32);
    myFile.print("|");
    myFile.print(gyro12);
    myFile.print("|");
    myFile.print(gyro22);
    myFile.print("|");
    myFile.print(gyro32);
    myFile.print("|");
    myFile.print(angle12);
    myFile.print("|");
    myFile.print(angle22);
    myFile.print("|");
    myFile.print(angle32);
    myFile.println("");

    myFile.close();
  } else {
    Serial.println("error opening test.txt");
  }
}

```

I also found this question: Arduino Mega 2560 SoftwareSerial Not Working. The guy has exact problem as I do but nooone found a solution to it. I also want to note that the manufacturer states that this library and sensor works fine on Mega. Really need your help.

cheers

@edit So I did some tests and the only code that actually shows something in monitor is:

```
#include <DFRobot_WT61PC.h>

DFRobot_WT61PC sensor(&Serial);

void setup()
{
  //Use Serial as debugging serial port

  //Use software serial port mySerial as communication seiral port
  Serial.begin(9600);
  sensor.modifyFrequency(FREQUENCY_10HZ);
}

void loop()
{
  if (sensor.available()) {
    Serial.print("Acc\t"); Serial.print(sensor.Acc.X); Serial.print("\t"); Serial.print(sensor.Acc.Y); Serial.print("\t"); Serial.println(sensor.Acc.Z); //acceleration information of X,Y,Z
    Serial.print("Gyro\t"); Serial.print(sensor.Gyro.X); Serial.print("\t"); Serial.print(sensor.Gyro.Y); Serial.print("\t"); Serial.println(sensor.Gyro.Z); //angular velocity information of X,Y,Z
    Serial.print("Angle\t"); Serial.print(sensor.Angle.X); Serial.print("\t"); Serial.print(sensor.Angle.Y); Serial.print("\t"); Serial.println(sensor.Angle.Z); //angle information of X, Y, Z
    Serial.println(" ");
  }
}

```

But as you see the output is corrupted.

# Answer
It's quick and dirty but you can make it Mega compatible by deleting the line `#include <SoftwareSerial.h>`, and replacing the lines

```
SoftwareSerial mySerial(2, 3);
SoftwareSerial mySerial2(5, 6);

```

with

```
#define mySerial Serial1
#define mySerial Serial2

```

replacing `Serial1` and `Serial2` with whichever of the Mega's serial ports you wish to use for mySerial and mySerial2, and connecting your DFRobot sensor signals to the correct pins for your chosen hardware serial ports.
> 0 votes

# Answer
There are three fairly major issues in your code:

* The Mega does not support SoftwareSerial on pins 2, 3, 5, 6 because those pins do not support change interrupts. Thus it simply can't work on those pins. This itself is a show-stopper.
* Your code to read data is flawed. You test if a single byte is available (sensor.available()) and then proceed to read 9 bytes. There is no guarantee that 8 of them are actually there.
* I'm confused about what you are doing in your second block of code. You are telling the sensor library to get its data from Serial, which is where you type stuff. All that would do is echo what you type, bearing in mind my point directly above.
> 0 votes

---
Tags: arduino-mega, softwareserial, imu
---


# Question
Title: Help with reading data from ADXL373 Accelerometer (I2C)
I am using ADXL373Z accelerometer with Arduino Uno for a project.

When I run the code, I am getting incorrect values which are probably not even acceleration data. I am thinking it might be a wiring problem, I attached circuit diagram below. This is my first Arduino project, and I couldn't find any other applications with the sensor I am using so any help would be much appreciated. Thanks in advance.

Datasheet for sensor : https://www.analog.com/media/en/technical-documentation/data-sheets/adxl373.pdf

Code ( for x-axis data only) :

```
// ADXL373 Accelerometer Test

#include <Wire.h>

/* -------- REGISTERS -------- */
#define ADDRESS_ADXL373 0x53 // sensor adress (assumes MISO pin high)
#define ADDRESS_POWER_CTL 0x3F // power control
#define ADDRESS_MEASURE 0x0E // measurement control
#define ADDRESS_TIMING 0x3D // output data rate and extarnal timing triggers
#define ADDRESS_XDATA_H 0x08 // x-axis acceleration data [11:4]
#define ADDRESS_XDATA_L 0x09 // x-axis acceleration data [3:0]
#define ADDRESS_YDATA_H 0x0A // y-axis acceleration data [11:4]
#define ADDRESS_YDATA_L 0x0B // y-axis acceleration data [3:0]
#define ADDRESS_ZDATA_H 0x0C // z-axis acceleration data [11:4]
#define ADDRESS_ZDATA_L 0x0D // z-axis acceleration data [3:0]
/* -------- REGISTERS -------- */

#define SCALE_FACTOR 0.2f // 200 mg per LSB scaling factor
#define GRAVITY_EARTH 9.80665f // gravity of earth in m/s^2

void setup() {
  Serial.begin(115200);
  while(!Serial);
  Serial.println("ADXL373 Accelerometer Test");
  Wire.begin();
  Wire.beginTransmission(ADDRESS_ADXL373);
  Wire.write(ADDRESS_POWER_CTL);
  Wire.write(0x03); // activate full bandwith measurement mode
  Wire.endTransmission(true);
  delay(50);
  Wire.beginTransmission(ADDRESS_ADXL373);
  Wire.write(ADDRESS_MEASURE);
  Wire.write(0x04); // set output signal bandwith to 2560 Hz
  Wire.endTransmission(true);
  delay(50);
  Wire.beginTransmission(ADDRESS_ADXL373);
  Wire.write(ADDRESS_TIMING);
  Wire.write(0x80); // set output data rate to 5120 Hz
  Wire.endTransmission(true);
  delay(50);
}

void loop() {
  byte xAxisH, xAxisL;
  Wire.beginTransmission(ADDRESS_ADXL373);
  Wire.write(ADDRESS_XDATA_H);
  Wire.endTransmission(false);
  Wire.requestFrom(ADDRESS_ADXL373, 1, true);
  xAxisH = Wire.read();
  Wire.beginTransmission(ADDRESS_ADXL373);
  Wire.write(ADDRESS_XDATA_L);
  Wire.endTransmission(false);
  Wire.requestFrom(ADDRESS_ADXL373, 1, true);
  xAxisL = Wire.read();
  int16_t xAxisFinal;
  xAxisFinal = (uint16_t) xAxisH << 8 | xAxisL; // bit shift and combine two components
  xAxisFinal = xAxisFinal >> 4; // 12-bit resolution
  float xAccel;
  xAccel = xAxisFinal * SCALE_FACTOR * GRAVITY_EARTH;
  Serial.print("Xa = "); Serial.println(xAccel);
  delay(200);
}

```

Circuit Diagram :

Results from Serial Monitor (in m/s^2) :

# Answer
According to the datasheet, the 12 bits of the X acceleration are stored into the registers `XDATA_H` and `XDATA_L` as follows:

```
XDATA_H:   b₁₁b₁₀b₉ b₈ b₇ b₆ b₅ b₄
XDATA_L:   b₃ b₂ b₁ b₀ x  x  x  x

```

where `x` means “reserved”.

Now, there are two issues with this code:

```
xAxisFinal = xAxisH << 4 | xAxisL; // bit shift 12-bit output data

```

The first issue is that, by shifting `xAxisH` by four places, the bits b₇–b₄ end up in the same positions as the bits b₃–b₀ in `xAxisL`. Then, when those values are combined with `|`, the bit b₇ gets mixed with b₃, b₆ with b₂, etc. If you really want to shift `xAxisH` left by four places, you should also shift `xAxisL` right by four places.

The second issue is that the x data is a signed number represented as two's complement, and the sign bit (b₁₁) ends up in the wrong place. For example, if the measured value is −16 (XDATA\_H:XDATA\_L = 0xff:0x00), you end up reading 4980 (0x0ff0). In order to avoid this issue you could sign extend the 12-bit number to 16 bits.

I would suggest, though, a completely different approach. The number is left justified in the sensor registers, so just keep it like this:

```
xAxisFinal = (uint16_t) xAxisH << 8 | xAxisL;

```

The intermediate cast to `uint16_t` is here to avoid an undefined behavior, the final result is signed. If there is some risk that the reserved bits are non-zero (the datasheet is not very clear in this respect), you could

```
xAxisFinal &= 0xfff0;  // clear last 4 bits

```

Note that now the unit of the acceleration is 1/16 of the resolution of the sensor, and all values you get are multiples of 16. I don't expect this to be an issue. If you really want to use the sensor resolution as your unit, you could now shift `xAxisFinal` four places to the right, which would automatically perform the sign extension.

---

**Edit**: Addressing the edited code from the OP:

> I modified the code according to your suggestions. But I am still getting incorrect values from serial monitor.

What I see in your post is very small values, around ±3 LSBs of the sensor. This could very well be sensor noise. But then, there is the occasional larger value. Interestingly, those larger values seem to be very close to ±16 LSBs, hinting at some kind of communication problem.

I guess the answer is in this warning from the sensor's datasheet:

> Always read acceleration data using multibyte transfers to ensure that a concurrent and complete set of x, y, and z acceleration data is read.

Imagine the sensor is outputting only noise, and the noise fluctuates between −1 and +1 LSB. What you expect then is:

```
value  XDATA_H   XDATA_L
  −1   11111111  11110000
  +1   00000000  00010000

```

If you read `XDATA_H` and `XDATA_L` in two different transactions, you may well read 0b11111111 for `XDATA_H` (as the sensor is reading −1), then read `00010000` for `XDATA_L` (as it is getting +1). When you combine these two readings together, you get

```
value  XDATA_H   XDATA_L
 −15   11111111  00010000

```

I suggest you follow the recommendation from the datasheet and read both registers in one go:

```
Wire.beginTransmission(ADDRESS_ADXL373);
Wire.write(ADDRESS_XDATA_H);
Wire.endTransmission(false);
Wire.requestFrom(ADDRESS_ADXL373, 2, true);
xAxisH = Wire.read();
xAxisL = Wire.read();

```
> 5 votes

---
Tags: sensors, accelerometer
---


title: Measured voltage higher than AREF

text:
# Question
Title: Measured voltage higher than AREF
What happen when a voltage measured by analogRead() is higher than AREF voltage?

Example: AREF = 2.5V AO = 3.2V

What is the maximum voltage ?

# Answer
> 3 votes
You will be reading the maximum ADC value. If you were sampling a waveform the top of it would be clipped off at 2.5v.

---
Tags: analogread, voltage
---


# Question
Title: Arduino Pro Micro not recognised by computer or showing up in ports
Around 4 days ago my Arduino Pro Micro arrived. I've been messing around with it, using it to run keyboard commands on a computer. Just recently, whenever I plug it in to the computer it isn't detected by ports or anything. The green light is still on, and the left red light (looking at it from the side of the micro USB input) still works as well, however the right red light no longer works. Can someone tell me what's happening? Have I broken it all ready?

# Answer
The `arduino pro micro` is notoriously difficult to program. I am sure you have figured this out when first installing the drivers but on power up, the micro runs a `bootloader` for `<750ms` so for me at least, it was extremely difficult to install drivers.

However, if you look at this guide by sparkfun, you will see that resetting the board in quick succession will load a longer `8 sec` bootloader, which gives your more time to program it. Obviously, this is not normally something you need to worry about as the `Arduino IDE` automatically resets the board sending it into the bootloader when you upload a sketch to it.

Back to your problem, if it is not popping up as a device when you plug it in to your computer, go into `control panel > system > hardware > device manager` and look to see if you can find it there. If it still doesn't show up, do what I said above and reset it twice and hopefully you will see the bootloader appear where you can reinstall the drivers for it. You can find the appropriate drivers in the same location where you installed the `IDE` originally.

Hope this helps!
> 2 votes

# Answer
Sorry to tack onto a 4yr old thread, but hoping this helps others, as it would have me.

Unbeknownst to me,some USB micro cables are power-only and don't have the data lines. I had one of these in my rotation of cables, and while the LEDs lit up nicely, the USB does not appear. I was sure it was not a cable prob as I thought I'd tried multiples. I was unaware I had one of these power only USB cables about - marked with the USB Trident just like the others.

So if you have the 'dead USB' problem with your Pro Micro, do make the effort to be absolutely sure of your cable situation.

I read the debugging posts across the web far and wide, but I yada-yada'd the cable check, as I never saw anyone point out the cable might be undamaged, but just a null-data variant. My bad obvs - but just FYI for others like me.
> 1 votes

---
Tags: arduino-micro
---


# Question
Title: ISR for very fast processes, strange code found. Has ISR effect on timer behaviour?
I found the following code within an example for performing very fast changes on a PWM-output. It works, however I'm wondering about some details.

TIMER2 was set up in setup() as follows:

```
TCCR2A = 0;               // We need no options in control register A
TCCR2B = (1 << CS21);     // Set prescaller to divide by 8
TIMSK2 = (1 << OCIE2A);   // Set timer to call ISR when TCNT2 = OCRA2
OCR2A = 32;               // sets the frequency of the generated wave
sei();                    // Enable interrupts to generate waveform!

```

If I understand that correctly, the timer will run until overflow and generate interrupts any time in between as defined by OCR2A.

```
ISR(TIMER2_COMPA_vect) {  // Called each time TCNT2 == OCR2A
  static byte index=0;    // Points to successive entries in the wavetable
  OCR1AL = wave[index++]; // Update the PWM output
  asm("NOP;NOP");         // Fine tuning
  TCNT2 = 6;              // Timing to compensate for time spent in ISR
}

```

TIMER2 is used to call this routine in equidistant points in time. To adapt the timespan between two calls of the ISR the author sets OCR2A and within the ISR resets TCNT2. As the timer is reset at the end of the ISR there's some time "already gone" written into the start value of the timer. However there are two things I don't understand.

1. Why isn't CTC mode used by setting WGM21 in TCCR2A? This should call the ISR in precise intervals.
2. If not using CTC mode the counter has to be reset by the ISR. But why isn't that done directly at the beginning of the ISR? Everytime the ISR gets some minor changes the correction value written into TCNT2 has to be changed.

Am I missing some vital detail? Or is my idea of using CTC better?

For sake of completeness, the only other things done in setup() are configurations on timer1:

```
pinMode(9, OUTPUT);       // Make timer's PWM pin an output
TCCR1B  = (1 << CS10);    // Set prescaler to full 16MHz
TCCR1A |= (1 << COM1A1);  // PWM pin to go low when TCNT1=OCR1A
TCCR1A |= (1 << WGM10);   // Put timer into 8-bit fast PWM mode
TCCR1B |= (1 << WGM12);

```

loop() is empty.

# Answer
> Why isn't CTC mode used by setting WGM21 in TCCR2A?

As we cannot read the author's mind, we cannot say for sure. That being said, to me, the most likely reason is that either the author was not aware of CTC mode, or they just didn't think about it.

You are right that CTC is the most straightforward way to get precise intervals. You are also right that the resetting the timer at the end of the ISR makes the code somewhat fragile. If, for some reason, I needed to avoid CTC in a code like this, I would

```
OCR2A += 32;

```

rather than resetting `TCNT2`.
> 5 votes

---
Tags: arduino-uno, timers, isr
---


# Question
Title: PWM on Wemos D1 Mini (esp8266 chip) does not work
I am working on a hobby project: creating an rc-(radio controlled)-toy car.

I'm working with a **Wemos D1 Mini** (esp8266) microcontroller, **L298N** H-bridge (for controlling the motor) and I'm using the **Arduino IDE** to program it all.

The project is quite simple: make the car drive around via an virtual joystick on an app. The project is quite fun and a nice learning experience for me. The project is going pretty well until this point.

I can move the car forwards and backwards with a constant speed, but I'm not able to change the speed via a **PWM** signal. Actually, I'm not even sure if it is even possible to create a PWM signal on the Wemos D1 Mini, I have never done it before on this specific controller. I'm not an electrical engineer, so I'm not really familiar with very specific details about the controller itself.

Can somebody help me create a PWM signal to control the speed of the car?

This is what I have got now, very basic stuff:

```
void setup() {
  pinMode(D2, OUTPUT);
  pinMode(D5, OUTPUT);
  pinMode(D6, OUTPUT);
  pinMode(D7, OUTPUT);
  pinMode(D8, OUTPUT);
}

void forward() {
  digitalWrite(D5, LOW);
  digitalWrite(D6, HIGH);
}

void backward() {
  digitalWrite(D5, HIGH);
  digitalWrite(D6, LOW);
}

void setVelocity(int value){
  analogWrite(D2, value);
}

void loop() {
  setVelocity(1023);
  forward();
}

```

Thanks in advance!

Sincerly,

Stefan

# Answer
At one point `analogWrite` as it was implemented in the esp8266-core had defaulted to a 10-bit range. This is no longer the case. It defaults to 8-bit range now.

In any case `analogWrite` is implemented to clamp the given value to be within the range.

If you were not experimenting in the bottom quarter of the velocity range with your code as written then you would have seen full velocity.

You can change to working with the 8-bit range or use `analogWriteRange(new_range)` or `analogWriteResolution(bits)` as this mentions.

Your code as is will produce a 50% duty cycle 1Khz signal on D2 if setVelocity is given 128 with the current core.
> 2 votes

---
Tags: esp8266, pwm
---


# Question
Title: Determining ArduinoJSON document size based on file size
I'm trying to effectively allocate a doc's size, based on the size of the file saved in flash of ESP8266. Is there a way?

For example: `file.size()` X 1.5

# Answer
> 4 votes
There is unfortunately no way to predict the size of the `JsonDocument` from the file size alone.

As a workaround, I suggest that you allocate a very large memory pool and shrink it after deserialization; like so:

```
DynamicJsonDocument doc(ESP.getMaxAllocHeap());
deserializeJson(doc, file);
doc.shrinkToFit();

```

Indeed, this program consumes more memory than strictly required, but only for a fraction of a second.

See also:

---
Tags: esp8266, json
---


title: Funduino USB Host Shield problems

text:
# Question
Title: Funduino USB Host Shield problems
I'm currently working on connecting a Funduino version of usb host shield onto an arduino mega board. But the serial output shows "osc did not start", which means the board can't find the shield. However the reset button works, so I estimate insufficient power being supplied.

I'm aware of the bridging solution for the regular arduino module for the 3.3v and 5v (example). But how can this solution be applied to the Funduino model.

Update: I've changed the SPI lines on the shield to the 6 ISCP pins on the Mega, but still no change in results.

I performed a second test using board\_qc, which returned:

Circuits At Home 2011

USB Host Shield Quality Control Routine

Reading REVISION register... Die revision invalid. Value returned: 00

Unrecoverable error - test halted!!

0x55 pattern is transmitted via SPI

Press RESET to restart test

# Answer
> 0 votes
That shield communicates over SPI. However the SPI pins it uses are the "old" style (10-13) for the Arduino UNO.

The Mega doesn't use those pins, which is why the "new" style 6-pin SPI/ICSP header was added to boards.

You will have to manually jumper the right pins to the SPI pins of the Mega using wires.

---
Tags: arduino-mega, usb, spi, shields
---


# Question
Title: Can we use more than one timer when programming an Atmega32/16?
I tried to do a simple program using the ATmega16 microcontroller, the program is to toggle two LEDs the first one by using timer0 interrupt and the other using timer2 interrupt.

# Answer
> 0 votes
Yes, you can. However there is one thing to note:

**Only one ISR can run at once.**

That means that if one LED wants to toggle while the other one is in the process of toggling it will have to wait until that first ISR is finished before it can toggle.

For simple LED toggling that won't be noticeable, but it's something you need to bear in mind if you are doing multiple things that require precise timing.

# Answer
> 1 votes
Yes, we can.

(stackexchange wants the body of the answer to be at least 30 characters, so I have to add some filler. Truth is, for answering the question *as asked*, there is nothing more to say.)

---
Tags: atmega328, attiny, atmel, atmega16u2, atmega
---


# Question
Title: Why does the data I send to the server get rounded off and how do I send the entire float instead?
```
#include <Arduino.h>
#include <WiFi.h>
#include "WiFiManager.H"
#include <HTTPClient.H>
#include "ESPAsyncWebServer.h"
#include <AsyncTCP.h>

float version = 1.9;

uint32_t chipId = 0;
String chipId2 = "";
int i;

String serverName = "http://d";

// WiFiManager
// Local intialization. Once its business is done, there is no need to keep it around
WiFiManager wifiManager;

// Create AsyncWebServer object on port 80
AsyncWebServer server2(80);
WiFiServer server(80);

// variables to count the pulses of the meters.
int count1=0;
float prior_count1=0;
int count2=0;
float prior_count2=0;
int count3=0;
float prior_count3=0;
int count4=0;
float prior_count4=0;
int countgas=0;
float prior_countgas=0;
int countwater=0;
float prior_countwater=0;

String payloadpulse = "0";

unsigned long lastTime = 0;
unsigned long timerDelay = 6000;

String guifactor1 = "1000";
String guifactor2 = "1000";
String guifactor3 = "1000";
String guifactor4 = "1000";
String guifactorgas = "1000";
String guifactorwater = "1000";

String counter1 = "1";
String counter2 = "1";
String counter3 = "1";
String counter4 = "1";
String counter5 = "1";
String counter6 = "1";

// function to increment the meters value by 1.
void pulse1() {
  if (counter1.toInt() == 1) {
    count1 = count1 + 1;
  }

  if (counter1.toInt() == 2) {
    count1 = count1 - 1;
  }
}

void pulse2() {
  if (counter2.toInt() == 1) {
    count2 = count2 + 1;
  }

  if (counter2.toInt() == 2) {
    count2 = count2 - 1;
  }
}

void pulse3() {
  if (counter3.toInt() == 1) {
    count3 = count3 + 1;
  }

  if (counter3.toInt() == 2) {
    count3 = count3 - 1;
  }
}

void pulse4() {
  if (counter4.toInt() == 1) {
    count4 = count4 + 1;
  }

  if (counter4.toInt() == 2) {
    count4 = count4 - 1;
  }
}

void pulsegas() {
  if (counter5.toInt() == 1) {
    countgas = countgas + 1;
  }

  if (counter5.toInt() == 2) {
    countgas = countgas - 1;
  }
}

void pulsewater() {
  if (counter6.toInt() == 1) {
    countwater = countwater + 1;
  }

  if (counter6.toInt() == 2) {
    countwater = countwater - 1;
  }
}

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

  wifiManager.autoConnect("ss", "ss");

  pinMode(25, INPUT_PULLDOWN); // Set GPIO25 as digital output pin
  attachInterrupt(digitalPinToInterrupt(25), pulse1, RISING);

  pinMode(19, INPUT_PULLDOWN); // Set GPIO19 as digital output pin
  attachInterrupt(digitalPinToInterrupt(19), pulse2, RISING);

  pinMode(23, INPUT_PULLDOWN); // Set GPIO22 as digital output pin
  attachInterrupt(digitalPinToInterrupt(23), pulse3, RISING);

  pinMode(18, INPUT_PULLDOWN);// Set GPIO18 as digital output pin
  attachInterrupt(digitalPinToInterrupt(18), pulse4, RISING);

  pinMode(21, INPUT_PULLDOWN); // Set GPIO22 as digital output pin
  attachInterrupt(digitalPinToInterrupt(21), pulsegas, RISING);

  pinMode(5, INPUT_PULLDOWN); // Set GPIO5 as digital output pin
  attachInterrupt(digitalPinToInterrupt(5), pulsewater, RISING);
}

//--------------------------------------------------------------------
void loop() {
  float new_count1  = static_cast<float> (count1) / guifactor1.toInt();
  float new_count2 = static_cast<float> (count2) / guifactor2.toInt();
  float new_count3 = static_cast<float> (count3) / guifactor3.toInt();
  float new_count4 = static_cast<float> (count4) / guifactor4.toInt();
  float new_countgas = static_cast<float> (countgas) / guifactorgas.toInt();
  float new_countwater = static_cast<float> (countwater) / guifactorwater.toInt();

  // keeps track of the amount of pulses of pulse meters
  if (new_count1 != prior_count1 ||
   new_count2 != prior_count2 ||
    new_count3 != prior_count3 ||
     new_count4 != prior_count4 ||
      new_countgas != prior_countgas ||
       new_countwater != prior_countwater) {
     Serial.println(new_count1, 4);
     Serial.println(new_count2, 4);
     Serial.println(new_count3, 4);
     Serial.println(new_count4, 4);
     Serial.println(new_countgas, 4);
     Serial.println(new_countwater, 4);
     prior_count1 = new_count1;
     prior_count2 = new_count2;
     prior_count3 = new_count3;
     prior_count4 = new_count4;
     prior_countgas = new_countgas;
     prior_countwater = new_countwater;
  }
  // sends an update to the web
  if ((new_count1 > 0 && ((millis() - lastTime) > timerDelay)) ||
   (new_count2 > 0 && ((millis() - lastTime) > timerDelay)) ||
    (new_count3 > 0 && ((millis() - lastTime) > timerDelay)) ||
     (new_count4 > 0 && ((millis() - lastTime) > timerDelay)) ||
      (new_countgas > 0 && ((millis() - lastTime) > timerDelay)) ||
       (new_countwater > 0 && ((millis() - lastTime) > timerDelay))) {
  {
      // checks if wifi is connected.
      if (WiFi.status()== WL_CONNECTED) {
        HTTPClient http;
        // preparation HTTP GET request.
         String serverPath = serverName + "?chip_id=" + chipId + "&count1=" + new_count1 + "&count2=" + new_count2 + "&count3=" +
         new_count3 + "&count4=" + new_count4 + "&countgas=" + new_countgas + "&countwater=" + new_countwater;
        // Your Domain name with URL path or IP address  with path.
        http.begin(serverPath.c_str());
        // Send HTTP GET request.
        int httpResponseCode = http.GET();
        // confirms the arrival of a response from the server or sends an error.
        if (httpResponseCode>0) {
          count1 = 0;
          count2 = 0;
          count3 = 0;
          count4 = 0;
          countgas = 0;
          countwater = 0;
          payloadpulse = http.getString();
          Serial.println(payloadpulse);
         }
         else {
          Serial.print("Error code: ");
          Serial.println(httpResponseCode);
         }
        // closes the HTTP connection.
        http.end();
      }
      else {
       Serial.println("WiFi Disconnected");
      }
    }
  }

  //reset timer when done sending data
  if (((millis() - lastTime) > timerDelay)) {
    lastTime = millis();
  }
}

```

The program is a pulse counter which should add 0.001 pulse everytime it detects one. I expect it to send 0.006 to the server, but instead it sends 0.01. How do I make sure it doesn't send rounded data?

# Answer
> 3 votes
The constructor for the String object from float is this:

```
String(double, unsigned char decimalPlaces=2);

```

So if you don't want to have 2 decimal digits, you have to use `String(someFloat, 3)`.

Also you have to remember there are limits for the floating point numbers, but in this case it shouldn't be the case.

And as Edgar mentioned, String objects are bit dangerous if they are overused, particularly building that serverPath is the worst way how to do it (every single level of it creates new temp object to be copied into next bigger one and released).

It would be cheaper to do it like:

```
String serverPath;
serverPath.reserve(100); // reserve space so it doesn't have to resize; should be proper estimate
serverPath += serverName;
serverPath += "?chip_id=";  // on AVR it should be F()
serverPath += chipId;
serverPath += "&count1=";
serverPath += new_count1;
serverPath += "&count2=";
serverPath += new_count2;
serverPath += "&count3=";
serverPath += new_count3;
serverPath += "&count4=";
serverPath += new_count4;
serverPath += "&countgas=";
serverPath += new_countgas;
serverPath += "&countwater=";
serverPath += new_countwater;

```

or you can use some c++ magic:

```
template <class T> inline String & operator<<(String & out, T const & what) {
    out += what;
    return out;
}

String serverPath;
serverPath.reserve(100); // reserve space so it doesn't have to resize

serverPath << serverName << "?chip_id=" << chipId << "&count1="
           << new_count1 << "&count2=" << new_count2 << "&count3="
           << new_count3 << "&count4=" << new_count4 << "&countgas="
           << new_countgas << "&countwater=" << new_countwater;

```

this code takes `serverPath << serverName` adds serverName into serverPath and the result is serverPath again, and then it continues as `serverPath << "?chip_id="` and so on

---
Tags: web-server, float, data
---


# Question
Title: Create member object using constructor arguments, or pass reference to object via constructor
I'm not entirely sure about the proper C++ terminology, so I'll just illustrate what I'm trying to achieve by giving a Java example since it should be pretty obvious:

```
public class LcdDecorator {
    private HD44780Lcd lcd;

    public LcdDecorator(int rows, int cols, int i2cAddress) {
        this.lcd = new HD44780Lcd(rows, cols, i2cAddress);
    }
}

```

or... alternatively...

```
public class LcdDecorator {
    private HD44780Lcd lcd;

    public LcdDecorator(HD44780Lcd lcd) {
        this.lcd = lcd;
    }
}

```

For what it's worth, there's no real concern about scope... LcdDecorator is a Singleton that gets created in setup(), then lives forever and gets used by loop() until the power gets shut off.

#### Here's what I've attempted so far:

`LcdFacade.h`:

```
#ifndef CORECONTROLLER_LCDFACADE_H
#define CORECONTROLLER_LCDACADE_H

#include <stdint.h>
#include "../.pio/libdeps/megaatmega2560/HD44780_LCD_PCF8574/src/HD44780_LCD_PCF8574.h"

class LcdFacade {

public:
    LcdFacade(uint8_t rows, uint8_t cols, uint8_t i2cAddress) ;
};

#endif //CORECONTROLLER_LCDFACADE_H

```

`LcdFacade.cpp`:

```
#include "LcdFacade.h"
#include "../.pio/libdeps/megaatmega2560/HD44780_LCD_PCF8574/src/HD44780_LCD_PCF8574.h"

HD44780LCD lcd;

LcdFacade::LcdFacade (uint8_t rows, uint8_t cols, uint8_t i2cAddress) : lcd{rows, cols, i2cAddress} {
    // ... the rest of the constructor goes here ...
}

```

note: I also tried using parentheses instead of braces for lcd's constructor:

```
LcdFacade::LcdFacade(uint8_t rows, uint8_t cols, uint8_t i2cAddress) : lcd(rows, cols, i2cAddress) {

```

In CLion, the 'lcd{rows, cols, i2caddress}' portion of the constructor in LcdFacade.cpp is red-underlined, and reports `member initializer 'lcd' does not name a non-static data member or base class`

Meanwhile, gcc(?) reports `error: no matching function for call to 'HD44780LCD::HD44780LCD()` on line 4 of LcdFacade.cpp.

Any ideas?

# Answer
When you define

```
HD44780LCD lcd;

```

at global scope, you are creating a global variable that is initialized before `main()` is called. In this case, it is initialized with the default constructor `HD44780LCD::HD44780LCD()`, which does not exist, hence the error. You could avoid this error by calling a suitable constructor in the initialization, e.g.

```
HD44780LCD lcd(4, 20, 0x23);

```

but this may be inconvenient to you.

If you want to initialize `lcd` in the constructor of `LcdFacade`, then it must be a non-static member of the class:

```
// In LcdFacade.h:
class LcdFacade {
public:
    LcdFacade(uint8_t rows, uint8_t cols, uint8_t i2cAddress);
private:
    HD44780LCD lcd;  // <- non-static member
};

// In LcdFacade.cpp:
LcdFacade::LcdFacade(uint8_t rows, uint8_t cols, uint8_t i2cAddress)
: lcd(rows, cols, i2cAddress) {
    ...
}

```
> 2 votes

---
Tags: c++
---


# Question
Title: Will the atmega8-U2 work with Arduino IDE
I use a homemade board that hosts a PIC16F1829 and an ATmega328P on the same board. We use the ATmega328P with the Arduino IDE and the PIC with the MPLABX IDE for about 100 EE students a semester at UTSA. I have 100 pic chips but no ATmega328P chips, I can re-spin the board and adapt it to the ATmega8-U2, since right now I can by 250 ATmega8-U2 chips that are in stock but there are no ATmega328P chips available anywhere and I need 100 at least. I am currently using a different UART to TTL adapter, the CP2102 to connect the ATmega328P to the Arduino IDE. I have the 2 chips talk via a shared I2C line. How difficult will it be to use the Arduino IDE with the ATmega8-U2? (Again, not as the UART to USB interface but as the main processor. Thanks,

# Answer
I never tried, but it seems to me it should work without issues.

In the Arduino IDE, Menu Tools → Board, you can select “Arduino NG or older”. You then have a menu Tools → Processor where you can select either “ATmega168” or “ATmega8”. These options don't require you to install any extra board support package: they come with the default “classic” AVR core, which does support the ATmega8.
> 2 votes

---
Tags: arduino-ide, atmega
---


# Question
Title: Servo retaining its position every time I send some value
I wanted to control my servo with a Bluetooth module.

I gave certain values for rotating it. When I press those values the servo rotates, but then retains its original position and the PC also makes the sound of the Arduino board disconnecting because I powered the board with my PC (tried with powerbank also). Even my Bluetooth disconnects.

This is my code:

```
#include <Servo.h>

Servo myservo;
int pos = 0;
char data = 0;

void setup() {
  myservo.attach(9);
  Serial.begin(9600);
}

void loop() {
  if (Serial.available() > 0) {
    data = Serial.read();
    if (data == 'F') {
      // for (pos = 0; pos <= 180; pos += 1)
      myservo.write(180);
      delay(1);
    }
  }
  else if (data == 'B') {
    // for (pos = 180; pos >= 0; pos -= 1)
    myservo.write(0);
    delay(1);
  }
}

```

Connections:

Servo:

```
red wire -- 5 V (not working at 3.3 V)
orange wire -- pin9
brown wire -- gnd

```

Bluetooth (hc05):

```
5 V -- 5 V
gnd -- gnd
rx -- tx
tx -- rx

```

# Answer
I tried changing the USB B cable with a better quality one and it worked.
> 0 votes

---
Tags: arduino-uno, bluetooth, servo, hc-05
---


# Question
Title: Efficient way to save accelerometer data on sd card
I have analog accelerometer that transfer acceleration on 3 axis with frequency 5 kHz. I want to store that data in SD card for in txt file. My sketch is the following:

```
void loop()
{

  // Get raw accelerometer data for each axis
  int rawX = analogRead(A0);
  int rawY = analogRead(A1);
  int rawZ = analogRead(A2);

  // Scale accelerometer ADC readings into common units
  // Scale map depends on if using a 5V or 3.3V microcontroller
  float scaledX, scaledY, scaledZ; // Scaled values for each axis
  if (micro_is_5V) // Microcontroller runs off 5V
  {

    scaledX = mapf(rawX, 0, 1023, -scale, scale); // 3.3/5 * 1023 =~ 675
    scaledY = mapf(rawY, 0, 1023, -scale, scale);
    scaledZ = mapf(rawZ, 0, 1023, -scale, scale);

  }
  else // Microcontroller runs off 3.3V
  {
    scaledX = mapf(rawX, 0, 675, -scale, scale);
    scaledY = mapf(rawY, 0, 675, -scale, scale);
    scaledZ = mapf(rawZ, 0, 675, -scale, scale);
  }

   String dataString = "";
   // Concatenate string
   dataString += String(scaledX);
   dataString += "\t\t";
   dataString += String(scaledY);
   dataString += "\t\t";
   dataString += String(scaledZ);
   dataString += "\t\t";
   saveSD();
}

// Same functionality as Arduino's standard map function, except using floats
float mapf(float x, float in_min, float in_max, float out_min, float out_max)
{
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

void saveSD()
{
  // create file for writing
  File dataFile = SD.open("datalog.txt", FILE_WRITE);
  // if file is available
  if (dataFile) {
    // save the data
    dataFile.println(dataString);
    // close file
    dataFile.close();
  } else {
    // if file is unavailable
    Serial.println("Error opening datalog.txt");
  }
}

```

So in loop I open file, write to it and after that close it. When my file will be big enough there will be bottle neck.It will take a lot of time to read and write file. How to deal with saving data to files on SD card?

**UPD:** I measured the time of executing code like that:

```
  ...
  start_open_t=micros(); // time in milli seconds
  File dataFile = SD.open("datalog.txt", FILE_WRITE);
  delta_open_t=micros() - start_open_t ;
  // if file is available for writing
  if (dataFile) {
    // save the data
    start_write_t=micros(); // time in milli seconds
    dataFile.println(dataString);
    delta_write_t=micros() - start_write_t ;
    // close the file
    start_close_t=micros(); // time in milli seconds
    dataFile.close();
    delta_close_t=micros() - start_close_t ;
    ...

```

And there is the result:

```
Open time:
7656
Write time:
2176
Close time:
8076

```

The open time is increasing there is no surprise (with increasing the file size).
Write to file and close time is almost constant. I thought to open file in setup() and initialize timer. Write to file in loop() and after some time interval to close the file, after that open new file and so on. But as can be seen the print operation `dataFile.println(dataString);` takes approximately 2 ms that is 500 Hz, and it is too slow. I need to register with 5 kHz. If I print in serial the data is printed much faster but I can not connect to usb because arduino is located to far (approx 30 meters). May be there is the way to connect to serial with wifi or bluetooth or may be there are another methods to store the data fast?

# Answer
I can see it is safe to open/close the file every time, especially closing, as if the Arduino loses power, the entire file can be corrupted possibly.

However, I can find of some 'solutions':

1. Backup battery

Open the file in `setup()`, and only close the file when the backup battery becomes active (instead of closing the file after every write). This will however need an external battery, and some implementation to check if it is active. Also, during the external battery is active, no data should be written.

2. Using multiple files

More easier is to use multiple files, and write each time period (less than the size of the file that cause problems) in a separate file. You can either close the file after each write, or when starting a new period, meaning when the Arduino loses power, you only lose the last time period.

3. Using binary format

This can be used in combination with solution 1 and 2, and is to not write the files as text files but in binary format, reducing the size considerably.
> 1 votes

---
Tags: sd-card
---


# Question
Title: ESP8266 Wemos D1 min pro - how to change TCP_SND_BUF?
Is there any way to change the TCP send buffer size (TCP\_SND\_BUF) on this module ?

Now it is equal to `TCP_SND_BUF = 2 * TCP_MSS = 2 * 1460 = 2920`.

Editing `lwipopts.h` doesn't make any difference.

The same question applies to `ΤCP_MSS`, `TCP_WND` etc.

I am using v2 Higher Bandwidth variant. Platform is Microchip Studio with vMicro Arduino addon.

# Answer
I finally figured it out the hard way :

https://github.com/esp8266/Arduino/discussions/8616

---

Install **Git** for windows (https://git-scm.com/download/win)

Install **MinGW** for windows (https://sourceforge.net/projects/mingw)

In **MinGW** installation manager, enable:

* mingw-developer-toolkit
* mingw32-base
* mingw32-gcc-g++
* msys-base

*(not sure if all are necessary but just in case)*

put *C:\MinGW\bin* in Windows PATH (check this https://www.rapidee.com)

## **reboot PC**

rename **C:\MinGW\bin\mingw32-make.exe** to **C:\MinGW\bin\make.exe**

open **bash** terminal (just type bash in run)

*(from now on assume that hardware files are in \Documents\Arduino\hardware\esp8266com\esp8266)*

go to *\tools\sdk\lwip2*

optional: change **lwip options** in *\tools\sdk\lwip2\builder\glue-lwip\arduino\lwipopts.h*

(caution : **NOT** *\tools\sdk\lwip2\include\lwipopts.h*, this will be overwritten !)

type in bash: **make install** to build libraries in *\esp8266com\esp8266\tools\sdk\lwip2\builder*

type in bash: **make clean** to clean *\esp8266com\esp8266\tools\sdk\lwip2\builder*

finally copy new libraries to *\esp8266com\esp8266\tools\sdk\lib*
> 1 votes

# Answer
No, you can't.

The macro you are trying to tweak is for reference only and does not control the size of the buffer.

On the ESP8266 the IP stack (and much of the rest of the system) is precompiled as `.a` libraries. Changing things like the `TCP_SND_BUF` macro will never change what has been compiled into those libraries. Instead all it will do is cause problems of buffer overruns and corrupted data as other code is then given incorrect information about the size of the buffer.
> 1 votes

---
Tags: esp8266, c, tcpip
---


title: Library fails to compile

text:
# Question
Title: Library fails to compile
I want to try out this library: https://github.com/connornishijima/arduino-volume3

I downloaded the zip file from github, renamed it, and included it as a library in the IDE.

So run one of the examples, `A4_440HZ` This is its code:

```
#include "Volume3.h"
#define speakerPin 9

uint16_t frequency = 440;

void setup() {
  // Nothing neeeded here!
}

void loop() {
  for(uint16_t volume = 0; volume < 1023; volume++){
    vol.tone(speakerPin,frequency,volume);
    delay(1);
  }
  for(uint16_t volume = 1023; volume > 0; volume--){
    vol.tone(speakerPin,frequency,volume);
    delay(1);
  }
}

```

And i get this error:

```
Error Compiling
A4_440Hz.cpp.o: In function `loop':
/usr/share/arduino/A4_440Hz.ino:12: undefined reference to `vol'
/usr/share/arduino/A4_440Hz.ino:12: undefined reference to `vol'
/usr/share/arduino/A4_440Hz.ino:16: undefined reference to `vol'
/usr/share/arduino/A4_440Hz.ino:16: undefined reference to `vol'
collect2: error: ld returned 1 exit status

```

I have no idea what is to blame, or how to mitigate it.

This is the first time that an included example from a library does not play out of the box.

# Answer
This is kind of a weird situation. The library declares the object `vol`, but fails to define it. On the ancient version of the Arduino IDE you are using, compilation fails, understandably, because `vol` has never been defined. What is weird is that, on a more recent version (1.8.15 on Ubuntu here), compilation succeeds.

It is worth noting that `vol` belongs to the class `Volume`, which is an empty class. As such, it only plays the role of a namespace for the functions `vol.tone()` and `vol.noTone()`. Strictly speaking, as `vol` has no data (its size is zero), the compiler should never need to access it. My guess is that the newer Arduino manages to compile this only because it uses different optimization settings than the ancient 1.0.5.

Anyhow, you have two options:

* upgrade your installation of the Arduino IDE
* declare `Volume vol;` near the top of the sketch.

**Edit**: I did some tests and it appears that, as I suspected, this is related to link-time optimization (LTO). Since version 1.5.7, the Arduino IDE enables LTO, and when this is the case, the linker doesn't complain about missing empty objects.

The library could be fixed by defining `vol` in Volume3.cpp, although this would create a weird empty object in the BSS. Another option would be to declare both methods as `static` within Volume3.h. This would make the compiler know it doesn't actually need to reference the `vol` object when one of its methods is called.

Would you submit a pull request with one of those fixes?
> 2 votes

---
Tags: library, audio
---