title: esp8266 esp01s EEPROM and flashing

text:
# Question
Title: esp8266 esp01s EEPROM and flashing
which flash option do I need to take to use EEPROM?

Can I flash with 1MB and no SPIFFs and still write data to EEPROM?

thanks T

# Answer
> Can I flash with 1MB and no SPIFFS and still write data to EEPROM?

Yes. The EEPROM emulation is saved into different part of the flash, not to SPIFFS.

```
|--------------|-------|---------------|--|--|--|--|--|
^              ^       ^               ^     ^
Sketch    OTA update   File system   EEPROM  WiFi config (SDK)

```

the memory map is from esp8266 SPIFFS docs

> which flash option do I need to take to use EEPROM?

There is no special option in Tools menu for EEPROM emulation. Only use the library.
> 1 votes

---
Tags: esp8266, eeprom, flash
---


title: How to write a float value EEPROM

text:
# Question
Title: How to write a float value EEPROM
I'm using this library for my DS3231 which have a Atmel 24C32 on it. i have a float value which increases by 0.5, like:

27.50

28

28.50 ...

the code is like this:

```
float lowTemp= 10.5

float highTemp= 10.5

void setup(){
  lowTemp = i2c_eeprom.read(100);
  highTemp = i2c_eeprom.read(101);
}
void loop(){
  if ((menuswtichStatus == HIGH) && (lcdWelcome == HIGH)) {
    previousMillis = millis();
    lcd.clear();
    menuScroll++;
    lcdClear = 1;
    lcdClear2 = 1;
  }
  if (menuScroll == 1) {
    lcd.setCursor(0, 0);
    lcd.print("Temperature set:");
    lcd.setCursor(0, 1);
    lcd.print("Minimum  ");
    lcd.print(lowTemp);
    lcd.print((char)223);
    lcd.print("C ");
    if (plusSwitchstatus == HIGH) {
      lowTemp += 0.5;
    }
    if (minusSwitchstatus == HIGH) {
      lowTemp -= 0.5;
    }
  }
  if (menuScroll == 2) {
    lcd.setCursor(0, 0);
    lcd.print("Temperature set:");
    lcd.setCursor(0, 1);
    lcd.print("Maximum  ");
    lcd.print(highTemp);
    lcd.print((char)223);
    lcd.print("C ");
    if (plusSwitchstatus == HIGH) {
      highTemp += 0.5;
    }
    if (minusSwitchstatus == HIGH) {
      highTemp -= 0.5;
    }
  }
  if (menuScroll == 3) {
    lcd.setCursor(0, 0);
    lcd.print("   Saving the");
    lcd.setCursor(0, 1);
    lcd.print("   Settings...");
    delay(1000);
    i2c_eeprom.write(100, lowTemp);
    i2c_eeprom.write(101, highTemp);
    delay(1000);
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("    SETTINGS");
    lcd.setCursor(0, 1);
    lcd.print("     SAVED!");
    delay(2000);
    menuScroll = 0;
    lcdClear = 0;
    lcdClear2 = 0;
  }
}

```

*i have the library and stuff up there, it's just an example of my code...*

The float value is not saving(written), what's the solution?

# Answer
You have multiple options:

1. According to jsotola's remark: the easiest is to multiply your value by 2, store it, and after reading, divide it by 2. In one byte you can store a value from 0 to 127.5 (255 / 2), or if you use signed from -64.0 to +63.5. Of course you also can use an offset in case you know the value cannot be less than e.g. -20.
2. If you need a higher range, you can still multiply it by 2, but store it in two bytes. Split the value in a 'high value' (value % 256) / 256, and a 'low value' (value % 256).
3. If you want to store the value completely, than use sizeof(float) to find the length, and a for loop to write each byte, starting from the first byte of the float until the last one.
> 3 votes

---
Tags: eeprom, float
---


# Question
Title: problem data I2C to sensor GY955/BNO055 (China)
I want to ask, I have a problem when running the Arduino sensor, I can't output data, but it's detecting that the sensor address has been paired.
Like I2C has a problem or locks it.

Last night it worked only because my twin sensors tried another with the same program after I compiled and uploaded, I see the serial monitor is only a detection sensor, but it doesn't display data, so the pitch evaporates and the roll data is 0.0,0.

There seems to be a problem with i2c: the data does not come out, it only detects the sensor address but the contents are all zero. Have you ever experienced this?

This initially worked, because the sensor was the same and I tried it with the same program after reading GY 955 / BNO055 on Euler\_streaming it only showed zero per axis.

This is code in the bread board

```
/****************************************************************************

    Euler_Streaming.pde - part of sample SW for using BNO055 with Arduino

   (C) All rights reserved by ROBERT BOSCH GMBH

   Copyright (C) 2014 Bosch Sensortec GmbH

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

 **************************************************************************/
/*  Date: 2014/01/07
     Revision: 1.2

*/
#include "BNO055_support.h"     //Contains the bridge code between the API and Arduino
#include <Wire.h>

//The device address is set to BNO055_I2C_ADDR2 in this example. You can change this in the BNO055.h file in the code segment shown below.
// /* bno055 I2C Address */
// #define BNO055_I2C_ADDR1                0x28
// #define BNO055_I2C_ADDR2                0x29
// #define BNO055_I2C_ADDR                 BNO055_I2C_ADDR2

//Pin assignments as tested on the Arduino Due.
//Vdd,Vddio : 3.3V
//GND : GND
//SDA/SCL : SDA/SCL
//PSO/PS1 : GND/GND (I2C mode)

//This structure contains the details of the BNO055 device that is connected. (Updated after initialization)
struct bno055_t myBNO;
struct bno055_euler myEulerData; //Structure to hold the Euler data

unsigned long lastTime = 0;

void setup() //This code is executed once
{
  //Initialize I2C communication
  Wire.begin();

  //Initialization of the BNO055
  BNO_Init(&myBNO); //Assigning the structure to hold information about the device

  //Configuration to NDoF mode
  bno055_set_operation_mode(OPERATION_MODE_NDOF);

  delay(1);

  //Initialize the Serial Port to view information on the Serial Monitor
  Serial.begin(115200);
}

void loop() //This code is looped forever
{
  if ((millis() - lastTime) >= 100) //To stream at 10Hz without using additional timers
  {
    lastTime = millis();

    bno055_read_euler_hrp(&myEulerData);            //Update Euler data into the structure

    Serial.print("Time Stamp: ");               //To read out the Time Stamp
    Serial.println(lastTime);

    Serial.print("Heading(Yaw): ");             //To read out the Heading (Yaw)
    Serial.println(float(myEulerData.h) / 16.00);       //Convert to degrees

    Serial.print("Roll: ");                 //To read out the Roll
    Serial.println(float(myEulerData.r) / 16.00);       //Convert to degrees

    Serial.print("Pitch: ");                //To read out the Pitch
    Serial.println(float(myEulerData.p) / 16.00);       //Convert to degrees

    Serial.println();                   //Extra line to differentiate between packets
  }
}

```

# Answer
> 1 votes
I had the same problem with the Adafruit library. When a Chinese module is used the **id needs to be specified** in the constructor like this:

```
Adafruit_BNO055 bno = Adafruit_BNO055(55,0x29);

```

---
Tags: arduino-mega, arduino-ide, i2c, serial-data, bno055
---


title: Firmware backup and restore

text:
# Question
Title: Firmware backup and restore
I need to have the firmware stored somewhere on the board in order to get back to it after flashing a new firmware.

Is there a way to store a backup of the firmware somewhere, and use a button to erase a newer firmware and get back to the old one, without re-flashing the old firmware again ?

# Answer
Yes. You need to create a `factory` partition and upload your bin file to there.

You can read more about ESP32 partitions here

Note that none of the partition schemes in the ESP32 core have factory partitions, so you will need to create a custom one and link it to a menu entry (look at the boards.txt file to see how that is done).

The existing partition files are just `.csv` files within the ESP32 core. Copy one and modify it, then link that to a menu entry using the new file name.
> 2 votes

---
Tags: arduino-ide, esp32, reset, firmware, version-control
---


# Question
Title: Any possible way to stack Motor Driver shield L293D with Xbee Shield v03 on arduino?
So i am trying to stack these two shield on arduino, now the problem here is that i guess there is a conflict between the pins of arduino being used by both shields, so can anyone suggest a solution?

# Answer
Read the documentation for both boards. They should list the pins used. Their associated libraries will define variables to which you can assign non-conflicting pins. Review the sample code provided as well. Usually, the sample code included setting the pins to use, even if the code only sets them to their default.

There is another possibility. I don’t think this is the case, but I’ve run into this issue with different shields. If the shields use I2C, they may need to have jumpers shorted to set an address.
> 1 votes

---
Tags: shields, xbee, l293d
---


# Question
Title: ESP8266 Webserver not reachable after 2 minutes from reset
I have a Keyes Espressif ESP8266 NodeMCU, I have two LEDs that I want to control which are connected to the ESP. When I open the webpage `http://10.0.0.5/5` after uploading the sketch it works fine. If I don't open and close the website before ~ 02:30\[mm:ss\] the server becomes unreachable even if I close the existing connection and open a new connection in a new tab the same error yields: `ERR_CONNECTION_TIMED_OUT`

If I don't open a web page before ~ 02:30\[mm:ss\] I also receive error `ERR_CONNECTION_TIMED_OUT`

The web server is only made available when I hard reset the board then the same rules apply as above.

```
ESP.getFullVersion() outputs:
SDK:2.2.1(cfd48f3)/Core:2.5.1=20501000/lwIP:STABLE-2_1_2_RELEASE/glue:1.1-7-g82abda3/BearSSL:a143020

```

Question:

How can I make the web server accessible constantly?

With the help of @Juraj I tried changing to SDK V3 which made no difference I also tried:

* All lwip variants

My Code:

```
// Load Wi-Fi library
#include <ESP8266WiFi.h>

// Replace with your network credentials
const char* ssid     = "DO_231455";
const char* password = "0828842107";

// Set web server port number to 80
WiFiServer server(80);

// Variable to store the HTTP request
String header;

// Auxiliar variables to store the current output state
String output5State = "off";
String output4State = "off";

// Assign output variables to GPIO pins
const int output5 = 16;
const int output4 = 4;

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

  // Initialize the output variables as outputs
  pinMode(output5, OUTPUT);
  pinMode(output4, OUTPUT);
  // Set outputs to LOW
  digitalWrite(output5, LOW);
  digitalWrite(output4, LOW);

  Serial.print(ESP.getFullVersion());
  //WiFi.disconnect() ;
  //WiFi.persistent(false);
  //WiFi.setSleepMode(WIFI_NONE_SLEEP);
  // Connect to Wi-Fi network with SSID and password
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  // Print local IP address and start web server
  Serial.println("");
  Serial.println("WiFi connected.");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  server.begin();
}

void loop(){
  WiFiClient client = server.available();   // Listen for incoming clients
  if (client) {                             // If a new client connects,
    Serial.println("New Client.");          // print a message out in the serial port
    String currentLine = "";                // make a String to hold incoming data from the client
    while (client.connected()) {            // loop while the client's connected
      if (client.available()) {             // if there's bytes to read from the client,
        char c = client.read();             // read a byte, then
        Serial.write(c);                    // print it out the serial monitor
        header += c;
        if (c == '\n') {                    // if the byte is a newline character
          // if the current line is blank, you got two newline characters in a row.
          // that's the end of the client HTTP request, so send a response:
          if (currentLine.length() == 0) {
            // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
            // and a content-type so the client knows what's coming, then a blank line:
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println("Connection: close");
            client.println();

            // turns the GPIOs on and off
            if (header.indexOf("GET /5/on") >= 0) {
              Serial.println("GPIO 5 on");
              output5State = "on";
              digitalWrite(output5, HIGH);
            } else if (header.indexOf("GET /5/off") >= 0) {
              Serial.println("GPIO 5 off");
              output5State = "off";
              digitalWrite(output5, LOW);
            } else if (header.indexOf("GET /4/on") >= 0) {
              Serial.println("GPIO 4 on");
              output4State = "on";
              digitalWrite(output4, HIGH);
            } else if (header.indexOf("GET /4/off") >= 0) {
              Serial.println("GPIO 4 off");
              output4State = "off";
              digitalWrite(output4, LOW);
            }

            // Display the HTML web page
            client.println("<!DOCTYPE html><html>");
            client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
            client.println("<link rel=\"icon\" href=\"data:,\">");
            // CSS to style the on/off buttons
            // Feel free to change the background-color and font-size attributes to fit your preferences
            client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
            client.println(".button { background-color: #195B6A; border: none; color: white; padding: 16px 40px;");
            client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
            client.println(".button2 {background-color: #77878A;}</style></head>");

            // Web Page Heading
            client.println("<body><h1>ESP8266 Web Server</h1>");

            // Display current state, and ON/OFF buttons for GPIO 5
            client.println("<p>GPIO 5 - State " + output5State + "</p>");
            // If the output5State is off, it displays the ON button
            if (output5State=="off") {
              client.println("<p><a href=\"/5/on\"><button class=\"button\">ON</button></a></p>");
            } else {
              client.println("<p><a href=\"/5/off\"><button class=\"button button2\">OFF</button></a></p>");
            }

            // Display current state, and ON/OFF buttons for GPIO 4
            client.println("<p>GPIO 4 - State " + output4State + "</p>");
            // If the output4State is off, it displays the ON button
            if (output4State=="off") {
              client.println("<p><a href=\"/4/on\"><button class=\"button\">ON</button></a></p>");
            } else {
              client.println("<p><a href=\"/4/off\"><button class=\"button button2\">OFF</button></a></p>");
            }
            client.println("</body></html>");

            // The HTTP response ends with another blank line
            client.println();
            // Break out of the while loop
            break;
          } else { // if you got a newline, then clear currentLine
            currentLine = "";
          }
        } else if (c != '\r') {  // if you got anything else but a carriage return character,
          currentLine += c;      // add it to the end of the currentLine
        }
      }
    }
    // Clear the header variable
    header = "";
    // Close the connection
    client.stop();
    Serial.println("Client disconnected.");
    Serial.println("");
  }
}

```

Worth noting (while debugging):
The new client disconnects.

# Answer
**The short answer: Config a static IP!**

After looking at Git Issue #2371 I found out that I need to create a static IP address to fix this issue. I can do this by inserting `WiFi.config(ip, gateway, subnet)` just before `WiFi.mode(WIFI_STA)` in the code above.

* First I found the information `gateway` & `subnet` I needed by opening the command prompt on a computer that's connected to the access point(router) as the one connected to the ESP8266 which functions in station mode. I did this on Windows by searching `Command Prompt` then typing `ipconfig` to obtain the following information:

**Replace the points with commas!** See this references for more information regarding other parameters and DNS.

---

* To create an IP address you need to see your IP address in the red square in the picture above taken from the command prompt. The first three octects (numbers) of your router IP (probably `10.0.0.x`, `192.168.0.x`, or `192.168.1.x`) must match your chosen static IP. For my example the numbers to match would be `10.0.0`.
* Next, I needed to obtain the DCHP range for my router. My router is a Netgear Wireless ADSL2+ Modem Router DG834Gv5. To obtain the range I needed to access my router settings. To access this I looked for an HTTP link under the router. For my router it was `http://10.0.0.2` along with the username and password which was `admin`, `admin` respectively. This is what it looks like:

This will vary according to your router - Then I went into Advanced settings and saw the DHCP range. **This is an error on my part noted by @djsfantasi. Please see his answer regarding DHCP range selection.**The new static IP needs to be within the DHCP range According to one of the comments `brendanmatkin` made in Git Issue #2371 the last number of my static IP (which is `ZZ` in `WW.XX.YY.ZZ`) needs to be **outside** of this range. For me it didn't work, it worked when I used a value **inside** this range but `brendanmatkin` knows much more than me, I'm just a novice. There might be implications that I am not aware of so I think it's worth looking into. A DHCP range looks like this below:

My inserted code looks like this below:

```
void setup(void) {
  .
  .
  .
  Serial.begin(115200);
  //WiFi.disconnect();  //Prevent connecting to wifi based on previous configuration
  IPAddress ip(10,0,0,15); // this 3 lines for a fix IP-address
  IPAddress gateway(10,0,0,2);
  IPAddress subnet(255,255,255,0);
  //WiFi.hostname("ESP8266");      // DHCP Hostname (useful for finding device for static lease)
  WiFi.config(ip, gateway, subnet);
  //Station mode:
  WiFi.mode(WIFI_STA);
  .
  .
  .
}

```

Please comment for more info :)

**Additional information and changes I've made to IDE:**

OS : Windows 8.1

IDE : Arduino IDE V1.9.8

Board : Keyes ESP8266

Arduino IDE \> Tools \>Board (in boards manager) : Generic ESP8266 Board

Arduino IDE \> Tools \>lwip : V2 Low Memory

Arduino IDE \> Tools \>Esp FW:"nonos.." : nonos-sdk pr-3(known issues)\*

Power Supply : USB COM from 300Watt desktop power supply. ~ 1.5A current output.

Much appreciation to @Juraj. Juraj
> 1 votes

# Answer
It worked when the IP was in the range because there are no valid IP addresses outside the range.

WW.XX.YY.0 and WW.XX.YY.255 are reserved. The router is using the .1 and .2 addresses. That leaves 3-254 available, which as we see are the addresses within the DHCP range.

You can assign a static IP address within the DHCP range, but you run the risk of disabling 1 or 2 devices. DHCP doesn’t know you’ve used one of it's addresses, so can assign it to another device. Boom! Two devices with the same address and both will not function.

The correct way to resolve this is to log into the router and change the DHCP range. For example, increase the lower limit of 3 to (random pick) 20. Now, DHCP won’t be disturbed and will happily give out addresses to your devices. But if you need a static IP address, you’ve defined a pool, from WW.XX.YY.3 to WW.XX.YY.19
> 1 votes

---
Tags: esp8266, arduino-ide, wifi, web-server, tcpip
---


# Question
Title: Arduino OSX Mojave - Serial port only shows sometimes
I've found lots of issues about serial ports not showing up at all, but none about what I'm experiencing.

Sometimes I can see my Arduino Mega 2560 in the ports list, and sometimes I can't. I've tried unplugging, replugging, rebooting my PC, and installing various CH34X USB drivers

Is there some way I can troubleshoot this issue to work out where things are going wrong?

EDIT: I have a Macbook Pro 2017 with Thunderbolt 3.0 ports connected to an adapter that lets me plug in USB. The Mega is a CH340G -\> Wemos® Mega +WiFi R3 Module ATmega2560+ESP8266 32Mb Memory USB-TTL CH340G Compatible For Arduino Mega NodeMCU ESP8266.

EDIT #2: It looks like it's working again, all I did was switch around some of the DIP switches and change it from RX/TX0 to RX/TX3, sometimes when that stops working ill change it back to RX/TX0 and itll start working again. I suspect it has something to do with the USB-C adapter but haven't nailed it down yet.

# Answer
A colleague at work was struggling with a similar problem just two days ago.

He said he resolved it by reinstalling the USB driver. I did not pay much attention to more details (because I did not have that problem). If you can not work how to reinstall and none can advise how, I can ask him on Monday.

In the meantime here are a couple of reinstall the USB driver links:

https://www.roland.com/global/support/support\_news/18091014/

https://forum.arduino.cc/index.php?topic=570440.0

https://support.serato.com/hc/en-us/articles/115001883474-macOS-High-Sierra-10-13-macOS-Mojave-10-14-and-above-driver-install-process

Hopefully one of these will help you.

Here is the link that my colleague followed:

https://github.com/adrianmihalko/ch340g-ch34g-ch34x-mac-os-x-driver

All I can add is that this one worked for him. He has I have High Sierra (version 10.13.3) and needed to reboot after the installation.
> 0 votes

---
Tags: arduino-mega, osx
---


# Question
Title: Why Arduino Mega 2560 throw error when i try to upload example
I'm try to connect my Arduino Mega 2560 to PC, but I think it's not easy as I imagine. I spent a lot's of time to install USB driver. Here is a screenshot:

When I try to upload blink example, Arduino IDE throw this error:

```
Sketch uses 656 bytes (0%) of program storage space. Maximum is 253952 bytes.
Global variables use 9 bytes (0%) of dynamic memory, leaving 8183 bytes for local variables. Maximum is 8192 bytes.
avrdude: ser_open(): can't set com-state for "\\.\COM10"
avrdude: ser_drain(): read error: The handle is invalid."

```

Please help to run one simple example.

I think this screen may help to understand my problem:

# Answer
I install driver for this site and everything is working well. driver download: wch.cn/download/CH341SER\_EXE.html

I'm recommend to unplug arduino first and install driver, after that plug and enjoy.

Here is a video: https://www.youtube.com/watch?v=FhmG5J-AHrg
> 2 votes

# Answer
What you can try is:

* Use another USB port
* Reopen IDE
* Reinsert the USB cable
* Use a different USB cable
* Prevent using a USB 'box' in between
* Try a different 2560 (if you have)
* Restart computer
* Check if it can be found in the system drivers
* Reinstall IDE (after deinstall it).

However, as the author already mentioned the real solution is needed for some non-genuine Arduinos:

* Install the CH driver e.g. at wch.cn/download/CH341SER\_EXE.html
> 0 votes

# Answer
I also got the same error. Then I un-plugged my connections and pressed the reset button. Then I uploaded the default blink example to my board. Then it's working fine. Then again I made a connection to the board and it shows the same error again. Now, I un-plugged the GND pin; it's working again. So, in my case there was some thing wrong with my connections.
> 0 votes

---
Tags: usb, atmega2560
---


# Question
Title: Getting "spikes" from an array of values - measure rpm using accelerometter
For a project where I intend to use an arduino and an accelerometer to get rpm of an diesel / gasoline engine i intend to use following solution. I glued an mma8453 accelerometer to a neodium magnet which will be placed on a metallic part of the engine. Using an arduino I am reading values from accelerometter and calculate one final value which is sqrt (acc.x^2 + acc.y^2 + acc.z^2), and also get millis for each value. The values looks like this:

First column = millis, second acc value and third I identified maximums and millis since last maximum for them. Assuming that for an engine you have to max's per revolution I can calculate rpm of the engine.

My issue is that I have no idea how to write a function to do that.

Any help really appreciated

Thanks

```
269503  310
269504  303
269506  334
269507  326
269509  331
269510  330
269512  380
269513  377
269514  392
269516  400
269517  339
269519  393
269520  368
269521  353
269523  346
269524  316
269527  330
269528  281
269530  196
269531  195
269532  162
269534  119
269535  140
269537  132
269538  90
269539  99
269541  122
269542  168
269544  224
269545  219
269546  211
269548  268
269549  301
269551  334
269552  332
269554  316
269555  329
269556  379
269558  363
269559  381
269561  388
269562  403
269564  400
269565  420 49
269566  388
269569  360
269570  346
269572  259
269573  276
269574  284
269576  242
269577  207
269579  192
269580  145
269582  119
269583  113
269584  45
269586  125
269587  142
269589  123
269590  205
269591  243
269593  304
269594  308
269596  305
269597  298
269599  321
269600  340
269601  360
269603  380
269604  384
269606  370
269607  372
269608  413
269611  441 46
269612  395
269614  355
269615  332
269617  290
269618  317
269619  286
269621  227
269622  190
269624  172
269625  199
269627  146
269628  154
269629  177
269631  176
269632  156
269634  136
269635  174
269636  212
269638  260
269639  318
269641  291
269642  321
269644  304
269645  315
269646  343
269648  339
269649  360
269651  393
269652  390
269654  305
269656  405
269657  458 46
269659  358
269660  372
269662  339
269663  277
269664  298
269666  241
269667  203
269669  208
269670  185
269672  130
269673  165
269674  105
269676  87
269677  109
269679  128
269680  176
269681  229
269683  226
269684  271
269686  343
269687  307
269688  320
269690  318
269691  322
269693  322
269694  369
269697  363
269698  413
269699  399
269701  388
269702  426 45
269704  395
269705  380
269707  342
269708  311
269709  309
269711  315
269712  221
269714  227
269715  198
269716  113
269718  111
269719  88
269721  44
269722  69
269723  107
269725  158
269726  200
269728  232
269729  247
269731  313
269732  338
269733  348
269735  366
269736  339
269739  348
269740  377
269741  378
269743  385
269744  394
269746  403
269747  447
269749  454 47
269750  398
269751  380
269753  302
269754  245
269756  299
269757  310
269758  238
269760  206
269761  180
269763  108
269764  81
269766  83
269767  11
269768  119
269770  106
269771  169
269773  245
269774  270
269775  311
269777  338
269778  341
269780  332
269782  337
269783  337
269785  380
269786  387
269788  382
269789  373
269791  398
269792  414 43
269793  408
269795  387
269796  374
269798  285
269799  290
269801  326
269802  266
269803  211
269805  221
269806  191
269808  120
269809  175
269810  63
269812  147
269813  59
269815  120
269816  183
269817  196
269819  252
269820  301
269822  334
269824  325
269826  334
269827  310
269828  351
269830  354
269831  358
269833  373
269834  379
269835  332
269837  386
269838  404 46
269840  383
269841  385
269843  332
269844  266
269845  301
269847  282
269848  188
269850  199
269851  182
269852  128
269854  163
269855  119
269857  120
269858  140
269860  120
269861  129
269862  212
269864  230
269865  241
269868  290
269869  304
269871  340
269872  350
269873  327
269875  323
269876  351
269878  369
269879  387
269880  379
269882  380
269883  421 45
269885  373
269886  364
269888  360
269889  305
269890  302
269892  266
269893  249
269895  202
269896  229
269897  136
269899  122
269900  128
269902  49
269903  98
269904  107
269906  158
269907  211
269910  235
269911  225
269913  269
269914  314
269915  341
269917  335
269918  325
269920  348
269921  410
269923  375
269924  404
269925  419
269927  425
269928  442 45
269930  436
269931  400
269932  393
269934  326
269935  259
269937  307
269938  265
269940  220
269941  199
269942  183
269944  86
269945  83
269947  98
269948  23
269949  65
269952  124
269953  152
269955  221
269956  249
269957  287
269959  350
269960  331
269962  323
269963  341
269964  338
269966  389
269967  388
269969  380
269970  370
269972  358
269973  415 45
269974  403
269976  377
269977  381
269979  338
269980  328
269982  284
269983  246
269984  197
269986  178
269987  230
269989  162
269990  171
269991  141
269993  258
269995  138
269997  111
269998  163
270000  212
270001  192
270002  304
270004  287
270005  294
270007  349
270008  309
270009  334
270011  332
270012  364
270014  361
270015  408
270017  336
270018  421
270019  432 46
270021  361
270022  361
270024  342
270025  271
270027  288
270028  310
270029  235
270031  218
270032  166
270034  136
270035  146
270036  102
270039  78
270040  99
270042  122
270043  105
270044  181
270046  222
270047  293
270049  299
270050  299
270052  318
270053  349
270054  344
270056  349
270057  382
270059  381
270060  412
270062  380
270063  397
270064  425 45
270066  381
270067  367
270069  332
270070  272
270071  291
270073  296
270074  178
270076  177
270077  190
270080  123
270081  146
270082  107
270084  85
270085  108
270087  117
270088  148
270089  234
270091  223
270092  238
270094  283
270095  301
270097  332
270098  331

```

# Answer
A simple approach would be to filter the signal using a low-pass filter, and then just calculate the time between two zero crossings.

Here's an example that works on your data. It's written in Python for easy testing and plotting, but trans-coding it to C++ should be trivial.

I used an Exponential Moving Average low-pass filter to get rid of the noise. Depending on the frequencies involved, you can change the shift factor. The higher this factor, the lower the cut-off frequency, and the greater the phase shift.

I chose a fixed DC offset, but if necessary, you could use another (very slow) filter to get rid of it before applying the zero-cross detection.

If you want to, you could use both zero crossings. Use the average of the two last RPM measurements in that case, to compensate for asymmetric waveforms.

You could add another EMA to smooth out the RPM measurements.

```
class ZeroCrossRPMCounter:
    def __init__(self,
                 max_rpm: float):
        self.min_distance = int(round(60_000 / max_rpm))

        self.first_crossing = True
        self.time_of_last_crossing = 0
        self.rpm = float('nan')
        self.previous_value = 0

    def __call__(self, time_ms: int, value: int):
        new_crossing = self.previous_value >= 0 and value < 0
        if new_crossing:
            if self.first_crossing:
                self.time_of_last_crossing = time_ms
                self.first_crossing = False
            elif (time_ms - self.time_of_last_crossing) >= self.min_distance:
                self.rpm = 60_000 / (time_ms - self.time_of_last_crossing)
                self.time_of_last_crossing = time_ms
            else:
                new_crossing = False
        self.previous_value = value
        return new_crossing

class EMA_shift_round:
    def __init__(self, shiftfac: int, initial: int = 0):
        self.shiftfac = shiftfac
        self.fixedPointOneHalf = 1 << (shiftfac - 1)
        self.z = initial << shiftfac

    def __call__(self, x: int):
        self.z += x
        shifted = (self.z + self.fixedPointOneHalf) >> self.shiftfac
        self.z -= shifted
        return shifted

if __name__ == '__main__':
    import numpy as np
    from matplotlib import pyplot as plt

    # Load the data
    data = np.genfromtxt('rpm-ctr-data.csv', delimiter='\t', dtype=np.int)
    time, signal = data[:, 0], data[:, 1]
    t_start, t_end = time[0] * 1e-3, time[-1] * 1e-3

    # Find the DC offset
    offset = int(round(np.mean(signal)))
    print(offset)

    # Initialize the filter and RPM counter
    lp_filter = EMA_shift_round(3)
    counter = ZeroCrossRPMCounter(2000)

    # Iterate over the data, filter it, and count the RPM
    peaks = []
    rpms = []
    filtered = np.zeros(len(time))
    for n in range(len(time)):
        filtered[n] = lp_filter(signal[n] - offset)
        new_crossing = counter(time[n], filtered[n])
        if new_crossing:
            peaks.append(time[n] * 1e-3)
            rpms.append(counter.rpm)

    # Plot the results
    plt.figure(figsize=(10, 6))
    plt.subplot(3, 1, 1)
    plt.title('Original signal')
    plt.plot(time * 1e-3, signal)
    for peak in peaks:
        plt.axvline(peak, color='red')
    plt.xlim((t_start, t_end))
    plt.subplot(3, 1, 2)
    plt.title('Filtered signal')
    plt.plot(time * 1e-3, filtered)
    for peak in peaks:
        plt.axvline(peak, color='red')
    plt.axhline(0, color='black', linestyle=':')
    plt.xlim((t_start, t_end))
    plt.subplot(3, 1, 3)
    plt.title('RPM measurements')
    plt.plot(peaks, rpms, '-o')
    plt.axhline(np.mean(rpms[1:]), color='red', linestyle=':')
    plt.xlim((t_start, t_end))
    plt.xlabel("Time [s]")
    plt.tight_layout()
    plt.show()

```
> 2 votes

# Answer
I think most cars use a magnetic pickup next to the fly wheel to derive engine timing. The method picked here is likely to have several problems. For example, how to avoid picking up the shock of more than one cylinder compressing and exploding. Or, perhaps the motor developed on is out of balance. And a more nominal motor vibrates less making the project difficult to apply universally.

That said, using FFTs (Fast Fourier Transforms) is an alternative but fundamentally similar approach to detecting zero crossings for finding fundamental frequencies, and hence the engine's RPM.

This "FFT on an Arduino" article describes how to implement Fast Fourier Transforms on an Arduino. It uses the FFT libraries hosted here on github.
> 1 votes

# Answer
The approach suggested by tttapa is an excellent suggestion. But just to give you more options, you can consider using an hysteretic crossing detector instead of a filter. The hysteresis in a comparator consists of having one threshold value for detecting the high → low transition, and another, higher value, for the low → high transition. This tends to provide good immunity against noise, as noise spikes will not be able to trigger false transitions as long as they are smaller than the hysteresis (i.e. the difference between the thresholds).

Here is an example function that performs this detection. If you feed it all your data samples, it will always return `false`, except exactly *once* per signal period.

```
const int LOW_THRESHOLD = 220;
const int HIGH_THRESHOLD = 300;

/* Returns true when a high threshold crossing is detected. */
void crossing_detector(int x)
{
    static enum { BELOW, ABOVE } state;
    if (state == BELOW && x >= HIGH_THRESHOLD) {
        state = ABOVE;
        return true;
    }
    if (state == ABOVE && x < LOW_THRESHOLD) {
        state = BELOW;
    }
    return false;
}

```

Now, it is perfectly possible to combine tttapa's filter idea with this hysteretic crossing detector. The issue with the low pass filter is that it is tricky to find the right time constant. If you filter too aggressively, you may kill the signal at high RPMs. If you don't filter enough, you may end up keeping enough noise to trigger false zero crossings. If you use an hysteretic detector instead of a plain zero-crossing detector, then you will be able to use less aggressive filtering, as you will not be sensitive to the small residual noise.
> 1 votes

---
Tags: arduino-nano
---


# Question
Title: Is this the right way of using an RF communication?
I have a 433Mhz Superheterodyne receiver and a hand set remote of similar frequency, I'm using the RC-Switch library and I couldn't find a better way than using the "numbers" that I'm receiving like this:

```
#include <RCSwitch.h>

RCSwitch mySwitch = RCSwitch();

void setup() {
  Serial.begin(9600);
  mySwitch.enableReceive(0);  // Receiver on interrupt 0 => that is pin #2
  pinMode(13, OUTPUT);
}

void loop() {
  if (mySwitch.getReceivedValue() == 7264305) {
    digitalWrite(13, LOW);
  }
  if (mySwitch.getReceivedValue() == 7264308) {
    digitalWrite(13, HIGH);
  }
  if (mySwitch.getReceivedValue() == 7264306) {
    mySwitch.resetAvailable();
  }
}

```

Is there any other (better?) way than just using the "numbers" simply like that or everyone are using their remote commands like I'm using?

# Answer
> 1 votes
Credits for this answer are mainly for jsotola (see his remarks above). But I want to show an alternative to the `if` statements, and a way to get the last 4 bits:

1. In case you want to check for the least significant bits, use `((mySwitch.getReceivedValue() & 0xFFFFF0)`
2. TO check for the least significant four bits (the data you want to act upon), use `((mySwitch.getReceivedValue() & 0xF)`
3. Use a switch statement instead of the `if` statement; also in theory (I don't know the code of `mySwitch.getReceivedValue()` does not need to be executed multiple times.

So you get something like this:

```
void loop()
{
  unsigned long receivedValue = mySwitch.getReceivedValue(); // Call function only once

  if ((receivedValue & 0xFFFF0) == 0x6ED830)
  {
    // Process action
    switch (receivedValue & 0xF)
    {
    case 0x5:
      digitalWrite(13, LOW);
      break;

    case 0x8:
      digitalWrite(13, HIGH);
      break;

    case 0x6:
      mySwitch.resetAvailable();
      break;

    default: // All other values
      break; // Ignore
  }
}

```

---
Tags: rf, remote-control
---


# Question
Title: What is the best delay to use between characters sent to the serial port
I have an Arduino Uno. It's role is to echo back what it receives.
But if I send it a stream of ascii characters it starts to error after the first one. Occasionally it gets the second character correct but often not.

If I delay each character then it works ok. I couldn't see this limitation mentioned in the SoftwareSerial library: https://www.arduino.cc/en/Reference/SoftwareSerial

The Arduino is running the following code:

```
#define BT_RX_PIN 16 // A2
#define BT_TX_PIN 17 // A3
#include <SoftwareSerial.h>
SoftwareSerial OtherSerial(BT_RX_PIN, BT_TX_PIN);

void setup()
{
  Serial.begin(9600);  // not used
  OtherSerial.begin(9600);
}

void loop()
{
  if (OtherSerial.available()) {
    char value = OtherSerial.read();
    String stri = "Received: ";
    stri += value;
    OtherSerial.println(stri);
  }
}

```

The limitations do say "If using multiple software serial ports, only one can receive data at a time.". I don't have multiple software serial ports though I do have an instance of the "normal" serial port but I'm not sending any data to it... but perhaps even just initialising it is enough to disrupt seamless communication with the SoftwareSerial port?

Using the following test code for serial communication from a Raspberry Pi (using logic level conversion to go from 5V -\> 3.3V and visa versa):

```
import time

def write(msg, delay):
  for char in msg:
    with open("/dev/ttyAMA0", "w") as f:
      f.write(char)
      time.sleep(delay)

write("hello", 0.01)

```

I got the following results (repeated 10 times at each delay time and averaged):

```
Delay (ms)   |   Success rate
10           |   100 %
9            |   100 %
8            |     0 %
5            |     0 %
1            |     0 %

```

A delay of 9 ms between each character means the communication rate falls from ~ 960 characters per second (9600 baud / 10 bits per 7 bit character) to ~ 100 characters per second (1 / (1 / 960 characters per second + 9ms)). Is this right? Perhaps I'm doing something else wrong / set it up wrong in software / hardware?

# Answer
SoftwareSerial has a considerable overhead. It can often send at 115200 successfully but 9600 is about its limit for receiving, and you're trying both send and receive. In addition, for each character your code receives, it transmits considerably more than that 1 character (11 characters, by my count). It isn't too surprising that it would fall behind. You will need to either reduce the size of what you echo or reduce the rate at which you send characters to it (which is what you accomplished with your delay) so that the transmission (echo) rate can keep up.

Update:

The OP reports success with continuous reception by, and transmission from, the Arduino at 57600 baud (but not at the same time). The transmission rate would be consistent with my experience transmitting at 115200 baud (blindly and for short bursts, to reconfigure ESP8266-01s that were shipped with a preset 115200 rate.
> 5 votes

# Answer
Simply put, a serial port implemented in software requires the program to sample the input pin fast enough to detect every transition. To satisfy the Nyquist frequency rate we need the program to sample the data twice as fast as we expect the data to change.

A serial port implemented in hardware might only need to be sampled at 1/16 this rate assuming the data size is 8 bits.

Your program implements a serial port in software which is admirably keeping up with the received data. However, when you tell the program to send the message "Received" plus the string that was received, the program stops looking at the serial input pin long enough for data to go missing.

By far the easiest solution would be to use a hardware implemented serial port. If this is not possible consider approaching the problem using interrupts. However, while a powerful programming tool, interrupts can be difficult to implement and hard to debug.
> 5 votes

---
Tags: serial, softwareserial
---


# Question
Title: Are my stepper motors being burnt out? What is the issue here?
I am building a mini-cnc laser engraver as shown in this intructable and this youtube video.

I have built the circuit (minus the jst connector and two male pins at the top left of the board) and have attached a stepper motor from a dvd drive. It worked like a charm, but made a loud ringing noise (like tinnitus.) I proceeded to test it with laser GRBL, and it moved great, but gradually started missing steps, at first only in one direction and eventually in both. After a couple hours of being connected, it wouldn't budge at all. I switched the motor for another motor, and tested it again. This time the motor was much shorter-lived. It made 5 steps perfectly and then just shut off. You could hear the motor try to turn, but it was like it didn't have any torque at all. What could be the issue? (I also tried it on the other axis with the other motor driver, no change.)

It's also worth noting that at one point both the positive and negative (ground) cables from my power supply made contact with metal at once, throwing a spark. However, the steps were already beginning to be lost **before** that happened.

As per your request, I have attached the circuit layout I am attempting (it's identical to the one in the tutorial) as well as a picture of my physical circuit board. (sorry, a link was my only option as the pics were to big for upload) I know the soldering is pretty bad- I have a giant soldering iron. I don't see any shorts though.

# Answer
> 1 votes
So the problem was that somehow the potentiometer had reset its own vref output. I couldn't adjust it after it did this. I replaced both drivers and it works like a charm now.

---
Tags: arduino-nano, power, motor, stepper-motor, a4988
---


title: Parsing Arduino Receiving Strings

text:
# Question
Title: Parsing Arduino Receiving Strings
I'm currently using google geolocation to get location data to one nodemcu and sending it through serial to another Arduino. The serial command I'm getting right now is,

```
1.450187T103.824745

```

I'm using the following code to parse it.

```
 if (Serial.available())  {
    char c = Serial.read();  //gets one byte from serial buffer
    //if (c == '\n') {  //looks for end of data packet marker
    if (c == '\n') {
     // Serial.println(readString); //prints string to serial port out
      //do stuff
      substring = readString.substring(0,8);
      lati = substring;
      loc = readString.indexOf("T");
      substring = readString.substring(loc+1, loc+11);
     longi = substring;
       readString=""; //clears variable for new input
      substring="";

    }
    else {
      readString += c; //makes the string readString
    }
  }

```

It works most of the time but sometimes I get 'T' inside the string as well. like this

```
lat=1.450146&longi=102464T103

```

What's wrong in my code?

# Answer
> 1 votes
with readBytesUntil and C string

```
if (Serial.available()) {
  char buff[32];
  int l = Serial.readBytesUntil('\n', buff, sizeof(buff));
  if (l > 0 && buff[l - 1] == '\r') {
    l--; // to remove \r if it is there
  }
  buff[l] = 0; // terminate the string
  char* p = strchr(buff,'T'); // returns pointer in string
  if (p != NULL) {
    *p = 0; // write 0 as char at pointer to terminate the first part
    p++; // move the pointer to next char
    Serial.println(buff);
    Serial.println(p);
  } else {
    Serial.println(buff);
  }
}

```

---
Tags: serial, communication, string, data
---


# Question
Title: Sim800L Uploading issues, HTTPACTION returns 0, 302, 701
I'm using the Sim800L module and the NEO6M GPS Module in combination with an Arduino nano to create a simple tracking device. I get the data from the GPS and try to upload it to my site with some simple PHP scripts. I'm using this code down here:

```
//the function - which is responsible for sending data to the web server
void sendLocation(String lat, String lon){
 Sim800l.listen();
 //The line below sets the URL we want to connect to
 Sim800l.println("AT+HTTPPARA=\"URL\", \"http://" + ipAddress +  "/log_info.php?dev_id=13&lat=" + lat + "&lon=" + lon + "\"");
 waitUntilResponse("OK");
 //GO
 Sim800l.println("AT+HTTPACTION=0");
 waitUntilResponse("200");
 Serial.println("Location sent");
 gpsPort.listen();
}

```

Unfortunately, when I try to use this code, in my serial monitor I get this message:

```
AT+HTTPACTION=0
OK
+HTTPACTION: 0,302,171
error

```

I Looked it up in the datasheet for the Sim800L, and the number 302 means "Found". I'm expecting the number 200 for "OK". I have no idea what I did wrong, the data is not being send to the web server for some reason. I hope you can help. Thanks in advance!

EDIT: The datasheet with all the errors for the Sim800L https://www.elecrow.com/wiki/images/2/20/SIM800\_Series\_AT\_Command\_Manual\_V1.09.pdf

# Answer
> 1 votes
302 is HTTP code returned by the server. It is used for redirection. Print the response with AT+HTTPREAD to see where does it redirectd.

---
Tags: arduino-nano, gps, web-server, error
---


# Question
Title: Waveshare 1.54 inch ePaper display requires 5Vs from Arduino Uno
I have an Arduino Uno and I would like to attach a Waveshare 1.54“ display (red, black & white) to it.

All the specs tell me that it consumes 3.3 V which I have readily available on the Arduino Uno.

I could not get the display to work until I attached the Power pin to 5V instead of 3.3V.

I did try this with two different ePaper displays and the situation was the same.

I also tried to power the display with a Raspberry Pi‘s 3.3V (with the GNDs connected). But this did not work either.

So I am wondering what I am missing here, is it simply a power issue and my Arduino can‘t deliver the necessary current?

# Answer
The answer lies in the FAQ for that display:

> Why the e-Paper cant work with Arduino?
>
> Answer:
>
> The I/O level of Arduino is 5V, and the e-Paper should be driven with 3V3. If your Arduino cant drive the e-Paper successfully, please try to convert the level to 3.3V
>
> You can also try to connect the Vcc pin to the 5V of Arduino to see whether the e-Paper works, but we recommend you not to use 5V for a long time.

So while you *can* run it from 5V, you really shouldn't, since you run the risk of breaking it.

Instead, you should employ proper logic level shifting to reduce the Arduino's outgoing signals to 3.3V and, more importantly, boost the incoming signals from the display to 5V.
> 1 votes

# Answer
Update to those who have bought the display module recently (doesn't apply to bare displays). There has been a change and the new modules support 5V. From the display's user manual:

> 9. For raw panel, its working voltage is 3.3V, note that when you designed you own driver board, level convert circuit is required if the working voltage of your board is 5V. Module/HAT version can support 5V voltage if the Module you buy is the new version which has been integrated convert circuit.
> 1 votes

---
Tags: arduino-uno, voltage-level, display
---


# Question
Title: Can I use the PWM pins as regular digital input/output pins?
In regards to the arduino which has pwm pins, can I use these pins as normal input/output digital pins or not? Thanks in advance.

# Answer
> 6 votes
Yes you can use them as ordinary digital io pins. PWM is essentially a normal digital output pin that is repeatedly turned on and off at a high rate.

The magic is that the turning off and on is done in the hardware according to the duty cycle (I.e. there is no need for software to perform the on/off operations) . This is why only some pins can do h/w PWM, because the PWM hardware is not added on to all pins.

If you are not using the pin for PWM, it is available for you to use as required.

---
Tags: arduino-uno, pins, pwm, input
---


title: 0 temperature & hummidity DH11

text:
# Question
Title: 0 temperature & hummidity DH11
Alright so I'm having problems with my code. Its my first time using DH11

I keep on getting that temperature is 0 degrees so as the humidity

```
#include "dht.h"
#define dht_apin A0

dht DHT;

void setup(){

  Serial.begin(9600);
  delay(500);
  Serial.println("DHT11 Humidity & temperature Sensor\n\n");
  delay(1000);

}

void loop()
{

    DHT.read11(dht_apin);

    Serial.print("Current humidity = ");
    Serial.print(DHT.humidity);
    Serial.print("%  ");
    Serial.print("temperature = ");
    Serial.print(DHT.temperature);
    Serial.println("C  ");

    delay(5000)

}

```

What Im getting is basically

> Current humidity = 0.00% temperature = 0.00C

# Answer
> 0 votes
I have run into problems when using some `DHT` library versions. May I suggest that you try using a different version of `dht.h`?

This version works for me (there is a newer version I have NOT tested):

dht.h (606B 6/12/2012)

```
//
//    FILE: dht.h
// VERSION: 0.1.00
// PURPOSE: DHT Temperature & Humidity Sensor library for Arduino
//
//     URL: http://arduino.cc/playground/Main/DHTLib
//
// HISTORY:
// see dht.cpp file
//

#ifndef dht_h
#define dht_h

#if ARDUINO >= 100
 #include "Arduino.h"
#else
 #include "WProgram.h"
#endif

#define DHT_LIB_VERSION "0.1.00"

class dht
{
public:
    int read11(uint8_t pin);
    int read22(uint8_t pin);
    double humidity;
    double temperature;

private:
    uint8_t bits[5];  // buffer to receive data
    int read(uint8_t pin);
};
#endif
//
// END OF FILE
//

```

---
Tags: arduino-uno
---


title: esp32 cam and PIR sensor

text:
# Question
Title: esp32 cam and PIR sensor
I have tried all the GPIO pins listed here:I am following this tutorial to save a picture using the ESP32 cam board. I am trying to add a PIR sensor. https://randomnerdtutorials.com/esp32-cam-take-photo-save-microsd-card/

whenever I try to use any pins to enable wake on external pin high, there is an error either because of interruption with the camera initiation or sd card.

here is my PIR sensor https://www.robotshop.com/en/wide-angle-pir-motion-sensor.html?gclid=EAIaIQobChMI0Y7QuaOA4wIVl\_5kCh3zYA4OEAQYASABEgJFPvD\_BwE here is the code I am using

```
    /*********
      Rui Santos
      Complete project details at https://RandomNerdTutorials.com/esp32-cam-    take-photo-save-microsd-card

      IMPORTANT!!!
       - Select Board "ESP32 Wrover Module"
      - Select the Partion Scheme "Huge APP (3MB No OTA)
    - GPIO 0 must be connected to GND to upload a sketch
    - After connecting GPIO 0 to GND, press the ESP32-CAM on-board RESET  button to put your board in flashing mode

   Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files.
  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.
*********/

 #include "esp_camera.h"
 #include "esp_timer.h"
 #include "img_converters.h"
 #include "Arduino.h"
 #include "fb_gfx.h"
 #include "fd_forward.h"
 #include "fr_forward.h"
 #include "FS.h"                // SD Card ESP32
 #include "SD_MMC.h"            // SD Card ESP32
 #include "soc/soc.h"           // Disable brownour problems
 #include "soc/rtc_cntl_reg.h"  // Disable brownour problems
 #include "dl_lib.h"
 #include "driver/rtc_io.h"
 #include <EEPROM.h>            // read and write from flash memory

    // define the number of bytes you want to access
     #define EEPROM_SIZE 1

     // Pin definition for CAMERA_MODEL_AI_THINKER
     #define PWDN_GPIO_NUM     32
     #define RESET_GPIO_NUM    -1
     #define XCLK_GPIO_NUM      0
     #define SIOD_GPIO_NUM     26
     #define SIOC_GPIO_NUM     27

     #define Y9_GPIO_NUM       35
     #define Y8_GPIO_NUM       34
     #define Y7_GPIO_NUM       39
     #define Y6_GPIO_NUM       36
     #define Y5_GPIO_NUM       21
     #define Y4_GPIO_NUM       19
     #define Y3_GPIO_NUM       18
     #define Y2_GPIO_NUM        5
     #define VSYNC_GPIO_NUM    25
     #define HREF_GPIO_NUM     23
     #define PCLK_GPIO_NUM     22

     int pictureNumber = 0;

     void setup() {
       WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); //disable brownout detector

       Serial.begin(115200);
       //Serial.setDebugOutput(true);
       //Serial.println();

       camera_config_t config;
       config.ledc_channel = LEDC_CHANNEL_0;
       config.ledc_timer = LEDC_TIMER_0;
       config.pin_d0 = Y2_GPIO_NUM;
       config.pin_d1 = Y3_GPIO_NUM;
       config.pin_d2 = Y4_GPIO_NUM;
       config.pin_d3 = Y5_GPIO_NUM;
       config.pin_d4 = Y6_GPIO_NUM;
       config.pin_d5 = Y7_GPIO_NUM;
       config.pin_d6 = Y8_GPIO_NUM;
       config.pin_d7 = Y9_GPIO_NUM;
       config.pin_xclk = XCLK_GPIO_NUM;
       config.pin_pclk = PCLK_GPIO_NUM;
       config.pin_vsync = VSYNC_GPIO_NUM;
       config.pin_href = HREF_GPIO_NUM;
       config.pin_sscb_sda = SIOD_GPIO_NUM;
       config.pin_sscb_scl = SIOC_GPIO_NUM;
       config.pin_pwdn = PWDN_GPIO_NUM;
       config.pin_reset = RESET_GPIO_NUM;
       config.xclk_freq_hz = 20000000;
       config.pixel_format = PIXFORMAT_JPEG;

       if(psramFound()){
         config.frame_size = FRAMESIZE_UXGA; // FRAMESIZE_ +  QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA
        config.jpeg_quality = 10;
        config.fb_count = 2;
      } else {
        config.frame_size = FRAMESIZE_SVGA;
        config.jpeg_quality = 12;
        config.fb_count = 1;
      }

      // Init Camera
      esp_err_t err = esp_camera_init(&config);
      if (err != ESP_OK) {
        Serial.printf("Camera init failed with error 0x%x", err);
        return;
      }

      //Serial.println("Starting SD Card");
      if(!SD_MMC.begin()){
        Serial.println("SD Card Mount Failed");
        return;
      }

      uint8_t cardType = SD_MMC.cardType();
      if(cardType == CARD_NONE){
        Serial.println("No SD Card attached");
        return;
      }

      camera_fb_t * fb = NULL;

      // Take Picture with Camera
      fb = esp_camera_fb_get();
      if(!fb) {
        Serial.println("Camera capture failed");
        return;
      }
      // initialize EEPROM with predefined size
      EEPROM.begin(EEPROM_SIZE);
      pictureNumber = EEPROM.read(0) + 1;

      // Path where new picture will be saved in SD Card
      String path = "/picture" + String(pictureNumber) +".jpg";

      fs::FS &fs = SD_MMC;
      Serial.printf("Picture file name: %s\n", path.c_str());

      File file = fs.open(path.c_str(), FILE_WRITE);
      if(!file){
        Serial.println("Failed to open file in writing mode");
      }
      else {
        file.write(fb->buf, fb->len); // payload (image), payload length
        Serial.printf("Saved file to path: %s\n", path.c_str());
        EEPROM.write(0, pictureNumber);
        EEPROM.commit();
      }
      file.close();

      // Turns off the ESP32-CAM white on-board LED (flash) connected to GPIO 4
      pinMode(4, OUTPUT);
      digitalWrite(4, LOW);
      rtc_gpio_hold_en(GPIO_NUM_4);

      delay(2000);
      Serial.println("Going to sleep now");
      delay(2000);
      esp_deep_sleep_start();
      Serial.println("This will never be printed");
    }

    void loop() {

    }

```

This is the thing I am trying to add. but no matter which pins i chose there are errors. I can add the error if that would be helpful.

```
esp_sleep_enable_ext0_wakeup(GPIO_NUM_X, level)

```

# Answer
> 1 votes
Software:

It may be that one of the included libraries (software) you are using depends on pin 3 (E32\_RST) of the ESP32 going low in order to operate as expected (wake up and take a picture). Using an alternate pin may wake up the ESP32 but may not behave as expected.

Hardware:

This schematic of the ESP32 Camera shows how switch K1 is connected to pin 3 of the ESP32. There is a capacitor C7 and resistor R6 likely used to mitigate K1 switch bouncing and to pull pin 3 high when switch K1 is not pressed. When switch K1 is pushed it pulls pin 3 to ground waking up the ESP32 to take a picture.

The PIR specified changes its output to high when activated according to its data sheet. This is opposite of what the ESP32 needs to see at pin 3 in order to take a picture. It appears an inverter is needed between the PIR and pin 3 of the ESP32. An open collector type of inverter would be best as this type of driving circuit can be attached where K1, C7 & R6 come together with out interfering with the their (the existing components') operation. This is the subject of this stackexchange question / answer.

---
Tags: sd-card, esp32, camera
---


# Question
Title: Can't add board for RFDuino in Arduino IDE
I tried to upload sketch to my RFDuino. I can select the RFDuino port. But I can't upload cos I can't select the RFDuino board.

I followed the installation steps listed here but I don't see RFduino package in Board Manager after I finished the steps above.

I am using Mac Mojave and Arduino IDE v1.8.9. I have tried it with v1.6.6 but results the same.

# Answer
> 1 votes
Turns out that rfduino.com's domain is gone, so the link will always return with an error downloading. After reading this thread arduino.cc, @pert posted a link for the .json file that used to be at the website you have. I used this link on MacOS Mojave and Arduino v1.8.9 and it worked perfectly!

---
Tags: arduino-ide
---


# Question
Title: LCDs interfere with Adafruit datalogger SD card function
I am using the Adafruit datalogger shield (Rev B) and a pair of cheap 20x4 LCD I2C displays. The displays have a small I2C I/O expansion module board on the back. The LCDs I am using are these;

https://www.amazon.ca/gp/product/B01GPUMP9C/ref=oh\_aui\_detailpage\_o09\_s00?ie=UTF8&psc=1

I'm using the NewLiquidCrystal 1.3.4 I2C library. My UNO clone is the iteaduino-BT https://www.itead.cc/iteaduino-bt.html, which is a board I really like.

I am getting interference between the LCD displays and the SD card function. Sometimes I can write to the SD card, and sometimes I can't. I have tried several SD cards. After a lot of experimenting, I think I have identified the problem. The LCDs are interfering somehow with the SD card functions. The LCD objects are created with the following statements; // set the lcd1 address to 0x26 // Set the pins on the I2C chip used for lcd1 connections: // addr, en,rw,rs,d4,d5,d6,d7,bl,blpol LiquidCrystal\_I2C lcd1(0x26, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

```
// set the lcd2 address to 0x27
LiquidCrystal_I2C lcd2(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

```

If I comment out the LCD lines, the SD problem goes away. My thinking is that the four data lines used by the LCDs (4,5,6,7) may be overlapping with the datalogger card, but after looking at the datalogger schematic, I can't see the problem. I found a couple of websites suggesting mapping the LCDs to use different data lines, but I'm not sure if that is the problem.

I also ran a program to scan the I2C bus and it showed that the LCDs were at 26 and 27 and the Adafruit datalogger at 68. No interference with addresses at least.

I really need this working yesterday. Creating datalogging projects is nothing new and I can't believe that there is no solution for including I2C LCD displays. Should I experiment with different LCD libraries or try mapping the pins differently during the creation of the LCD objects? I also am wondering if I can simply shut off the LCDs when writing to the SD card and then turn them back on after. I plan on taking measurements and writing the results every 5 minutes for several days, so high speed anything is not a requirement.

The code sample below is part of my program. I use the while(1) line as a hard break for debugging purposes.

```
#include <OneWire.h>              // library for DS18B20 thermocouple
#include <DallasTemperature.h>    // library for DS18B20 thermocouple
#include <Wire.h>                 // used for rtc
#include <SD.h>                   // library for SD card
#include <SPI.h>                  // library used for SD card
#include <RTClib.h>               // library for real time clock
#include <LiquidCrystal_I2C.h>    // library for lcd displays
#define ONE_WIRE_BUS 8            // Data wire for thermocouple is plugged into pin 8 on the Arduino
#define SYNC_INTERVAL 1000        // mills between calls to flush() - to write data to the card

RTC_PCF8523 rtc;                  // define the Real Time Clock object

String datetimestamp;
uint8_t MM;
uint8_t DD;
uint8_t mm;
uint8_t hh;
File logfile;                     // create file object to save results on SD card
const int chipSelect = 10;        // for the data logging shield, we use digital pin 10 for the SD cs line
OneWire oneWire(ONE_WIRE_BUS);        // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
DallasTemperature sensors(&oneWire);  // Pass our oneWire reference to Dallas Temperature.

// set the lcd1 address to 0x26
// Set the pins on the I2C chip used for lcd1 connections:
//                    addr, en,rw,rs,d4,d5,d6,d7,bl,blpol
LiquidCrystal_I2C lcd1(0x26, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

// set the lcd2 address to 0x27
LiquidCrystal_I2C lcd2(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

String inputString = "";         // a string to hold incoming data
String ackString = "ack";        // acknowledgement string from terminal
String temperature;              // temperature
boolean stringComplete = false;  // whether the incoming string from serial port is complete with /n
int interval = 60000;            // interval between measurements
long previousMillis;
int cycle = 1;                   // cycle number
int heartbeat = 30000;           // ping teminal to prevent bluetooth from shutting down
String dim_length;
String dim_width;
String dim_height;
String measurements;              // string containing measurements for inclusion in SD file
int firstcomma;
int secondcomma;
int thirdcomma;
String logEntry;
char filename[] = "logdata.txt";

void setup(void) {
  Serial.begin(9600);
  inputString.reserve(20);               // reserve space for the inputString
  pinMode(10, OUTPUT);
  pinMode(ONE_WIRE_BUS, INPUT);          // used for thermocouple

  WaitFor(2000);

  lcd1.begin(20, 4);        // initialize the first lcd for 20 chars 4 lines
  lcd1.backlight();         // turn on backlight
  lcd1.clear();             // clear lcd11

  lcd2.begin(20, 4);        // initialize the second lcd for 20 chars 4 lines
  lcd2.backlight();         // turn on backlight
  lcd2.clear();             // clear lcd11

  //These routines update rows on the LCDs
  Row1("DATE: ");
  Row2("TEST CYCLE: ");
  Row3(" ");
  Row4(" ");

  // check for working real time clock
  if (! rtc.begin()) {
    Row4("RTC failed");
    WaitFor(500);
    while (1);
  }
  else {
    Row4("RTC found");
    WaitFor(500);
  }

  if (! rtc.initialized()) {
    Row4("RTC failed");
    WaitFor(500);
    while (1);
  } else {
    Row4("RTC initialized");
    WaitFor(500);
  }

  UpdateRow1(GetTimestamp());      // display current date and time
  UpdateRow2(cycle);               // display current test cycle

  // initialize SD card
  if (!SD.begin(10)) {
    Row4("SD init failed");
    WaitFor(500);
    while (1);
  } else {
    Row4("SD card initialized");
    WaitFor(500);
  }

  //log file setup
  if (SD.exists(filename)) {
    Row4("log file exists");
    WaitFor(500);
  } else {
    Row4("log doesn't exist");
    WaitFor(500);
  }

  // sample write to SD card
  Row4("opening log file");
  logfile = SD.open(filename, FILE_WRITE);
  Row4("writing log file");
  WaitFor(500);
  logfile.println("DateTime,Temperature");
  WaitFor(500);
  for (int x = 1; x < 6; x++) {
    logfile.print("Test # ");
    logfile.println(x);
    delay(1000);
  }
  logfile.flush();
  WaitFor(500);
  Row4("flushed log file");
  WaitFor(1000);

  while (1);  //temporary stop for debugging

```

# Answer
I think your problem is with the way you create the LCD instants.

I've always used `LiquidCrystal_I2C lcd(0x27, 20, 4);` `LiquidCrystal_I2C lcd(address, row, col);` when I'm using the I2C modules.
> 1 votes

---
Tags: lcd, sd-card, adafruit
---


title: Code compatibility with Arduino Due

text:
# Question
Title: Code compatibility with Arduino Due
I am currently working on a quadcopter project that involves an MPU6050 accelerometer+gyroscope module, an ultrasonic sensor and control of electronic speed controllers. I have used existing examples and modified them to get raw values of acceleration, yaw pitch and roll angles, and the distance from the ultrasonic. Here is the *long code*.

```
#include "I2Cdev.h"

#include "MPU6050_6Axis_MotionApps20.h"
//#include "MPU6050.h" // not necessary if using MotionApps include file

#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
#include "Wire.h"
#endif

MPU6050 mpu;
//MPU6050 mpu(0x69); // <-- use for AD0 high

const int trigPin = 9;
const int echoPin = 10;

#define INTERRUPT_PIN 2  // use pin 2 on Arduino Uno & most boards
#define LED_PIN 13 // (Arduino is 13, Teensy is 11, Teensy++ is 6)
bool blinkState = false;

// MPU control/status vars
bool dmpReady = false;  // set true if DMP init was successful
uint8_t mpuIntStatus;   // holds actual interrupt status byte from MPU
uint8_t devStatus;
uint16_t packetSize;    // expected DMP packet size (default is 42 bytes)
uint16_t fifoCount;     // count of all bytes currently in FIFO
uint8_t fifoBuffer[64]; // FIFO storage buffer

// orientation/motion vars
Quaternion q;           // [w, x, y, z]         quaternion container
VectorInt16 aa;         // [x, y, z]            accel sensor measurements
VectorInt16 aaReal;     // [x, y, z]gravity-free accel sensor measurements
VectorInt16 aaWorld;    // [x, y, z] world-frame accel sensor measurements
VectorFloat gravity;    // [x, y, z]            gravity vector
float euler[3];         // [psi, theta, phi]    Euler angle container
float ypr[3], yprd[3] = {0, 0, 0};

// packet structure for InvenSense teapot demo
uint8_t teapotPacket[14] = {'$', 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0x00, 0x00, '\r', '\n' };

// ================================================================
// ===               INTERRUPT DETECTION ROUTINE                ===
// ================================================================
volatile bool mpuInterrupt = false;
void dmpDataReady() {
  mpuInterrupt = true;
}

// ================================================================
// ===                      INITIAL SETUP                       ===
// ================================================================
int16_t yo = 0, po = 0, ro = 0;
int lv = 1, flag = 0;
const int MPU_addr = 0x68; // I2C address of the MPU-6050
int16_t AcX, AcY, AcZ, Tmp, GyX, GyY, GyZ;
int32_t AcXo = 0, AcYo = 0, AcZo = 0, prev, curr;
int32_t AcXd = 0, AcYd = 0, AcZd = 0;
int i = 1, flaggl = 0;
int  glc = 0, lv2 = 1;
long duration;
int distance, distanced;
void setup() {

#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
  Wire.begin();
  Wire.setClock(400000);
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
  Fastwire::setup(400, true);
#endif
  Serial.begin(115200);
  // initialize device
  Serial.println(F("Initializing I2C devices..."));
  mpu.initialize();
  pinMode(INTERRUPT_PIN, INPUT);
  // verify connection
  Serial.println(F("Testing device connections..."));
  Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));
  // wait for ready
  Serial.println(F("\nSend any character to begin DMP programming and demo:
                   "));
  while (Serial.available() && Serial.read()); // empty buffer
  while (!Serial.available());                 // wait for data
  while (Serial.available() && Serial.read()); // empty buffer again
  // load and configure the DMP
  Serial.println(F("Initializing DMP..."));
  devStatus = mpu.dmpInitialize();
  // supply your own gyro offsets here, scaled for min sensitivity
  mpu.setXGyroOffset(220);
  mpu.setYGyroOffset(76);
  mpu.setZGyroOffset(-85);
  mpu.setZAccelOffset(1788); // 1688 factory default for my test chip
  // make sure it worked (returns 0 if so)
  if (devStatus == 0) {
    // turn on the DMP, now that it's ready
    Serial.println(F("Enabling DMP..."));
    mpu.setDMPEnabled(true);

    // enable Arduino interrupt detection
    Serial.println(F("Enabling interrupt detection (Arduino external
                     interrupt 0)..."));
    attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), dmpDataReady, RISING);
    mpuIntStatus = mpu.getIntStatus();

    // set our DMP Ready flag so the main loop() function knows it's okay to use it
    Serial.println(F("DMP ready! Waiting for first interrupt..."));
    dmpReady = true;

    // get expected DMP packet size for later comparison
    packetSize = mpu.dmpGetFIFOPacketSize();
  } else {
    // ERROR!
    // 1 = initial memory load failed
    // 2 = DMP configuration updates failed
    // (if it's going to break, usually the code will be 1)
    Serial.print(F("DMP Initialization failed (code "));
    Serial.print(devStatus);
    Serial.println(F(")"));
  }

  // configure LED for output
  pinMode(LED_PIN, OUTPUT);
  glc = 0;
  distance = distanced = 0;
}

// ================================================================
// ===                    MAIN PROGRAM LOOP                     ===
// ================================================================
void loop() {
  // if programming failed, don't try to do anything
  if (!dmpReady) return;

  // wait for MPU interrupt or extra packet(s) available
  while (!mpuInterrupt && fifoCount < packetSize) {
  }
  mpuInterrupt = false;
  mpuIntStatus = mpu.getIntStatus();
  // get current FIFO count
  fifoCount = mpu.getFIFOCount();
  // check for overflow (this should never happen unless our code is too inefficient)
  if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
    // reset so we can continue cleanly
    mpu.resetFIFO();
    Serial.println(F("FIFO overflow!"));
    // otherwise, check for DMP data ready interrupt (this should happen frequently)
  } else if (mpuIntStatus & 0x02) {
    // wait for correct available data length, should be a VERY short wait
    while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();
    // read a packet from FIFO
    mpu.getFIFOBytes(fifoBuffer, packetSize);
    // track FIFO count here in case there is > 1 packet available
    // (this lets us immediately read more without waiting for an interrupt)
    fifoCount -= packetSize;
    //#ifdef OUTPUT_READABLE_YAWPITCHROLL
    // display Euler angles in degrees
    mpu.dmpGetQuaternion(&q, fifoBuffer);
    mpu.dmpGetGravity(&gravity, &q);
    mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
    if (millis() > 30000 && flag == 0) {
      if ( flag == 0 && lv  < 21) {
        yo += ypr[0] * 180 / M_PI;
        po += ypr[1] * 180 / M_PI;
        ro += ypr[2] * 180 / M_PI;
        ++lv;
      } else if (flag == 0) {
        flag = 1;
        yo /= 20;
        po /= 20;
        ro /= 20;
      }
    }
    //#endif
    // blink LED to indicate activity
    blinkState = !blinkState;
    digitalWrite(LED_PIN, blinkState);
    Wire.beginTransmission(MPU_addr);
    Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
    Wire.endTransmission(false);
    Wire.requestFrom(MPU_addr, 14, true); // request a total of 14 registers
    AcX = Wire.read() << 8 | Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C     (ACCEL_XOUT_L)
    AcY = Wire.read() << 8 | Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
    AcZ = Wire.read() << 8 | Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
    Tmp = Wire.read() << 8 | Wire.read(); // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L)
    GyX = Wire.read() << 8 | Wire.read(); // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
    GyY = Wire.read() << 8 | Wire.read(); // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
    GyZ = Wire.read() << 8 | Wire.read(); // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)
    mpu.resetFIFO();
    if (i < 21 && !flaggl) {
      AcXo += AcX;
      AcYo += AcY;
      AcZo += AcZ;
      ++i;
      Serial.println();
      Serial.println("***************************************************************************");
    } else if (!flaggl) {
      flaggl = 1;
      AcXo  = AcXo / 20;
      AcYo = AcYo / 20;
      AcZo = AcZo / 20;
    }
    curr = (AcZ - AcZo / 100);
    if (prev == curr )
      ++glc;
    else {
      glc = 0;
      prev = curr;
    }
    if (glc == 10) {
      Serial.println("lock broken!!!");
      glc = 0;
      loop();
    }
    if (flag == 1 && flaggl == 1) {
      if (lv2 < 21) {
        delayMicroseconds(2);
        digitalWrite(trigPin, HIGH);
        delayMicroseconds(10);
        digitalWrite(trigPin, LOW);
        duration = pulseIn(echoPin, HIGH);
        distance = duration * 0.034 / 2;
        AcXd += (AcX - AcXo) / 100;
        AcYd += (AcY - AcYo) / 100;
        AcZd += (AcZ - AcZo) / 100;
        yprd[0] += ypr[0] * 180 / M_PI - yo;
        yprd[1] += ypr[1] * 180 / M_PI - po;
        yprd[2] += ypr[2] * 180 / M_PI - ro;
        distanced += distance;
        ++lv2;
      } else {
        AcXd /= 20;
        AcYd /= 20;
        AcZd /= 20;
        yprd[0] /= 20;
        yprd[1] /= 20;
        yprd[2] /= 20;
        distanced /= 20;
        lv2 = 1;
        Serial.print("AcX = ");
        Serial.print(AcXd);
        Serial.print(" | AcY = ");
        Serial.print(AcYd);
        Serial.print(" | AcZ = ");
        Serial.print(AcZd);
        Serial.print(" | yaw = ");
        Serial.print(yprd[0]);
        Serial.print(" | pitch = ");
        Serial.print(yprd[1]);
        Serial.print(" | roll = ");
        Serial.print(yprd[2]);
        Serial.print(" | distance = ");
        Serial.println(distanced);
        AcXd  = 0;
        AcYd = 0;
        AcZd = 0;
        yprd[0] = 0;
        yprd[1] = 0;
        yprd[2] = 0;
        distanced = 0;
      }
    }
  }
}

```

The code involves offset calculation and displays the averaged instantaneous values. After overcoming the problems of FIFO buffer overflow and some other typical issues, I've managed to get the code running but the the Arduino hangs after sometime (code tested on both Uno and Nano).

Therefore, it *seems* that maybe I need a higher clock speed. So, I had a look through other Arduino boards and Due seemed to be the solution, as it has a clock speed of 84MHz, compared to Uno's 16 MHz. Therefore, my question is that will the libraries and functions used in this code be compatible with the Due? Also, can the 3.3V operation of the Due, compared to Uno's 5V, present any problem in interfacing it with other sensors mentioned?

# Answer
> 0 votes
> Therefore, my question is that will be the libraries and functions used in this code be compatiable with Due?

The I2Cdev library is made for abstracting the hardware I2C functions to a more user friendly interface for each chip. Since the Arduino Due has hardware TWI (which is basically I2C) the normal `Wire` library from the Arduino IDE should work with it.

> Also, can the 3.3V operation of Due, compared to Uno's 5V present any problem in interfacing it with other sensors mentioned?

You cannot put 5V from your sensor on a 3.3V pin on the Arduino Due, since this would destroy the pins hardware. I don't know how exactly you are using the MPU6050, but this one from Adafruit runs on 3.3V, which would be perfect. If your MPU6050 board only works with 5V maybe you can level shift the lines (but note that I2C would need 2-way level shifting, because SDA is used as output and input).

Also this Article may help you, where they are porting MultiWii to an Arduino Due.

# Answer
> 0 votes
I am working with the ArduinoDue and ArduinoMega2560 boards and I have found that programs that compile with the Mega2560 board don't necessary compile with the Due board. This is because there is a limited amount of available libraries that are compatible with the Due board. Try compiling (verifying) your code with the Due options set, you don't need to buy one to try verifying it.

---
Tags: arduino-uno, arduino-nano, arduino-due, mpu6050
---


title: PWM delay without blocking the code

text:
# Question
Title: PWM delay without blocking the code
I want my LED to turn on gradually without using the `delay()` function and blocking the code.

Here's the code i came up with:

```
int led_pin = 6;
unsigned long millisTimer = 0;
int PWMdelay = 5000;
int condition = 0;
int i = 0;
void setup() {
    pinMode(led_pin, OUTPUT);
}
void loop() {
    if(condition == 1){
    if ((millis() - millisTimer) > PWMdelay){
        if(i<255){
            i++;
            millisTimer = millis();
        }

    }
        analogWrite(led_pin, i);
    }
}

```

Is this the "right way" of slowing the PMW duration from 0 to 255 or there are alternative/better/easier ways?

# Answer
> 3 votes
Here is my take at this - I've followed the example code mentioned by other members and here is "FadeWithoutDelay"

```

const int ledPin = 11;
unsigned long previousMillis = 0;        // will store last time LED was updated
const long interval = 100;               // fade interval (milliseconds)
int brightness = 0;                      // how bright the LED is
int fadeAmount = 5;                      // how many points to fade the LED by

void setup()
{
  pinMode(ledPin, OUTPUT);  // set the digital pin as output:
}
void loop()
{
  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= interval)
  {
    previousMillis = currentMillis;         // save the last state
    analogWrite(ledPin, brightness);        // Set the brightness
    brightness = brightness + fadeAmount;   // change the brightness for next time through the loop
    // reverse the direction of the fading at the ends of the fade:
    if (brightness <= 0 || brightness >= 255)
    {
      fadeAmount = -fadeAmount;
    }
  }
}

```

---
Tags: programming, pwm
---


# Question
Title: Person (phone) detector that trigger an event esp32 cam
So me and my dad are trying to catch would be thieves and also someone leaving behind alcohol bottles. At his storage business the cameras don't reach to these spots.

Without being too invasive I want to sense bluetooth and/or wifi signals of relatively close phones sort of like a pax counter. This is in lue of using a pir sensor which I have always found finicky and I want to make use of the esp32' cam's wifi/ble chip.

So to start I researched for the past few days or week. I found that most phones don't use ble so maybe that is out. I also found that the esp32 cam is a bit finicky and I'm not sure if it is compatible with other code I have found.

One time I was able to get the light to come on when my phone was near using code I found for the esp32.

Any help or direction would be nice

Edit: I understand this sounds weird but mostly I would just like to get proximity of bluetooth or wifi to trigger an event. The device is powered by battery and I understand not everyone carrys phones.

# Answer
Detecting a phone could be easily done by capturing WiFi probe requests which are sent by phones having at least one saved WiFi network. Note that such requests alone are often enough to identify the person, if their home WiFi SSID is set to something like "Davids\_wifi".

Software-wise, this would be much easier to do on Linux (think Raspberry Pi or a similar device) which already have all the network sniffing software like `tcpdump`, which you would otherwise have to find or implement on ESP32.

I'm leaving out the legal implications of what you're trying to do as I don't know what country you are in, but bear in mind that hidden surveillance may be illegal in some cases.
> 0 votes

---
Tags: wifi, bluetooth, esp32, camera
---


# Question
Title: How to utilize SPI Serial bus on a ATSAMD21G18?
Like the title suggests, I have a ATSAMD21G18 microcontroller that I want to interface with a LTC6803-4 chip, but I'm not sure how to set up the SPI bus on the microcontroller, and the datasheet proved too confusing for me to understand.

# Answer
Use the SPI API provided by Arduino (https://www.arduino.cc/en/Tutorial/SPITransaction) and the command format that the chip wants you to use based on the datasheet. Here's a bit of example code for SPI transaction. Though untested, it's what I understood from reading the datasheet. Written for an Adafruit Feather M0 express (uses SAMD21G18 MCU). For pinout see https://learn.adafruit.com/adafruit-feather-m0-express-designed-for-circuit-python-circuitpython/adafruit2-pinouts#logic-pins-2-8.

Also note that Analog Devices does provide Arduino-Code for *similiar* devices like LTC6803-2 but not for the -4. Still, you can look how they implemented a driver. See here

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

/* pin setup */
int chip_select_pin = PIN_A2;
/* SPI pins labeled "SCK" "MO" "MI" on the Adafruit Feather M0 express board
 * are used implicitly.
 * PIN_SPI_MISO (22),  PIN_SPI_MOSI(23), PIN_SPI_SCK(24),
 * */

#define LTC6803_4_MAX_SCLK_FREQ 1000000
#define LTC6803_4_USED_SCLK_FREQ (LTC6803_4_MAX_SCLK_FREQ/2)

SPISettings settings(LTC6803_4_USED_SCLK_FREQ, BitOrder::MSBFIRST, SPI_MODE3);

void start_voltage_adc_conversion(){
    SPI.beginTransaction(settings);
    digitalWrite(chip_select_pin, LOW);
    //STCVAD
    //Start Cell Voltage ADC Conversions and Poll Status, with Discharge Permitted
    uint8_t tranfer_buf[2] = {
            0x10, //CODE
            0xB0 //PEC
    };
    SPI.transfer(tranfer_buf, 2);
    //wait for conversion, just a static time. at least 12 milliseconds.
    delay(20);
    digitalWrite(chip_select_pin, HIGH);
    SPI.endTransaction();
}

void read_voltages_1_to_4(){
    //trigger voltage conversion
    start_voltage_adc_conversion();

    SPI.beginTransaction(settings);
    digitalWrite(chip_select_pin, LOW);
    //transfer buffer must have 2 bytes for command
    //and 6 bytes for response (four 12-bit ADC values encoded in 6 registers CVR00..CVR05)
    //plus 1 byte for PEC from chip
    //Read Cell Voltages 1-4, "RDCVA", page 22
    uint8_t tranfer_buf[2 + 6 + 1] = {
            0x06, //CODE
            0xD2 //PEC
    };
    SPI.transfer(tranfer_buf, 9);
    digitalWrite(chip_select_pin, HIGH);
    SPI.endTransaction();

    //recover 12-bit ADC value from C1V[0]..C1V[11] from register values CVR00 and CVR01
    //see datasheet page 24
    uint16_t adc_cell_1 = tranfer_buf[2] | ((tranfer_buf[3] & 0B1111) << 8);
    //adc value to voltage conversion according to page 15
    float voltage_cell_1_millivolt = ((int)adc_cell_1 - 512) * 1.5f ;
    Serial.print("Cell voltage 1: ");
    //print with 5 digits accuracy
    Serial.print(voltage_cell_1_millivolt, 5);
    Serial.println(" mV");
}

void setup() {
    Serial.begin(115200);
    pinMode(chip_select_pin, OUTPUT);
    SPI.begin();
}

void loop() {
    read_voltages_1_to_4();
    delay(2000);
}

```
> 2 votes

---
Tags: serial, c++, spi
---


# Question
Title: Can you put Ardupilot on any flight controller?
Some FC's say that they support cleanflight and have no mention of Ardupilot. Is this just because its what's recommended or because it's all that works?

# Answer
There are pre-built binaries for many flight controllers.

http://firmware.ardupilot.org/ lists out the different ardupilot builds (arducopter, arduplane, etc.) and by clicking on them , you can see the different versions, then the different builds per version.

This document goes into more detail on the file structure they use for pre-built binaries.
> 2 votes

---
Tags: drone
---


title: Arduino Nano LED not working

text:
# Question
Title: Arduino Nano LED not working
I am just starting with Arduino and was trying to make the LED example work. I changed the script as follows to keep the LED on:

```
#define LED_PIN 12
#define LED_RX_SIG LED_BUILTIN

void setup() {
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(LED_PIN, OUTPUT);
  pinMode(LED_RX_SIG, OUTPUT);
}

// the loop function runs over and over again forever
void loop() {
  digitalWrite(LED_PIN, HIGH);   // turn the LED on (HIGH is the voltage level)
  //delay(1500);                       // wait for a second
  //digitalWrite(LED_PIN, LOW);    // turn the LED off by making the voltage LOW
  //delay(1500);                       // wait for a second
  //digitalWrite(LED_RX_SIG, HIGH);
  //delay(1000);
  //digitalWrite(LED_RX_SIG, LOW);
  //delay(1000);
}

```

I setup the Nano board, LED and a 220ohm resistor on a breadboard. The D12 port on Nano is connected to one end of the 220ohm resistor using a jumper cable. The other end of the resistor is connected to the positive (longer end) of the LED. The negative end of the LED is connected to the GND pin on Nano. The setup is shown in the image below:

What's wrong with the setup and why the LED is not lit? Sorry in advance for such novice question and any help will be greatly appreciated. Thanks

# Answer
> 3 votes
As your program is currently written, you should see your LED light. I see nothing wrong with your program or your wiring. I am also assuming that you had no errors while compiling and downloading the program.

With the rest of the lines uncommented, what you should see is your LED light up for 1.5 seconds and then off. Then after another 1.5 seconds, the on-board LED should turn on and then off (both 1 second).

If you have wired up the LED wrong (or a bad connection), you should at least still see the on-board LED flash about once every 5 seconds. If you don't see this then something else is wrong.

One thing I notice from the photos is that you have no way of powering your circuit. (I realise this may just be while you took the photo). Plug a USB cable into the Arduino and the other end into the computer. You should see the LED called "POW" light up.

To verify your LED circuit, try disconnecting the jumper at D12 and connecting it to 5V and you should see the LED light. If this works then your circuit is OK so replace the jumper back at D12.

If the LED still does not light up when the jumper is connected to 5V then we need to dive into that circuit. Possible reasons include:

* The LED is dead -\> replace the LED
* The breadboard is not making good connection -\> wiggle the leads (to scratch away any corrosion) or twist together the wires where possible or even solder them together.
* The jumper wires are manufactured poorly (eg. the plastic wasn't stripped before crimping) -\> check the jumper crimps.
* The LED has been manufactured wrong and what should be the anode is actually the cathode (I have seen this) -\> reverse the polarity of the LED.
* The resistor is burnt out -\> replace the resistor.

# Answer
> 1 votes
If your led does not turn on after you directly connect it to the VCC and the GND (as you mentioned in a comment) , it means that your led is most likely broken. Simply try using another Led as your circuit and code look fine.

---
Tags: arduino-nano, led, breadboard
---


# Question
Title: Velleman KA02 not working on Mega 2560 r3
I have a Velleman KA02 audio shield. When I use this shield on an Arduino UNO R3 with this sample code, it works. And by "work" I mean when I interact with the `Serial Monitor` (by pressing `Y`, for example), I hear the playback.

However, if I place this audio shield on a Mega 2560 R3, the shield no longer works (pressing `Y` does nothing). I read about the SPI library, and the document seems to suggest that `MISO`, `MOSI`, `SCK` and `SS` are different for the Uno vs the Mega. For the Uno,

* MOSI: 11
* MISO: 12
* SCK: 13
* SS: 10

and the article is consistent with the constants defined in the ISD1700.h file. For the Mega,

* MOSI: 51
* MISO: 50
* SCK: 52
* SS: 53

I can modify `ISD1700.h` for use with the Mega easy enough. However, I do not think I can just sit the audio shield right on top of the Mega with the modified code and have it work. I used some (male to female) jumper wires to connect from the Mega pins 50, 51, 52, 53 to the audio shield pins 12, 11, 13, 53 (correspondingly). Additionally, I have jumper wires connecting the power and ground from the Mega to the audio shield. What works is that the audio shield has power and I am able to press the physical buttons on the audio shield to record and playback. What does not work is that when I enter `Y` in the serial monitor to force a playback, although the character is read and the `switch` case is reached, the playback never happens.

Any ideas on what I am doing wrong? On the Velleman site, they seem to suggest that this audio shield only works with the Uno, but the Illustrated Assembly Manual says that the audio shield should work with the Mega.

# Answer
Nevermind, I solved it. There's 6 pins located on the Uno and Mega labelled ICSP, and those were the key. I simply connected the MOSI, MISO and SCK pins on the Mega to the audio shield (along with GND and 5V) and also the 10 pin (audio shield) to the 53 pin (Mega) via a male to male jumper. The header code was modified to work with the new values, and now I am able to send character signals via the serial monitor.
> 1 votes

---
Tags: arduino-uno, spi, audio, atmega2560
---


# Question
Title: analogRead() output oscillates even though the pin is grounded
I'm using Arduino Micro to read from 5 flex sensors and display the corresponding angles to the Serial monitor. I am currently having quite some problems with the oscillating values I am getting from the analogRead(). It doesn't seem to matter whether the pin is connected to a flex sensor or just grounded - the output is oscillating a lot.

Originally everything was being read and outputted just fine but I wanted to have an exact 100Hz sampling frequency and tried to play a bit with Timer Interrupts. And that's when this oscillating behaviour started. I reversed to my original code, which just uses some delay(), and simplified to only read from two pins, but cannot seem to shake off the oscillations.

I think I may have messed up something about ADC when trying to implement Interrupts, but I don't know how to check it or fix it. Please, help me figure out how to fix this!

This is the raw output of analogRead. The drop in values occurs when I bend the flex sensor:

And this is the resulting calculated angle. Also oscillating:

This is the code I've been using to read the pins:

```
int fin;
const int input[5] = {A0,A1,A2,A3,A4}; // the analog pins

int flex[5]; // analog signal read
float flexV;
float flexR[5]; // resistance on the 47k resistor
int angle[5]; // joint angles

const float VCC = 4.98; // Measured voltage of Arduino 5V line
// Measured resistance of the 47k resistors R1-R5
const float R[5] = {45900.0,45900.0,45900.0,45900.0,45900.0};

// Calibration values of resistance measured during straight phase and 90 deg bend phase
const float R_STRAIGHT[5] = {37651.0,37651.0,37651.0,37651.0,37651.0};
const float R_BEND[5] = {71783.0,71783.0,71783.0,71783.0,71783.0};

void setup() {

}

void loop() {

  for(fin = 0; fin <= 4; fin++) {
   flex[fin] = analogRead(input[fin]);
   flexV = flex[fin]*VCC/1023.0;
   flexR[fin] = R[fin] * (VCC/flexV - 1.0);
   angle[fin] = map(flexR[fin],R_STRAIGHT[fin],R_BEND[fin],0,90.0);
   delay(1);
    }
    Serial.print(angle[0]);
    Serial.print(" ");
    Serial.print(angle[1]);
    Serial.print(" ");
    Serial.print(angle[2]);
    Serial.print(" ");
    Serial.print(angle[3]);
    Serial.print(" ");
    Serial.print(angle[4]);
    Serial.print(" ");
    Serial.println(millis());
    delay(6);
}

```

# Answer
> 1 votes
You have nothing in your setup loop. You need to set up all the inputs as inputs.

You setup() should look like this:

```
void setup()
 {
   Serial.begin(9600);
   for (int i = 0; i < 5; i++);
    {
      pinMode(input[i], INPUT);
    }
 }

```

The code cycles through your array "input", setting all the pins as inputs. Try that.

---
Tags: interrupt, analogread, arduino-micro, adc
---


# Question
Title: Memory usage in AnalogBinLogger of SdFat library
The AnalogBinLogger.ino file of SdFat library says the following:

> Each 512 byte data block in the file has a four byte header followed by up to 508 bytes of data. (508 values in 8-bit mode or 254 values in 10-bit mode). Each block contains an integral number of samples with unused space at the end of the block.

I was wondering why only 254 values can be stored in 10-bit mode instead of (508\*8 bits/ 10 bits ~ 406 values ).

1. Is this because of the memory being byte-addressable and hence does a 10-bit value take up 2 bytes?
2. If so, how will a file-reader differentiate between a 10-bit value taking 2 bytes and two 8-bit values?
3. The AnalogBinLogger.ino says:

> The logger will use SdFat's buffer plus BUFFER\_BLOCK\_COUNT additional buffers.

`BUFFER_BLOCK_COUNT` is 1 for the Arduino Uno since it has 2KB of SRAM. Each buffer is 512-byte long. Is **SdFat's internal buffer** also in SRAM? If I am not wrong, the libraries the program uses and the program code reside in the Flash memory, can SdFat write into a buffer in Flash memory?

# Answer
> how will a file-reader differentiate between a 10-bit value taking 2 bytes and two 8-bit values?

The file AnalogBinLogger.h, which comes with the example sketch you mentioned, contains the following:

```
// First block of file.
struct metadata_t {
  unsigned long  adcFrequency;     // ADC clock frequency
  unsigned long  cpuFrequency;     // CPU clock frequency
  unsigned long  sampleInterval;   // Sample interval in CPU cycles.
  unsigned long  recordEightBits;  // Size of ADC values, nonzero for 8-bits.
  unsigned long  pinCount;         // Number of analog pins in a sample.
  unsigned long  pinNumber[123];   // List of pin numbers in a sample.
};

```

Thus, the file reader just needs to be aware of the format of this first block, and read the `recordEightBits` field in order to know whether this is 8-bit data or not.

> Is SdFat's buffer also in SRAM?

Yes, that's the only sensible place you could have a data buffer. It's allocated on the stack, only during the execution of the `logData()` function.
> 1 votes

---
Tags: arduino-uno, memory-usage, flash
---


title: Libraries not included correctly

text:
# Question
Title: Libraries not included correctly
I stumbled upon the following unexpected behaviour and am curious about its cause.

header.h:

```
#include <Time.h>
[...]

```

main.ino:

```
#include "header.h"
#include <Time.h>
[...]

```

My code is working correctly with this setup. However, if I comment out the Time.h library in my main.ino, my code is working not correctly anymore:

```
#include "header.h"
//#include <Time.h>
[...]

```

I can still access the functions of Time.h, but they are returning garbage time.

Why do I have to include the library in my \*.ino, although I am already including it in my header file? Is there a best practice, on where to include libraries? Shall I simply always include all libraries in my \*.h and \*.ino file?

# Answer
Firstly you should be including `TimeLib.h` not `Time.h` \- the library header name has been changed to avoid conflicts on case-insensitive systems (Windows) and the internal `time.h` header in many compilers.

Secondly you should always include all your libraries in your INO file directly. This is because the IDE parses the INO file before compiling looking for any included libraries. It then adds these found libraries to the list of libraries that need to be compiled. Without this you won't get the source code for your libraries compiled properly.
> 1 votes

---
Tags: arduino-ide, library
---