title: NeoMatrix Button Troubles

text:
# Question
Title: NeoMatrix Button Troubles
I am creating a 20x15 LED Matrix using and Arduino Nano. My goal is to switch between different "scenes," if you will, using 4 buttons (I just need to run different code to make it display something different). The four buttons share a ground, and they go into digital pins (I don't have resistors on the ground because of this article). Then in the code (under `void loop`) there is one big if-then tree. For example, `if (button1State == HIGH) {} else {if (button2State == HIGH)}` and so on and so forth.

When I connect the buttons, the lights flicker and glitch. Without the buttons, it goes to the last `else` completely fine, so I know my light code works. To me, the code looks fine, but I want to see if there is something that I am doing wrong. I wonder if putting the code in voids instead of them in the if-thens in the loop would be better, but I don't know how I would invoke them.

If anyone could figure out what I am doing wrong or something that could make my code better, I would be super grateful.

Here is my full, current code (ignore all of the comments, I am designing the code so someone with no coding knowledge could understand it)

```
//   HEY! LOOK UP HERE! I know it looks confusing, but don't worry, I'll help you! I'm Clippy!
//    _________________
//   < I can help you! >
//    -----------------
//    \
//     \
//        __
//       /  \
//       |  |
//       @  @
//       |  |
//       || |/
//       || ||
//       |\_/|
//       \___/

//As you know, there are 4 buttons. When they are pressed, they display something different. We can make them display text as well.
//Below are VARIABLES, which control what text is displayed when buttons are pressed. Put what you want them to display between the
//quotation marks. If you don't want anything in a button, just put a space inbetween them.

//Note: only button 1 and 3 can display text, so lets only put text in those :)
String buttonText1 = " "; //Again, put what you want button 1 to display in text
//String buttonText2 = " ";
String buttonText3 = " ";
//String buttonText4 = " ";
String defaultText = "   Text for the panel"; //This is what will show up when you first start it up

//Here we can adjust what the brightness of the panel is. We use a switch to do this. You can use values from 0 (lowest) to 255 (highest)
int switchLevel1 = 10;
int switchLevel2 = 200;

//Here we can control how many colors are on the backgrounds at one time. We can customize this to get some variety in our displays.
int colorsOnscreen1 = 5; //For button 1
//int colorsOnscreen2 = 3
int colorsOnscreen3 = 10; //For button 3
//int colorsOnscreen4 = 5;
int colorsOnscreenDefault = 3; //For when you start it up

int lastButton = 0; //Last button pressed stuff, gets fed to buttons

//----------------------------------------------------------------You Probably Don't Have To Worry About The Rest----------------------------------------------------------------

//This stuff you don't have to worry about, its for the board
#include <Adafruit_NeoPixel.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SPITFT.h>
#include <Adafruit_SPITFT_Macros.h>
#include <gfxfont.h>
#include <Adafruit_NeoMatrix.h>
#include <gamma.h>
#include "RGB.h"
#ifndef PSTR
 #define PSTR
#include smileytongue24.h
#include yellowsmiley24.h
#endif

#define PIN 3 // This is the pin where the data is coming out (you don't have to worry about this)

const int button1 = 4;     // the number of the arcade button pins
const int button2 = 5;
const int button3 = 6;
const int button4 = 7;
const int brightnessSwitch = 8;

// variables will change:
int button1State = 0;         // variable for reading the pushbutton status
int button2State = 0;
int button3State = 0;
int button4State = 0;
int switchState = 0;
int panelBrightness = 0;

//This stuff tells the board how the lights are arranged. In our case, it starts at the top left, and
//the signal goes right, and zigzags the rest of the way. It also tells it that it is 20 by 15 LEDs
Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(20, 15, PIN,
  NEO_MATRIX_TOP     + NEO_MATRIX_RIGHT +
  NEO_MATRIX_ROWS + NEO_MATRIX_ZIGZAG,
  NEO_GRB            + NEO_KHZ800);

void setup() {
  // initialize the buttons as inputs:
  pinMode(button1, INPUT);
  pinMode(button2, INPUT);
  pinMode(button3, INPUT);
  pinMode(button4, INPUT);
  pinMode(brightnessSwitch, INPUT);
  matrix.begin();
  matrix.setTextWrap(false);
  Serial.begin(9600);
  Serial.print("The LED Matrix has started. Default will be activated soon");
}

String panelText = buttonText1; //This is what text gets fed to the panel

int x    = matrix.width();
int pass = 0;

void loop() {
  matrix.setBrightness(panelBrightness); //This sets the overall brightness. 255 is the highest, while 0 is the lowest
  // read the state of the button:
  button1State = digitalRead(button1);
  button2State = digitalRead(button2);
  button3State = digitalRead(button4);
  button4State = digitalRead(button4);
  switchState = digitalRead(brightnessSwitch);
  if (switchState == HIGH){panelBrightness = switchLevel1;} else {panelBrightness = switchLevel2;} //Brightness Logic

  // if-then statements
  if (button1State == HIGH){ //BUTTON 1 CODE START
      static int i = 0;
  i++;
  for(int y = 0; y < 15; y++)
    for(int x = 0; x < 20; x++)
      if(y & 1)
        matrix.setPixelColor(19 - x + y * 20, matrix.gamma32(matrix.ColorHSV((x + y) * 256 * colorsOnscreen1 + i * 128 * 2)));
      else
        matrix.setPixelColor(x + y * 20, matrix.gamma32(matrix.ColorHSV((x + y) * 256 * colorsOnscreen1 + i * 128 * 2)));

  matrix.setTextColor(matrix.Color(255, 255, 255)); //This determines the text color. If you want to set a text color, search in google "Color Picker" and use the RGB values in place of the numbers in (a,a,a)
  matrix.setCursor(-((millis() / 40) & 127), 4);
  matrix.print(buttonText1);
  matrix.show();
}
//BUTTON 1 CODE END
   else {
      if (button2State == HIGH){ //BUTTON 2 CODE START
          //PUT WHAT HAPPENS FOR BUTTON 2 HERE
          //BUTTON 2 CODE END
      } else {
          if (button3State == HIGH){ //BUTTON CODE 3 START
                    static int i = 0;
  i++;
  for(int y = 0; y < 15; y++)
    for(int x = 0; x < 20; x++)
      if(y & 1)
        matrix.setPixelColor(19 - x + y * 20, matrix.gamma32(matrix.ColorHSV((x - y) * 200 * colorsOnscreen3 + i * 128 * 2)));
      else
        matrix.setPixelColor(x + y * 20, matrix.gamma32(matrix.ColorHSV((x - y) * 256 * colorsOnscreen3 + i * 128 * 2)));

  matrix.setTextColor(matrix.Color(255, 255, 255)); //This determines the text color. If you want to set a text color, search in google "Color Picker" and use the RGB values in place of the numbers in (a,b,c)
  matrix.setCursor(-((millis() / 40) & 127), 4);
  matrix.print(buttonText3);
  matrix.show();
}
              //BUTTON 3 CODE END
           else {
              if (button4State == HIGH){ //BUTTON 4 CODE START
                  //PUT WHAT HAPPENS FOR BUTTON 4 HERE
                  //BUTTON 4 CODE END
              } else {
                  //WHAT HAPPENS UNTIL A BUTTON IS PRESSED

   static int i = 0;
  i++;
  //matrix.fillScreen(0);
  for(int y = 0; y < 15; y++)
    for(int x = 0; x < 20; x++)
      if(y & 1)
        matrix.setPixelColor(19 - x + y * 20, matrix.gamma32(matrix.ColorHSV((x + y) * 256 * colorsOnscreenDefault + i * 128 * 2)));
      else
        matrix.setPixelColor(x + y * 20, matrix.gamma32(matrix.ColorHSV((x + y) * 256 * colorsOnscreenDefault + i * 128 * 2)));

  matrix.setTextColor(matrix.Color(255, 255, 255)); //This determines the text color. If you want to set a text color, search in google "Color Picker" and use the RGB values in place of the numbers in (a,b,c)
  matrix.setCursor(-((millis() / 70) & 127), 4);
  matrix.println(defaultText);
  matrix.show();

}}}}

    }

```

Again, Thank You

-Micah

# Answer
I think your main problem is how you read the buttons.

1. You simply connected the buttons with ground and the corresponding digital input pin on the Arduino without any extra components, just like the linked forum entry states. But you missed a very important part: The pullup resistor. When your button is pressed, the Arduinos pin will be pulled to ground. But if it is not pressed, there is nothing connected to the pin. Such a pin is called floating, as it does not have a fixed reference value. It will pick up whatever noise is floating around at it's location (often the state of other electronic parts or pins near it). It will change it's state erratically. You need to pull the pin to Vcc (5V in case of the Nano), so that the pin has a clear fixed state, when the button is not pressed. This can be done by either an external or the internal pullup resistor of the Atmega328P (the chip on the Nano). In the forum post the internal pullup is activated by doing a `digitalWrite(pin, HIGH);` after setting the pin to INPUT. But I think it is more speaking code to just use `pinMode(pin, INPUT_PULLUP);` which will do the same in one single step.
2. In your code you check for the button pins to be HIGH, as if a button press would make the pin HIGH. But this is not the case, if you connect the button to ground. If pressed, the button will pull the pin to GROUND, thus a value of LOW. You need to check for the buttons to get LOW.
> 1 votes

# Answer
You should always comment your code, so that you will know what your code does when you look at it 6 months from now.

For beginners, you should not leave out the braces `{}` from any part of the code as you did in the `for` loops.

Here is your code correctly formatted, followed by a more cleaned up version which may be easier for beginner to follow.

Main question is whether the `for` loops are written as you intended.

Also, the use of `if {} else { if {}}` makes the code listing somewhat convoluted.

The second listing shows the `if {} else if {}` version.

```
//   HEY! LOOK UP HERE! I know it looks confusing, but don't worry, I'll help you! I'm Clippy!
//    _________________
//   < I can help you! >
//    -----------------
//    \
//     \
//        __
//       /  \
//       |  |
//       @  @
//       |  |
//       || |/
//       || ||
//       |\_/|
//       \___/

// As you know, there are 4 buttons. When they are pressed, they display something different. We can make them display text as well.
// Below are VARIABLES, which control what text is displayed when buttons are pressed. Put what you want them to display between the
// quotation marks. If you don't want anything in a button, just put a space inbetween them.

//Note: only button 1 and 3 can display text, so lets only put text in those :)
String buttonText1 = " "; //Again, put what you want button 1 to display in text
//String buttonText2 = " ";
String buttonText3 = " ";
//String buttonText4 = " ";
String defaultText = "   Text for the panel"; //This is what will show up when you first start it up

//Here we can adjust what the brightness of the panel is. We use a switch to do this. You can use values from 0 (lowest) to 255 (highest)
int switchLevel1 =  10;
int switchLevel2 = 200;

//Here we can control how many colors are on the backgrounds at one time. We can customize this to get some variety in our displays.
int colorsOnscreen1 = 5;           // For button 1
//int colorsOnscreen2 = 3
int colorsOnscreen3 = 10;          // For button 3
//int colorsOnscreen4 = 5;
int colorsOnscreenDefault = 3;     // For when you start it up

int lastButton = 0;                // Last button pressed stuff, gets fed to buttons

//----------------------------------------------------------------You Probably Don't Have To Worry About The Rest----------------------------------------------------------------

//This stuff you don't have to worry about, its for the board
#include <Adafruit_NeoPixel.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SPITFT.h>
#include <Adafruit_SPITFT_Macros.h>
#include <gfxfont.h>
#include <Adafruit_NeoMatrix.h>
#include <gamma.h>
#include "RGB.h"
#ifndef PSTR
 #define PSTR
#include smileytongue24.h
#include yellowsmiley24.h
#endif

#define PIN 3 // This is the pin where the data is coming out (you don't have to worry about this)

const int button1          = 4;     // the number of the arcade button pins
const int button2          = 5;
const int button3          = 6;
const int button4          = 7;
const int brightnessSwitch = 8;

// variables will change:
int button1State           = 0;     // variable for reading the pushbutton status
int button2State           = 0;
int button3State           = 0;
int button4State           = 0;
int switchState            = 0;
int panelBrightness        = 0;

                                                                        // This stuff tells the board how the lights are arranged.
Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(20,                      // In our case, it starts at the top left,
                                               15,                      //   and the signal goes right, and zigzags the rest of the way.
                                               PIN,                     // It also tells it that it is 20 by 15 LEDs
                                               NEO_MATRIX_TOP + NEO_MATRIX_RIGHT + NEO_MATRIX_ROWS + NEO_MATRIX_ZIGZAG,
                                               NEO_GRB + NEO_KHZ800);

void setup() {
  pinMode(button1, INPUT);                                              // initialize the buttons as inputs:
  pinMode(button2, INPUT);
  pinMode(button3, INPUT);
  pinMode(button4, INPUT);

  pinMode(brightnessSwitch, INPUT);

  matrix.begin();
  matrix.setTextWrap(false);

  Serial.begin(9600);
  Serial.print("The LED Matrix has started. Default will be activated soon");
}

String panelText = buttonText1;                                         // This is what text gets fed to the panel

int x    = matrix.width();
int pass = 0;

void loop() {
  matrix.setBrightness(panelBrightness);                                // This sets the overall brightness. 255 is the highest, while 0 is the lowest

  button1State = digitalRead(button1);                                  // read the state of the buttons
  button2State = digitalRead(button2);
  button3State = digitalRead(button4);
  button4State = digitalRead(button4);

  switchState = digitalRead(brightnessSwitch);

  if (switchState == HIGH) { panelBrightness = switchLevel1; }          // Brightness Logic
  else                     { panelBrightness = switchLevel2; }

  // if-then statements
  if (button1State == HIGH) {                                           // BUTTON 1 CODE START
    static int i = 0;
    i++;
    for(int y = 0; y < 15; y++)
      for(int x = 0; x < 20; x++)
        if(y & 1)
          matrix.setPixelColor(19 - x + y * 20, matrix.gamma32(matrix.ColorHSV((x + y) * 256 * colorsOnscreen1 + i * 128 * 2)));
        else
          matrix.setPixelColor(     x + y * 20, matrix.gamma32(matrix.ColorHSV((x + y) * 256 * colorsOnscreen1 + i * 128 * 2)));

    matrix.setTextColor(matrix.Color(255, 255, 255));                   // This determines the text color.
    matrix.setCursor(-((millis() / 40) & 127), 4);                      //     If you want to set a text color, search in google "Color Picker"
                                                                        //     and use the RGB values in place of the numbers in (a,a,a)
    matrix.print(buttonText1);
    matrix.show();
  }                                                                     // BUTTON 1 CODE END

  else {
    if (button2State == HIGH) {                                         // BUTTON 2 CODE START
                                                                        //    PUT WHAT HAPPENS FOR BUTTON 2 HERE
    }                                                                   // BUTTON 2 CODE END
    else {
      if (button3State == HIGH) {                                       // BUTTON CODE 3 START
        static int i = 0;
        i++;
        for(int y = 0; y < 15; y++)
          for(int x = 0; x < 20; x++)
            if(y & 1)
              matrix.setPixelColor(19 - x + y * 20, matrix.gamma32(matrix.ColorHSV((x - y) * 200 * colorsOnscreen3 + i * 128 * 2)));
            else
              matrix.setPixelColor(     x + y * 20, matrix.gamma32(matrix.ColorHSV((x - y) * 256 * colorsOnscreen3 + i * 128 * 2)));

        matrix.setTextColor(matrix.Color(255, 255, 255));
        matrix.setCursor(-((millis() / 40) & 127), 4);

        matrix.print(buttonText3);
        matrix.show();
      }                                                                 // BUTTON 3 CODE END
      else {
        if (button4State == HIGH){                                      // BUTTON 4 CODE START
                                                                        //    PUT WHAT HAPPENS FOR BUTTON 4 HERE
        }                                                               // BUTTON 4 CODE END
        else {                                                          // WHAT HAPPENS UNTIL A BUTTON IS PRESSED

          static int i = 0;
          i++;
//        matrix.fillScreen(0);
          for(int y = 0; y < 15; y++)
            for(int x = 0; x < 20; x++)
              if(y & 1)
                matrix.setPixelColor(19 - x + y * 20, matrix.gamma32(matrix.ColorHSV((x + y) * 256 * colorsOnscreenDefault + i * 128 * 2)));
              else
                matrix.setPixelColor(     x + y * 20, matrix.gamma32(matrix.ColorHSV((x + y) * 256 * colorsOnscreenDefault + i * 128 * 2)));

          matrix.setTextColor(matrix.Color(255, 255, 255));
          matrix.setCursor(-((millis() / 70) & 127), 4);

          matrix.println(defaultText);
          matrix.show();
        }
      }
    }
  }
}

```

---

```
    //   HEY! LOOK UP HERE! I know it looks confusing, but don't worry, I'll help you! I'm Clippy!
    //    _________________
    //   < I can help you! >
    //    -----------------
    //    \
    //     \
    //        __
    //       /  \
    //       |  |
    //       @  @
    //       |  |
    //       || |/
    //       || ||
    //       |\_/|
    //       \___/

    // As you know, there are 4 buttons. When they are pressed, they display something different. We can make them display text as well.
    // Below are VARIABLES, which control what text is displayed when buttons are pressed. Put what you want them to display between the
    // quotation marks. If you don't want anything in a button, just put a space inbetween them.

                                                  // Note: only button 1 and 3 can display text, so lets only put text in those :)
    String buttonText1 = " ";                     // Again, put what you want button 1 to display in text
//  String buttonText2 = " ";
    String buttonText3 = " ";
//  String buttonText4 = " ";

    String defaultText = "   Text for the panel"; // This is what will show up when you first start it up

    int switchLevel1 =  10;                       // Here we can adjust what the brightness of the panel is.
    int switchLevel2 = 200;                       // We use a switch to do this. You can use values from 0 (lowest) to 255 (highest)

                                                  // Here we can control how many colors are on the backgrounds at one time.
                                                  // We can customize this to get some variety in our displays.
    int colorsOnscreen1 =  5;                     // For button 1
//  int colorsOnscreen2 =  3;
    int colorsOnscreen3 = 10;                     // For button 3
//  int colorsOnscreen4 =  5;

    int colorsOnscreenDefault = 3;                // For when you start it up

    int lastButton = 0;                           // Last button pressed stuff, gets fed to buttons

    //----------------------------------------------------------------You Probably Don't Have To Worry About The Rest----------------------------------------------------------------

    //This stuff you don't have to worry about, its for the board

    #include <Adafruit_NeoPixel.h>
    #include <Adafruit_GFX.h>
    #include <Adafruit_SPITFT.h>
    #include <Adafruit_SPITFT_Macros.h>
    #include <gfxfont.h>
    #include <Adafruit_NeoMatrix.h>
    #include <gamma.h>
    #include "RGB.h"
    #ifndef PSTR
      #define PSTR
      #include smileytongue24.h
      #include yellowsmiley24.h
    #endif

    #define PIN 3 // This is the pin where the data is coming out (you don't have to worry about this)

    const int button1          = 4;     // the number of the arcade button pins
    const int button2          = 5;
    const int button3          = 6;
    const int button4          = 7;
    const int brightnessSwitch = 8;

    // variables will change:
    int button1State           = 0;     // variable for reading the pushbutton status
    int button2State           = 0;
    int button3State           = 0;
    int button4State           = 0;
    int switchState            = 0;
    int panelBrightness        = 0;

                                                                        // This stuff tells the board how the lights are arranged.
    Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(20,                  // In our case, it starts at the top left,
                                                   15,                  //   and the signal goes right, and zigzags the rest of the way.
                                                   PIN,                 // It also tells it that it is 20 by 15 LEDs
                                                   NEO_MATRIX_TOP + NEO_MATRIX_RIGHT + NEO_MATRIX_ROWS + NEO_MATRIX_ZIGZAG,
                                                   NEO_GRB + NEO_KHZ800);

    void setup() {
      pinMode(button1, INPUT);                                          // initialize the buttons as inputs:
      pinMode(button2, INPUT);
      pinMode(button3, INPUT);
      pinMode(button4, INPUT);

      pinMode(brightnessSwitch, INPUT);

      matrix.begin();
      matrix.setTextWrap(false);

      Serial.begin(9600);
      Serial.print("The LED Matrix has started. Default will be activated soon");
    }

    String panelText = buttonText1;                                     // This is what text gets fed to the panel

    int x    = matrix.width();
    int pass = 0;

    void loop() {
      matrix.setBrightness(panelBrightness);                            // This sets the overall brightness. 255 is the highest, while 0 is the lowest

      button1State = digitalRead(button1);                              // read the state of the buttons
      button2State = digitalRead(button2);
      button3State = digitalRead(button4);
      button4State = digitalRead(button4);

      switchState = digitalRead(brightnessSwitch);

      if (switchState == HIGH) { panelBrightness = switchLevel1; }      // Brightness Logic
      else                     { panelBrightness = switchLevel2; }

      // if-then statements
      if (button1State == HIGH) {                                       // BUTTON 1 CODE START

        static int i = 0;
        i++;
        for (int y = 0; y < 15; y++) {
          for (int x = 0; x < 20; x++) {
            if (y & 1) {
              matrix.setPixelColor(19 - x + y * 20, matrix.gamma32(matrix.ColorHSV((x + y) * 256 * colorsOnscreen1 + i * 128 * 2)));
            }
            else {
              matrix.setPixelColor(     x + y * 20, matrix.gamma32(matrix.ColorHSV((x + y) * 256 * colorsOnscreen1 + i * 128 * 2)));
            }
          }
        }

        matrix.setTextColor(matrix.Color(255, 255, 255));               // This determines the text color.
        matrix.setCursor(-((millis() / 40) & 127), 4);                  //     If you want to set a text color, search in google "Color Picker"
                                                                        //     and use the RGB values in place of the numbers in matrix.Color(r,g,b)
        matrix.print(buttonText1);
        matrix.show();
      }                                                                 // BUTTON 1 CODE END

      else if (button2State == HIGH) {                                  // BUTTON 2 CODE START
                                                                        //    PUT WHAT HAPPENS FOR BUTTON 2 HERE
      }                                                                 // BUTTON 2 CODE END

      else if (button3State == HIGH) {                                  // BUTTON CODE 3 START

        static int i = 0;
        i++;
        for (int y = 0; y < 15; y++) {
          for (int x = 0; x < 20; x++) {
            if (y & 1) {
              matrix.setPixelColor(19 - x + y * 20, matrix.gamma32(matrix.ColorHSV((x - y) * 200 * colorsOnscreen3 + i * 128 * 2)));
            }
            else {
              matrix.setPixelColor(     x + y * 20, matrix.gamma32(matrix.ColorHSV((x - y) * 256 * colorsOnscreen3 + i * 128 * 2)));
            }
          }
        }

        matrix.setTextColor(matrix.Color(255, 255, 255));
        matrix.setCursor(-((millis() / 40) & 127), 4);

        matrix.print(buttonText3);
        matrix.show();
      }                                                                 // BUTTON 3 CODE END

      else if (button4State == HIGH) {                                  // BUTTON 4 CODE START
                                                                        //    PUT WHAT HAPPENS FOR BUTTON 4 HERE
      }                                                                 // BUTTON 4 CODE END

      else {                                                            // WHAT HAPPENS UNTIL A BUTTON IS PRESSED

        static int i = 0;
        i++;
//      matrix.fillScreen(0);
        for (int y = 0; y < 15; y++) {
          for (int x = 0; x < 20; x++) {
            if (y & 1) {
              matrix.setPixelColor(19 - x + y * 20, matrix.gamma32(matrix.ColorHSV((x + y) * 256 * colorsOnscreenDefault + i * 128 * 2)));
            }
            else {
              matrix.setPixelColor(     x + y * 20, matrix.gamma32(matrix.ColorHSV((x + y) * 256 * colorsOnscreenDefault + i * 128 * 2)));
            }
          }
        }

        matrix.setTextColor(matrix.Color(255, 255, 255));
        matrix.setCursor(-((millis() / 70) & 127), 4);

        matrix.println(defaultText);
        matrix.show();
      }
    }

```
> 0 votes

---
Tags: arduino-nano, button, sketch, rgb-led, neopixel
---


# Question
Title: Piezo buzzer with PWM on arduino uno with atmega328p in C on registers + analogRead on registers
I have a little project at the university where I have to use the timers to generate a pwm signal and get it into a piezo buzzer when something else turns over a certain value by using the registers, the thing is that we have worked on some other microcontrollers so I don't really know the libraries for arduino uno with atmega328p and I would require some help on that. Also I have to use the registers instead of the function analogRead() that is reading from a temperature sensor.

Having the following code that works for my setup:

```
#include <LiquidCrystal.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 2); //Digital pins to which you connect the LCD
const int inPin = 0;
const int buzzer=9;// A0 is the sensor
void setup()
{
  pinMode(buzzer,OUTPUT); // DDRA=0b00000001;
  lcd.begin(16,2);
}
void loop()
{
  int value = analogRead(inPin); // read the value from the sensor <= to be written on registers
  lcd.setCursor(0,1);
  float millivolts = (value / 1024.0) * 5;
  float celsius = (millivolts-0.5)*100;
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print(celsius);
  lcd.print("C");
  lcd.setCursor(0,1);
  lcd.print((celsius * 9)/5 + 32); //turning the celsius into fahrehait
  lcd.print("F");
  delay(1000);
  if(celsius>30.0){tone(buzzer,1000);delay(1000);noTone(buzzer);delay(1000);} //<= on registers
}

```

# Answer
In fact all the mentioned function calls are using the Special Function Registers (SFR) and thus the hardware peripherals of the Arduino in the background to work. But I guess this is an exercise to learn how to configure and use these peripherals yourself. Doing this for the whole code is a rather big task for a single question on this site. So I will give you hints and will point you to the corresponding registers. Then the datasheet of the Atmega328P (the microcontroller on the Arduino Uno) is a must read for you. It contains detailed descriptions for almost every function and SFR of the microcontroller.

1. **PWM:** I think you want to use PWM for creating a tone from your buzzer. This is not the classical PWM use case (as you don't need to change the duty cycle but the frequency to get different tones). Nonetheless you reach it with the same hardware. For hardware PWM you need to configure a Timer. The Uno has 3 Timers, where Timer0 is already configured by the Arduino IDE for functions like `delay()`, `millis()` and such. So I suggest you use Timer1. It has 3 control registers called `TCCR1A` to `TCCR1C`. You want the timer to be in CTC Mode (Clear Timer on Compare Match)(Waveform Generation Mode Bits set to 4, CTC mode for OCR1A). The timer will count up with the set frequency (will describe this later) until it gets to the value, that you wrote into the `OCR1A` register (Compare Match). Then it will reset. If you have set the `COM1Ax` bits in the `TCCR1A` register to the correct values, you can set it up to toggle the OC1A pin on a Compare Match).

So in this mode, the timer will reset at a counter value that you set and will toggle the OC1A output pin for you. Thus it generates a square wave with variable frequency, that you can control by writing different values to the `OCR1A` register.

But we also need to configure the frequency with which the timer will count up. This is done by the clock selection bits `CS10` to `CS12` in the `TCCR1B` register. A value of 0 for all bits means the timer is stopped. Look at the corresponding table in the Timer1 register descriptions in the datasheet. You want to connect the timer to the internal system clock. With these bits you can set the prescaler. This determines how many clock pulses it needs to let the timer count 1 up. With no prescaler the timer will count at every clock pulse. With the bit values 0 1 1 you will get a prescaler of 64, so the timer will count up 1 every 64 clock pulses. This sets the frequency range, that you have with the counter. The internal system clock runs at 16MHz on the Uno (you can do the math with the prescaler to calculate for the wanted frequency).
2. **analogRead aka ADC:** For reading an analog voltage the ADC (Analog Digital Converter) is used. It has the SFRs `ADMUX`, `ADCSRA`, the convertion result registers `ADCL` and `ADCH`, and `ADCSRB`. First we want to set the reference voltage for our conversion. When we set the `REFS1` and `REFS0` bits in the `ADMUX` register to 01 we use Vcc as voltage reference, which is sufficient most of the time. The bits `MUX3` to `MUX0` in the same register select one of the ADC pins for AD Conversion (We have only 1 ADC in the Atmega328P, but we can connect it to multiple ADC pins one after another). Now on the `ADCSRA` register: The `ADEN` bit will enable the ADC, with `ADSC` we can start a conversion. With the bits `ADPS2` to `ADPS0` we can select a clock prescaler for the ADC. This determines how fast the ADC runs. For maximum resolution you should keep the frequency between 50 and 200kHz.

You can start a conversion by writing 1 to the `ADSC`. Then you can poll the `ADIF` bit in the same register. It will be set to 1, when the ADC has completed the conversion. Then you can read the conversion result from the `ADCL` and `ADCH` registers (for the Low byte and the High byte of the 10bit result). You should reset the `ADIF` bit after that by writing a 1 to it.
3. **LCD:** I don't know, if you also need to replace the LiquidCrystal library by your own code, since it does not use special peripherals (just digital pins). Digital pins are controlled via the `DDRx`, `PORTx` and `PINx` registers. Google "arduino port manipulation" for more information. And then you can resemble the functions from the library with it.
> 1 votes

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


# Question
Title: using multiple hc-05 with one arduino mega
please anyone help me build my project, i want to connect multiple smart phones to arduino mega using blutooth module hc-05 , I am working on real life home automation project and i don't have idea that can i use 4 Bluetooth modules with arduino mega . Requirement is max 4 smart phone connect to system , please anyone knowing about arduino please help ,i will be grateful . if u have any other suggestions tell me .

# Answer
HC-05 modules use Serial (UART) for communication with the Arduino. Thus you need 4 Serial interfaces for 4 HC-05 modules. The Arduino Mega has 4 hardware Serial interfaces, so just connect once HC-05 to each Serial interface. Then handle each module in your code the same just with a different Serial interface. If you already know, how to use one HC-05, then it should be rather easy to implement the same with all 4 modules.
> 1 votes

---
Tags: arduino-uno, arduino-mega, bluetooth, home-automation
---


# Question
Title: How to obtain the real and imaginary signal parts using Arduino FFT
How do you obtain the real and imaginary parts of a signal using FFT in arduino? I could not find a particular tutorial with code for this purpose in the internet.

# Answer
> 1 votes
Most libraries will either take one array of samples as input and then fill two other arrays of real and imaginary data, or it will take one array of samples and one empty array as input, and the sample data will be replaced by the real data and the empty array filled with the imaginary data.

You will have to first choose a library to use and then read the examples or documentation to see what the format of the functions are.

---
Tags: signal-processing
---


title: Convert C string to C++ string

text:
# Question
Title: Convert C string to C++ string
My program is running on ESP32. I'm retrieving some data from Bluetooth, and the Bluetooth string is a C string. I need to save that data in an RTC\_DATA\_ATTR String, which is a C++ string.

Just doing `c++string = cstring.c_str();` won't work, since it will just save a pointer to the location in the memory of the C string, and the purpose is to save the data in the RTC memory, so the ESP32 can go to deep sleep without losing the data.

All other data than RTC gets wiped on deep sleep, so there would just be a pointer, pointing to nothing.

How do I get the data copied from the C string to the C++ string?

Any help would be appreciated. A bit of extra info: this is how it is set up at the moment:

```
RTC_DATA_ATTR String ssid;

BLECharacteristic *cSsid = NULL;

ssid = cSsid->getValue().c_str();

```

# Answer
> 0 votes
simply, using strcpy, and using a char with a given length, works

RTC\_DATA\_ATTR char ssid\["dedicated length"\];

strcpy(ssid, cSsid-\>getValue().c\_str(), "dedicated length");

---
Tags: arduino-ide, c++, esp32
---


title: Question about RGB LEDs

text:
# Question
Title: Question about RGB LEDs
I think many people know about the staircase lights, which will get triggered by 2 PIR-sensors (1x upstairs and 1x downstairs).

Here is my code - which works well. It's not cleaned up - as i don't know how i can simplify it. I think there'll be a much nicer way of getting the same output. :)

```
#include "FastLED.h"
#define NUM_LEDS 300
CRGB leds[NUM_LEDS];
#define PIN 3
int sensorUP = 5;
int sensorDOWN = 7;
int state = LOW;
int valUP = 0;
int valDOWN = 0;

void setup()
{
  FastLED.addLeds<WS2811, PIN, GRB>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
  FastLED.setBrightness(20);
  pinMode(2, INPUT_PULLUP); // internal pull-up resistor
  pinMode(sensorUP, INPUT);
  pinMode(sensorDOWN, INPUT);
  Serial.begin(9600);
}

void loop() {
  valUP = digitalRead(sensorUP);
  valDOWN = digitalRead(sensorDOWN);

  if (valUP == HIGH) {
    colorWipeUP(0x55, 0xFF, 0x00, 2);
    delay(600);
    colorWipeUP(0x00, 0x00, 0x00, 2);
    delay(100);
  }
  if (valDOWN == HIGH) {
    colorWipeDOWN(0x55, 0xFF, 0x00, 2);
    delay(6000);
    colorWipeDOWN(0x00, 0x00, 0x00, 2);
    delay(100);
  }
}

void colorWipeUP(byte red, byte green, byte blue, int SpeedDelay) {
  for (uint16_t i = 0; i < NUM_LEDS; i++) {
    setPixel(i, red, green, blue);
   FastLED.show();
    delay(SpeedDelay);
  }
}
void colorWipeDOWN(byte red, byte green, byte blue, int SpeedDelay) {
  for (uint16_t i = 299; i < NUM_LEDS; i--) {
    setPixel(i, red, green, blue);
    FastLED.show();
    delay(SpeedDelay);
  }
}

void setPixel(int Pixel, byte red, byte green, byte blue) {
  leds[Pixel].r = red;
  leds[Pixel].g = green;
  leds[Pixel].b = blue;
}

void setAll(byte red, byte green, byte blue) {
  for (int i = 0; i < NUM_LEDS; i++ ) {
    setPixel(i, red, green, blue);
  }
  FastLED.show();
}

```

At the moment the LEDs just go on and after a delay off again (one-by-one).

QUESTION: I wish for a little smoother effect by fading them on and off. So i reached the actual output by using different snippets and trying to understand. What i don't understand atm is how to add fading.

# Answer
> 2 votes
Your code is currently written as blocking, so we can leave it that way and add another blocking nested loop. Let's take the `colorWipeUP()` function as example:

```
void colorWipeUP(byte red, byte green, byte blue, int SpeedDelay) {
  for (uint16_t i = 0; i < NUM_LEDS; i++) {
    setPixel(i, red, green, blue);
   FastLED.show();
    delay(SpeedDelay);
  }
}

```

You go through all leds, lighting them up one after another with the provided color, delaying between the LEDs. The brightness of an LED is controlled by the overall RGB value. If you just multiply the RGB components red, green and blue with a number between 0 and 1, you (mostly) keep the color and only control the brightness. For example like this:

```
void colorWipeUP(byte red, byte green, byte blue, int SpeedDelay) {
  for (uint16_t i = 0; i < NUM_LEDS; i++) {
    for(uint8_t brightness = 0; brightness <= 100; brightness++){
      setPixel(i, red*brightness/100, green*brightness/100, blue*brightness/100);
      FastLED.show();
      delay(fadeDelay);
    }
    delay(SpeedDelay);
  }
}

```

For every LED we are now going from zero brightness to 100% brightness in a loop, showing each individual step on the LED strip. `fadeDelay` determines, how fast this fade in should be. You will have to tune both delays to fit your expectations. You can use the same principle for the wipe down.

You may be asking yourself, why I count from 0 to 100 and then dividing by 100 instead of directly counting from 0 to 1 in steps of 0.01. I've done this, because on AVR based microcontrollers you don't have native floating point calculations. This means, that every floating point calculation needs many instructions to execute (because the floating point math is implemented in software instead of hardware). Here I'm counting with integers and when calculating the brightness also only integer math is involved (dividing by 100 is an integer division, which will automatically cut all digits after the decimal point. We don't need them).

Note: With 300 LEDs, the call to `FastLED.show()` will take some time. I haven't tested the code, but depending on your needs the fading might be too slow, even when you remove the delay call. Then you can simply increase the increment of the for loop, for example to use 10 steps instead of 100:

```
for(uint8_t brightness=0; brightness<100; brightness+=10)

```

---

> something like a fade over 10 LEDs

For this I would use a totally different approach. If you view it mathematically, the brightness of each LED is a function of position and time. So we can implement a function much like a mathematical function, that returns the brightness for a given position and a given time. As I understood, you want the a function, that is first constantly zero, then it grows linearly with time and position and then it is constantly full brighntess. We can count the time from the moment, that the sensor is triggered, where we then start with zero brightness and let it rise linearly. Something like this:

```
int fadeBrightness(int position, unsigned long time){
    int brightness = m_p*position+m_t*time;
    if(brightness > 100) return 100;
    if(brightness < 0) return 0;
    return brightness;
}

```

`m_p` and `m_t` are constants, that you would need to define and fine tune. For fading over 10 LEDs, `m_p` has to be `-10`. `time` is provided as milliseconds. I'm currently not sure about the value of `m_t`, but you can simply try some values and use one that's fitting.

Then in your `colorWipeUP()` function you can loop through all LEDs and set their pixel just like in the code above, but this time you use the newly created function.

```
void colorWipeUP(byte red, byte green, byte blue, int SpeedDelay) {
  unsigned long timestamp = millis();
  while(millis()-timestamp < duration){
    for (uint16_t i = 0; i < NUM_LEDS; i++) {
      setPixel(i, red*fadeBrightness(i, millis()-timestamp)/100, green*fadeBrightness(i, millis()-timestamp)/100, blue*fadeBrightness(i, millis()-timestamp)/100);
    }
    FastLED.show();
  }
}

```

You need to define the `duration` according to how long the fading will take with your `m_t`. If you set it longer, the loop will just loop longer, holding the brightness at 100%.

In the function we first create a timestamp from the `millis()` function. Then we loop, while the duration of the effect hasn't passed. In each while loop iteration, we set the color components of each LED pixel with the brightness according to our `fadeBrightness()` function. Then we show this on the LED strip. The function is constantly updating the strip at max speed. The actual speed of the animation is determined by the `fadeBrightness()` function.

This version is also blocking code, but it can easily be transformed to non-blocking code, that you would call repeatedly until the animation is done.

# Answer
> 0 votes
You could do something like this. (not tested)

```
void colorWipeUP(byte red, byte green, byte blue, int SpeedDelay) {
  for (int i = -5; i < NUM_LEDS + 5; i++) {
    setPixel(i    ,      red, green, blue);   // example only
    setPixel(i + 1, .8 * red, green, blue);   // change the green and blue also
    setPixel(i + 2, .6 * red, green, blue);
    setPixel(i + 3, .4 * red, green, blue);   // successive pixels have lower brightness
    setPixel(i + 4, .2 * red, green, blue);
    FastLED.show();
    delay(SpeedDelay);
  }
}

void setPixel(int Pixel, byte red, byte green, byte blue) {

  if (Pixel < 0 || Pixel >= NUM_LEDS) return;        // do not set color of non-existent pixels

  leds[Pixel].r = red;
  leds[Pixel].g = green;
  leds[Pixel].b = blue;
}

```

---
Tags: arduino-nano
---


# Question
Title: 6v between vin and pin even though pin is off
I have a arduino uno and i am trying to make a lightstrip work.
i have made a program for this but when i turn off the pins to make the light strip turn off it still glows.
red the reason is that there is still 6v between vin and the port even though there should be 0v.
here is my code

```
void setup() {
pinMode(13, OUTPUT);
digitalWrite(13, LOW);
}

void loop() {
}

```

any way to fix this

# Answer
> 0 votes
That would be the correct reading. If (LOW) 0 is near GND.
**All your measurements should be from(against) GND**
Never connect any pins into voltage before regulator(V-in) or voltage over 5v (I usualy target 4.6v as MAX voltage to give myself a margin of error) and even that should only be done in the event of input or high (1) mode.
You are lucky if your multi-meter had big enough resistance and did not damage your Arduino yet.
Arduinos pins have no real protection and very little resistance when in output mode.
Even though pro's keep saying that it is pointless I find that when connecting items sensitive to even tiny current using NPN transistor i tend to use pull-down 10K-ish resistor against GND

---
Tags: arduino-uno
---


# Question
Title: A problem with measuring time in a for loop
I am familiar with timing using millis() function, but it seems that I have run into a problem with a for loop. The thing is, I am comparing encoder readings with a value entered via 4x4 keypad. Since I have to enter more than one value, i placed all values from the keypad into an array. Then I created a for loop that will cycle through that array and compare each value with encoder readings, when encoder reached the entered keypad value an LED should light up for 2 seconds. This is where the problem occurs. When it reaches the set value the LED seems to light up for like a fraction of a second. My guess is that the loop is creating some trouble here. Maybe because the loop cycles so fast the LED doesn't have enough time to stay lit. What do you think?

When I tried this program without a for loop (with only one value entered from a keypad), it works fine. The code below has two arrays with values already entered, so no need or keypad. I used it just for testing. When I solve this problem I will add a keypad.

Please ask if you need any clarification of the code , and thank you in advance

```
#include <Encoder.h>
#include<Wire.h>
#include<LiquidCrystal_I2C.h>

int led1=14;
int led2=15;
unsigned long encoder;
unsigned long prev_value;
int array1[]={100, 200, 300, 400, 500, 600};
int array2[]={150, 250, 420};
int i,j,k,l;
int brV=6;
int brM=3;
int tolerance=10;
unsigned long oldTime=0.0;
unsigned long newTime;
int dt=2000;
bool testRange=true;
bool testRange2=true;

Encoder myEnc(2,3);
LiquidCrystal_I2C lcd1(0x27, 16, 2);

void setup() {
pinMode(led1,OUTPUT);
pinMode(led2,OUTPUT);
lcd1.init();
lcd1.backlight();
}

void loop() {
  newTime=millis();
  lcd1.setCursor(0,0);
  encoder=myEnc.read()*446/400;
  if(encoder!=prev_value){
    lcd1.clear();
    delay(10);
    prev_value=encoder;
  }
  lcd1.print(encoder);
  digitalWrite(led1,LOW);
  digitalWrite(led2,LOW);

  k=brV+brM;

  for(l=0;l<k;l++){
     for(i=0;i<brV;i++){
        if(encoder>=array1[i] && encoder<=(array1[i]+tolerance) && testRange){
           oldTime=newTime;
           digitalWrite(led1,HIGH);
           testRange=false;
         }
         else if(oldTime-newTime >= dt){
          oldTime=newTime;
          digitalWrite(led1,LOW);
         }
         if(encoder>(array1[i]+tolerance){
          testRange=true;
         }
     }
      for(j=0;j<brM;j++){
         if(encoder>=array2[j] && encoder<=(array2[j]+tolerance) && testRange2){
           oldTime=newTime;
           digitalWrite(led2,HIGH);
           testRange2=false;
         }
         else if(newTime-oldTime >= dt){
          oldTime=newTime;
          digitalWrite(led2,LOW);
         }
         if(encoder>array2[j]+tolerance){
          testRange2=true;
         }
      }
  }

  }

```

# Answer
> 0 votes
in loop() replace

```
digitalWrite(led1,LOW);

```

with

```
if (newTime - oldTime >= dt){
   digitalWrite(led1,LOW);
}

```

and you can remove the

```
else if(oldTime-newTime >= dt){
   oldTime=newTime;
   digitalWrite(led1,LOW);
}

```

from the `for` loop

# Answer
> 1 votes
Old time and new time are wrong way round on a part where the LED'd are switched off

```
else if(oldTime-newTime >= dt){
          oldTime=newTime;
          digitalWrite(led1,LOW);
         }

```

When simple processors reach the max or min value and continue counting, they overflow and start counting from far end: So **5-8=maxint(largest number)-3** Result is that the difference is a massive number greater then 2000 except every few weeks when millis() overflows and become larger then Unsigned large int can store and starts counting from zero. (many codes fail working on that occasion, your would only works then ;-)
Correct version:

```
else if(newTime-oldTime >= dt){
          oldTime=newTime;
          digitalWrite(led1,LOW);
         }

```

Although I have noticed that testrange (both) only returns its value onto true on limited circumstance if input from encoder increased considerably very quickly to catch-up with growing inputs, so the next values will never pass condition to switch them on

if(encoder\>=array1\[i\] && encoder\<=(array1\[i\]+tolerance) && testRange)

will never return true because testRange stays false. Add

testRange=true; testRange2=true;

at the end of the loop otherwise it does return into true for next loop()iteration. I guess question is if you want other functions to run while LEDs are on or not.

It is a bad habit to make unnecessary variables like i,j,k,l global as they waste memory even when not needed you can define them within structure itself Eg: for(int i=1;... this way as soon as for, while etc loop (brackets close)finishes you get your memory back and you can use variable again

---
Tags: arduino-uno, programming, c
---


title: DC Motor Car Steering

text:
# Question
Title: DC Motor Car Steering
I am working on a project with a 3-Wheel Car: 1 Custer Wheel, and 2 DC Motors. I need to steer the car playing with the speeds of these two dc motors. If I would supply a constant voltage and current to the DC motors, is there an equation or maybe a source to know the exact degree of turning by assigning PWM to a certain value? Let's say I want to turn the car 30 Degrees to the left from the straight direction. Can I do calculations to find all of the PWM values or it can only be got through experiments? Thanks in Advance!

# Answer
Basically you can't. PWM value required to turn to a specific degree will depend on motors, on voltage, on hardware, in the current velocity of the car and probably on the surface under the wheel. Also keep in mind that real cars don't turn like that (at a fixed angle). Instead, driver constantly adjusts the position of the steering wheel, while looking at the road (i.e.a feedback system). Same is for RC cars, operator smoothly deflects the joystick looking at the vehicle.
> 1 votes

---
Tags: motor, pwm, speed
---


# Question
Title: The problem of not saving the previous value when sending it from bluetooth
**Controlling Led's from Buttons and Bluetooth by same method**

**The problem now :**

the LED light up when you send an A over Bluetooth and it will turn off after 2 sec automatically without you doing anything (this is the wrong now in video).

I Want the same char when send data the led turn on and when i want closed led send same char to turn off light .

**The code: bottom this page**

**thank**

this is the wrong now in video

```
 #define CLK 10
 #define CLKI 9
 #define LD 8
 #define SO 11
 #define SER 12

 byte ledstates;
 byte copy=0;
 unsigned long bt_leds_timestamp=0;
 byte bt_leds_activated=0;

 void setup(){
   Serial.begin(9600);
   pinMode(CLK,OUTPUT);
   pinMode(CLKI,OUTPUT);
   pinMode(LD,OUTPUT);
   pinMode(SO,INPUT);
   pinMode(SER,OUTPUT);
  }

 void loop(){
  if (Serial.available()>0){
  message();
 }
  shift_In();
  shift_out(ledstates);

  if(bt_leds_activated && millis()-bt_leds_timestamp > 2000){
  ledstates &= ~bt_leds_activated;
  shift_out(ledstates);
   bt_leds_activated = 0;
  }
 }

 void message(){
  if(Serial.available()){      // Send data only when you receive data:
  char data = Serial.read();        //Read   the incoming data & store into data
  Serial.print(data);          //Print Value inside data in Serial monitor

  switch (data){
  case 'A' :
    bt_leds_activated |= 1;
    break;
  case 'B' :
    bt_leds_activated |= 2;
    break;
  case 'C' :
    bt_leds_activated |= 4;
    break;
  case 'D' :
    bt_leds_activated |= 8;
    break;
  case 'E' :
    bt_leds_activated |= 16;
    break;
  case 'F' :
    bt_leds_activated |= 32 ;
    break;
  case 'G' :
    bt_leds_activated |= 64;
    break;
  case 'H' :
    bt_leds_activated |= 128;
    break;
  default   : return; }
  }
   ledstates |= bt_leds_activated;
   shift_out(ledstates);
   bt_leds_timestamp = millis();
  }

 void shift_out (byte copy){
  digitalWrite(LD, LOW);
  shiftOut(SER,CLK,MSBFIRST,copy);
  digitalWrite(LD, HIGH);
  delay(100);
 }

 void shift_In(){
  digitalWrite(CLKI,HIGH);
  digitalWrite(LD,HIGH);
  digitalWrite(LD,LOW);
  digitalWrite(LD,HIGH);
  digitalWrite(CLK,HIGH);
  digitalWrite(CLKI,LOW);
  byte buttonstates = shiftIn(SO,CLK,MSBFIRST); //read button states in a local variable
  digitalWrite(CLKI,HIGH);
  for(int i=0;i<8;i++){ // loop through all 8 bits of the buttonstates
    if(!(copy & (1<<i)) && (buttonstates & (1<<i))){ // check if old button state (in copy) is zero and new buttonstate is 1 (for the currently check bit)
        ledstates ^= 1<<i; // toggle the corresponding bit in the ledstates variable (will be shifted out later in the loop() function)
    }
  }
  copy = buttonstates;
  delay(10); // delay for debouncing
  }

```

# Answer
C has an "Exclusive Or" operator which is `^`. You can use that instead of `|` so that it toggles the bit rather than always setting it:

```
case 'A' :
    bt_leds_activated ^= 1;
    break;

```

With `^` if you OR a 0 with a 1 you get a 1. If you OR a 0 with a 0 you get a 0. If you OR a 1 with a 1 you get a 0.

That means every time you send `A` bit one of `bt_leds_activated` will invert. If it's 0 it will become 1. If it's 1 it will be come 0.

Also you seem to have two sets of states - the button states, and the bluetooth states. Instead you only want one set of states, and both the buttons and the bluetooth toggle bits in that single state set.

Because of that if *either* of the methods of turning an LED on has turned the LED on then the other method will have no chance at all of turning the LED off.

So just drop `bt_leds_activated` completely and use `ledstates`:

```
case 'A':
    ledstates ^= 1;
    break;

```

Now both the button and the character through bluetooth will toggle the LED.
> 0 votes

---
Tags: arduino-uno, arduino-ide, bluetooth, c, shift-register
---


# Question
Title: Measure lipo voltage while powering arduino
I have a arduino pro micro 5V that I want to power with a 3.7V lipo. I also have a charging module to charge the lipo. (https://www.banggood.com/nl/TP4056-1A-Lipo-Battery-Charging-Board-Charger-Module-Mini-USB-Interface-p-1027027.html?rmmds=myorder&cur\_warehouse=CN).

I want to measure the battery level of the lipo.

* Should I use a step up module to 5V?
* How can I measure it? I read that you can't just use analogRead because the lipo itself is the reference.

Thanks in advance!

# Answer
The reference voltage for analogRead should be from the regulated 5V line, not from the unregulated input to the Arduino.

The real problem is that the voltage out of the battery will drop with current load. You're supposed to measure either the unloaded battery, or under a known, controlled load.

You ask "Should I use a step up module to 5V?" The answer is yes, but that's unrelated to your voltage measurement question. An Arduino requires a source of regulated 5V. The internal voltage regulator is a linear regulator that requires somewhat more than 5V as input (7.5V is about right.) You can't power the internal voltage regulator with a single 3.7V lipo battery. You'd need a step-up regulator, and with that, you could bypass the internal regulator on the Arduino (assuming your step-up regulator puts out 5V.)
> 1 votes

---
Tags: voltage-level, arduino-pro-micro, lipo
---


# Question
Title: What's the relation between arduino standard library and esp8266 library?
Can I only use the Arduino standard library, without touching any esp8266 related header files?

I tried to connect to WiFi , succeeded with `ESP8266WiFi.h` header, but failed with Arduino library `WiFi.h`.

I follow this https://www.arduino.cc/en/Tutorial/ConnectWithWPA WiFi connecting tutorial but the board seems to reboot repeatly (I don't understand the error of course. I know nothing about hardware).

My board is `ESP8266 V3 ESP-12N F NodeMcu Lua CP2102`

# Answer
The WiFi shield and an ESP8266 with any of several popular WiFi services firmwares are different pieces of hardware, each of which can provide WiFi services to another device connected to it, such as an Arduino Uno. Their interfaces are different, despite that they could be used to do similar jobs - offloading the WiFi communications from the Arduino - and the two libraries are written to drive each of them, respectively.
> 2 votes

---
Tags: esp8266
---


# Question
Title: In Linux, how to identify multiple Arduinos connected over USB?
If I have multiple Arduinos connected over USB to a Linux computer, and they show up as

* /tty/ACM0
* /tty/ACM1
* /tty/ACM2

How can I identify which Arduino is which **without connecting to them via serial connection**? Is there a serial number or a unique id on the Arduino?

Thank you for your time.

Situation: Uno R3, Mega, Leonardo with /ttyACM\[1,2,3\]

lsusb output with devices in the order mentioned above:

```
...
Bus 001 Device 011: ID 2341:0043
Bus 001 Device 013: ID 2341:8036
...
Bus 001 Device 014: ID 2341:0042

```

lsusb -d vendor:device -vvv shows for each one

Uno

```
Bus 001 Device 014: ID 2341:0042
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               1.10
  bDeviceClass            2 Communications
  bDeviceSubClass         0
  bDeviceProtocol         0
  bMaxPacketSize0         8
  idVendor           0x2341
  idProduct          0x0042
  bcdDevice            0.01
  iManufacturer           1 Arduino (www.arduino.cc)
  iProduct                2
  iSerial               220 55330313735351910141
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength           62
    bNumInterfaces          2
    bConfigurationValue     1
    iConfiguration          0
    bmAttributes         0xc0
      Self Powered
    MaxPower              100mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         2 Communications
      bInterfaceSubClass      2 Abstract (modem)
      bInterfaceProtocol      1 AT-commands (v.25ter)
      iInterface              0
      CDC Header:
        bcdCDC               10.01
      CDC ACM:
        bmCapabilities       0x06
          sends break
          line coding and serial state
      CDC Union:
        bMasterInterface        0
        bSlaveInterface         1
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0008  1x 8 bytes
        bInterval             255
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass        10 CDC Data
      bInterfaceSubClass      0 Unused
      bInterfaceProtocol      0
      iInterface              0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x04  EP 4 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               1
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x83  EP 3 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               1
Device Status:     0x0000
  (Bus Powered)

```

Leonardo:

```
Bus 001 Device 013: ID 2341:8036
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            0 (Defined at Interface level)
  bDeviceSubClass         0
  bDeviceProtocol         0
  bMaxPacketSize0        64
  idVendor           0x2341
  idProduct          0x8036
  bcdDevice            1.00
  iManufacturer           1 Arduino LLC
  iProduct                2 Arduino Leonardo
  iSerial                 0
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength          100
    bNumInterfaces          3
    bConfigurationValue     1
    iConfiguration          0
    bmAttributes         0x80
      (Bus Powered)
    MaxPower              500mA
    Interface Association:
      bLength                 8
      bDescriptorType        11
      bFirstInterface         0
      bInterfaceCount         2
      bFunctionClass          2 Communications
      bFunctionSubClass       2 Abstract (modem)
      bFunctionProtocol       1 AT-commands (v.25ter)
      iFunction               0
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         2 Communications
      bInterfaceSubClass      2 Abstract (modem)
      bInterfaceProtocol      0 None
      iInterface              0
      CDC Header:
        bcdCDC               1.10
      CDC Call Management:
        bmCapabilities       0x01
          call management
        bDataInterface          1
      CDC ACM:
        bmCapabilities       0x06
          sends break
          line coding and serial state
      CDC Union:
        bMasterInterface        0
        bSlaveInterface         1
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x83  EP 3 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        2
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         3 Human Interface Device
      bInterfaceSubClass      0 No Subclass
      bInterfaceProtocol      0 None
      iInterface              0
        HID Device Descriptor:
          bLength                 9
          bDescriptorType        33
          bcdHID               1.01
          bCountryCode            0 Not supported
          bNumDescriptors         1
          bDescriptorType        34 Report
          wDescriptorLength     101
          Report Descriptor: (length is 101)
            Item(Global): Usage Page, data= [ 0x01 ] 1
                            Generic Desktop Controls
            Item(Local ): Usage, data= [ 0x02 ] 2
                            Mouse
            Item(Main  ): Collection, data= [ 0x01 ] 1
                            Application
            Item(Local ): Usage, data= [ 0x01 ] 1
                            Pointer
            Item(Main  ): Collection, data= [ 0x00 ] 0
                            Physical
            Item(Global): Report ID, data= [ 0x01 ] 1
            Item(Global): Usage Page, data= [ 0x09 ] 9
                            Buttons
            Item(Local ): Usage Minimum, data= [ 0x01 ] 1
                            Button 1 (Primary)
            Item(Local ): Usage Maximum, data= [ 0x03 ] 3
                            Button 3 (Tertiary)
            Item(Global): Logical Minimum, data= [ 0x00 ] 0
            Item(Global): Logical Maximum, data= [ 0x01 ] 1
            Item(Global): Report Count, data= [ 0x03 ] 3
            Item(Global): Report Size, data= [ 0x01 ] 1
            Item(Main  ): Input, data= [ 0x02 ] 2
                            Data Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Global): Report Count, data= [ 0x01 ] 1
            Item(Global): Report Size, data= [ 0x05 ] 5
            Item(Main  ): Input, data= [ 0x03 ] 3
                            Constant Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Global): Usage Page, data= [ 0x01 ] 1
                            Generic Desktop Controls
            Item(Local ): Usage, data= [ 0x30 ] 48
                            Direction-X
            Item(Local ): Usage, data= [ 0x31 ] 49
                            Direction-Y
            Item(Local ): Usage, data= [ 0x38 ] 56
                            Wheel
            Item(Global): Logical Minimum, data= [ 0x81 ] 129
            Item(Global): Logical Maximum, data= [ 0x7f ] 127
            Item(Global): Report Size, data= [ 0x08 ] 8
            Item(Global): Report Count, data= [ 0x03 ] 3
            Item(Main  ): Input, data= [ 0x06 ] 6
                            Data Variable Relative No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Main  ): End Collection, data=none
            Item(Main  ): End Collection, data=none

            ......

      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x84  EP 4 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               1
Device Status:     0x0000
  (Bus Powered)

```

And Mega256:

```
Bus 001 Device 014: ID 2341:0042
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               1.10
  bDeviceClass            2 Communications
  bDeviceSubClass         0
  bDeviceProtocol         0
  bMaxPacketSize0         8
  idVendor           0x2341
  idProduct          0x0042
  bcdDevice            0.01
  iManufacturer           1 Arduino (www.arduino.cc)
  iProduct                2
  iSerial               220 55330313735351910141
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength           62
    bNumInterfaces          2
    bConfigurationValue     1
    iConfiguration          0
    bmAttributes         0xc0
      Self Powered
    MaxPower              100mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         2 Communications
      bInterfaceSubClass      2 Abstract (modem)
      bInterfaceProtocol      1 AT-commands (v.25ter)
      iInterface              0
      CDC Header:
        bcdCDC               10.01
      CDC ACM:
        bmCapabilities       0x06
          sends break
          line coding and serial state
      CDC Union:
        bMasterInterface        0
        bSlaveInterface         1
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0008  1x 8 bytes
        bInterval             255
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass        10 CDC Data
      bInterfaceSubClass      0 Unused
      bInterfaceProtocol      0
      iInterface              0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x04  EP 4 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               1
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x83  EP 3 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               1
Device Status:     0x0000
  (Bus Powered)

```

# Answer
Assuming your distro is using `udev`:

```
udevadm info --query=all --name=/dev/ttyACM0

```

You might need root privileges to run this(sudo / su). It will output a list of information like this:

```
P: /devices/pci0000:00/0000:00:1d.2/usb4/4-2/4-2:1.0/tty/ttyACM0
N: ttyACM0
S: serial/by-id/usb-Dean_Camera_LUFA_USB-RS232_Adapter_74133353537351403012-if00
S: serial/by-path/pci-0000:00:1d.2-usb-0:2:1.0
E: DEVLINKS=/dev/serial/by-id/usb-Dean_Camera_LUFA_USB-RS232_Adapter_74133353537351403012-if00 /dev/serial/by-path/pci-0000:00:1d.2-usb-0:2:1.0
E: DEVNAME=/dev/ttyACM0
E: DEVPATH=/devices/pci0000:00/0000:00:1d.2/usb4/4-2/4-2:1.0/tty/ttyACM0
E: ID_BUS=usb
E: ID_MM_CANDIDATE=1
E: ID_MODEL=LUFA_USB-RS232_Adapter
E: ID_MODEL_ENC=LUFA\x20USB-RS232\x20Adapter
E: ID_MODEL_FROM_DATABASE=Uno R3 (CDC ACM)
E: ID_MODEL_ID=0043
E: ID_PATH=pci-0000:00:1d.2-usb-0:2:1.0
E: ID_PATH_TAG=pci-0000_00_1d_2-usb-0_2_1_0
E: ID_REVISION=0001
E: ID_SERIAL=Dean_Camera_LUFA_USB-RS232_Adapter_74133353537351403012
E: ID_SERIAL_SHORT=74133353537351403012
E: ID_TYPE=generic
E: ID_USB_DRIVER=cdc_acm
E: ID_USB_INTERFACES=:020201:0a0000:
E: ID_USB_INTERFACE_NUM=00
E: ID_VENDOR=Dean_Camera
E: ID_VENDOR_ENC=Dean\x20Camera
E: ID_VENDOR_FROM_DATABASE=Arduino SA
E: ID_VENDOR_ID=2341
E: MAJOR=166
E: MINOR=0
E: SUBSYSTEM=tty
E: UDEV_LOG=3
E: USEC_INITIALIZED=751387324986

```

This is for an Uno with modified firmware on the atmega16u2(usb to serial). The lines of interest are probably ID\_MODEL\_ID and ID\_MODEL\_FROM\_DATABASE.
> 7 votes

# Answer
On Ubuntu 16.04 (and maybe previous versions or other distribs too), you can do:

```
> ls /dev/serial/by-id

```

which displays (on my box where an Arduino UNO is connected):

```
usb-Arduino__www.arduino.cc__0043_A4139363931351318241-if00

```

You can easily spot the Device ID 0043 (UNO) here.

This file is actually a link to `/dev/ttyACM0` in my box.
> 6 votes

# Answer
You can add an alias for each. Then you know which is which. Here is a nice tutorial on how to set this up.

Here is a snippet that I wrote based on the tutorial. In the below example, I am using a FTDI RS232RL USB to Serial adapter, which I believe is what the Arduino uses too.

1. In order to assign an alias to a USB-Serial device, we need to find some info on the device
2. Plug in the usb. This assumes you have already install the drivers for this use be device and the device is visible when typing:

`lsusb`

3. We are going to need the following a. The vendor id b. The product id c. The device serial number
4. To do this, it takes a little bit of hunting. All your devices log entries in '/var/log/messages'.

Therefore we can read this file and find the correct USB:

```
grep "ftdi" /var/log/messages

```

You can also use "usb"

5. This is find all messages tagged with ftdi:
6. Next to ftdi\_sio, there is a number like 1-1.2. This is the USB device

`grep "usb 1-1.2" /var/log/messages`

Or you can use:

```
dmesg | grep "usb 1-1.3"

```
7. This gives us all the info we need:

8. Now with the list of serial numbers in hand let’s create a UDEV ruleset that’ll make a nice symbolic link for each of these devices. UDEV rules are usually scattered into many files in /etc/udev/rules.d. Create a new file called 99-usb-serial.rules and put the following lines in there:

In this example my alias is called 'lcdbox'

```
SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", ATTRS{serial}=="A601ERJJ", SYMLINK+="lcdbox"

```
9. SYMLINK is the name of your alias. In this case my alias is lcdbox.
10. Save the file and type

sudo udevadm control --reload-rules
11. Type

ls –l /dev/lcdbox

lrwxrwxrwx 1 root root 7 Jan 1 1970 /dev/lcdbox -\> ttyUSB0

12. This shows that my lcdbox alias is mapped to ttyUSB0
> 5 votes

# Answer
This is quite easy! You have to customize the ftdi chips firmware and add an udev rule:

First, get `ftdi_eeprom` via `apt-get` or from the sources. Identify your device via lsusb and get the id:

```
lsusb

Bus 001 Device 005: ID 0403:6001 Future Technology Devices International, Ltd FT232 Serial (UART) IC
....

```

Prepare a config and make sure, that `vendor_id` and `product_id` match. Customize the strings in the `Strings` section to get a unique id for your device.

```
vendor_id=0x0403    # Vendor ID
product_id=0x6001   # Product ID

max_power=50        # Max. power consumption: value * 2 mA. Use 0 if self_powered = true.

###########
# Strings #
###########
manufacturer="FTDI"     # Manufacturer
product="Arduino Nano"      # Product
serial="arduino1"       # Serial

###########
# Options #
###########
self_powered=false  # Turn this off for bus powered
remote_wakeup=false # Turn this on for remote wakeup feature
use_serial=true     # Use the serial number string

# Normally out don't have to change one of these flags
# BM_type_chip=true         # Newer chips are all BM type
in_is_isochronous=false     # In Endpoint is Isochronous
out_is_isochronous=false    # Out Endpoint is Isochronous
suspend_pull_downs=false    # Enable suspend pull downs for lower power
change_usb_version=false    # Change USB Version
usb_version=0x0200      # Only used when change_usb_version is enabled

########
# Misc #
########

filename="eeprom.old"   # Filename, leave empty to skip file writing
cbus0=RXLED#
cbus1=TXLED#

```

Dump the current ftdi-firmware:

`ftdi_eeprom --read-eprom`

This command creates `${pwd}/eeprom.old`, which contains the current firmware on the ftdi. **Backup** this file **before continuing**, because during `flash-eeprom` the file gets rewritten. After the backup, flash the ftdi:

```
ftdi_eeprom --flash-eeprom myconfig.conf

```

Now, create an udev rule, like so

```
SUBSYSTEMS=="usb", ATTRS{idProduct}=="6001", ATTRS{idVendor}=="0403", SYMLINK+="$attr{serial}", OWNER="bananapi", GROUP="pi", MODE="0777"

```

in `/etc/udev/rules.d/90-arduino-usb.rules` and restart udev.

```
service udev restart

```

Unplug and re-plug your device and try

```
ls -lah /dev/arduino1

```

Where `arduino1` is the string defined under `serial` in the above `.conf`.

See also: Risks of ftdi\_eeprom? - TX always high after flashing
> 4 votes

# Answer
I would have used a script to make an alias under `/dev/` and also set group and rights on it with `udev` like the other answers.

But if I didn't have `udev` I would pipe `lsusb` into `grep` or `awk`, like `lsusb|grep -e "idProduct"`.

Anyway, with `udev` rules or with `lsusb` and `grep` to identify USB devices, use `idVendor`, `idProduct` and `iSerial` in `Device descriptor` part of `lsusb` to make the proper idenification. The `idVendor` tells you the manufaturer, `idProduct` should indentify the product from the manufacturer but sometimes they use the same product id for more than one product. Lastly, if needed, the `iSerial` should be a unique id for each example of that product.
> 3 votes

# Answer
You can always make some kind of id print via serial in void setup(). After the certain board is connected it will send this id to your USB interface (which you are listening with some kind of daemon app on your linux box). Once you receive id you can map it to it's path 'Arduino1' : '/dev/ttyACM0', 'Arduino2' : '/dev/ttyACM1', 'Arduino3' : '/dev/ttyACM2'...etc

Be aware that when device is disconnected for some reason it can change it's physical path so you might have to remap all of them. For this case it might be good to write separate function ex: get\_id() which you can call any time (not only on startup).
> 2 votes

# Answer
I'd be mighty tempted to identify some other way, like having the sketch itself respond to a special identify command, just to avoid USB's odd ways of identifying devices.
> 1 votes

# Answer
## Overview

* One way as ansi\_lumen mentioned in his answer is to flash ftdi chip EEPROM to have unique serial number which then could be identified by UDEV rules.

But turns out it *won't work on cheap chinese Arduinos* which instead of FTDI has CH340G chip which doesn't have EEPROM to store unique ID (CH340B should work).
* This answer suggests to write UDEV rule with special script which asks Arduino to send its unique ID via serial. Problem with that is that you need to modify Arduino sketch and in general it's quite complex.

## Identifying by port

So the easiest way I found was to use UDEV rules and identify Arduinos by the usb port (devpath) so connecting Arduino to the same port (even in nested usb hubs) will create persistent name.

**TLDR setup:**

Modified version of this

1. Find Arduino idVendor and idProduct:

`lsusb`

You will get something like this:

```
...
Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 003 Device 124: ID 1a86:7523 QinHeng Electronics HL-340 USB-Serial adapter
Bus 003 Device 123: ID 214b:7000
Bus 003 Device 122: ID 1a86:7523 QinHeng Electronics HL-340 USB-Serial adapter
Bus 003 Device 121: ID 1a86:7523 QinHeng Electronics HL-340 USB-Serial adapter
Bus 003 Device 120: ID 1a40:0101 Terminus Technology Inc. Hub
...

```

By connecting/disconnecting Arduino find which one it is (I have 3 connected). We are looking for its ID. In my case "...ID 1a86:7523 QinHeng...". So idVendor=1a86, idProduct=7523

2. Create new UDEV rules file:

`sudo nano /etc/udev/rules.d/99-usb-serial.rules`

3. Modify idVendor and idProduct values by what you found in previous step on copy paste it in the rules file we have created:

`SUBSYSTEM=="tty", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", SYMLINK+="ttyUSB-arduino%s{/devpath}"`

4. Reload UDEV rules

`sudo udevadm control --reload`

5. Replug Arduinos and now it will have unique name. To test it type:

`ls /dev/ttyUSB*`

---

Which will output:

`/dev/ttyUSB1 /dev/ttyUSB3 /dev/ttyUSB-arduino2.1 /dev/ttyUSB-arduino2.4
 /dev/ttyUSB2 /dev/ttyUSB4 /dev/ttyUSB-arduino2.2 /dev/ttyUSB-arduino3`

As you can see we still get /dev/ttyUSBx as before which are always changing depending which one was connected first. But now we also have /dev/ttyUSB-arduino{port} which are always the same for same port and only for Arduinos. To analyze what "..arduino2.4" means: 2 refers to the second port of laptop and 4 to the fourth port on usb hub.

To better see it type:

```
lsusb -t

```

Output:

```
...
/:  Bus 03.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/4p, 480M
    |__ Port 1: Dev 5, If 0, Class=Human Interface Device, Driver=usbhid, 12M
    |__ Port 1: Dev 5, If 1, Class=Human Interface Device, Driver=usbhid, 12M
    |__ Port 2: Dev 84, If 0, Class=Hub, Driver=hub/4p, 480M
        |__ Port 1: Dev 85, If 0, Class=Vendor Specific Class, Driver=ch341, 12M
        |__ Port 2: Dev 86, If 0, Class=Vendor Specific Class, Driver=ch341, 12M
        |__ Port 3: Dev 87, If 0, Class=Hub, Driver=hub/4p, 480M
        |__ Port 4: Dev 88, If 0, Class=Vendor Specific Class, Driver=ch341, 12M
    |__ Port 3: Dev 89, If 0, Class=Vendor Specific Class, Driver=ch341, 12M
/:  Bus 02.Port 1: Dev 1, Class=root_hub, Driver=ehci-pci/2p, 480M
    |__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/6p, 480M
...

```

By connecting/disconnecting you can see which devices are on which ports
> 1 votes

---
Tags: linux
---


# Question
Title: What is difference between NodeMCU and esp8266?
Since I have no previous experience in electronics I'm getting quite confused while coming across these two terms ..I'd like to know whether they're the same or different.

# Answer
> 8 votes
From https://forum.arduino.cc/index.php?topic=616324.0:

> NodeMcu is the name of the firmware originally for the ESP8266 microcontroller, with support for the ESP32 microcontroller added more recently, that allows you to program these microcontrollers using the Lua programming language.
>
> NodeMCU firmware was developed so that AT commands can be replaced with Lua scripting making the life of developers easier. So it would be redundant to use AT commands again in NodeMCU.

And ESP8266 is one of the microcontrollers supported by the NodeMcu firmware.

From NodeMcu vs Esp32 vs esp8266

> In the early days of the hobbyist community's adoption of the ESP8266, ESP8266 development boards were marketed with the name NodeMcu and the term "NodeMcu" started to be associated more with the hardware than the firmware. It is common for people with no interest in the Lua programming language to buy "NodeMcu" boards and program them with the Arduino IDE, which erases the NodeMcu firmware from the board. To make things more confusing, multiple companies marketed boards with the name "NodeMcu", but with small hardware differences. Over time, the NodeMcu boards became less popular in the Arduino world because the similarly priced WeMos D1 Mini came out with the same functionality, but in a smaller form factor. Now, the "NodeMcu" name is being used to market ESP32 boards as well.

# Answer
> 9 votes
ESP8266 is a microcontroller with WiFi capability. it requires external flash memory and some antenna to work. There are different modules and development boards with this system. Some development boards use basic esp8266 modules and some integrate the chip, flash memory and the antenna on the PCB.

NodeMcu is a development board with esp8266 and a firmware with the same name. On the picture is a NodeMcu development board with an esp-12F esp8266 module soldered to the PCB of the NodeMcu. The development board adds required circuits around the module - boot configuration pull-up and pull-down and enable pin pull-up. On the board is an USB chip to connect the esp8266 to USB and an auto reset circuit to enable the upload tool to put the esp8266 into flashing mode. The 3.3 V power for the esp8266 is converted from the 5 V of USB.

The NodeMcu firmware is a Lua language interpreter and has nothing to do with Arduino, but the NodeMcu development board can be used as any other esp8266 development board.

---
Tags: esp8266, nodemcu
---


title: What is the real lifetime of EEPROM?

text:
# Question
Title: What is the real lifetime of EEPROM?
ATMEL says the cell lifetime of an EEPROM cell is about 100,000 write cycle/ cell. Is this actually how the EEPROM performs in the wild?

If I do not change the value of a cell, does this stress the lifetime? For example, if I write the value `0xFF` to the same cell again and again, is this any different to writing `0x00`, `0xFF`, `0x00` etc.

# Answer
As you state, the internal EEPROM has a lifetime of 100,000 write cycles. This isn't a guess - a very significant proportion of ATmega328 will reach this number with no issues. I have tested three processors before, and all reached 150,000 cycles with no issues.

It is important to note the failure mode of EEPROM. Most "EEPROM destroyer" projects repeatedly read/write until the data is not written at all. Before this point, the EEPROM will still be damaged. This would be manifested by data not being retained for a reasonable period. It is unwise to rely on anything more than 100,000 write cycles for this reason.

EEPROM is different to the RAM on an ATmega. Writing to it is not simple or quick, but it is wrapped up in a friendly Arduino library, hiding this complexity from the user.

The first level of indirection is the EEPROM library, which is trivially simple\], just calling two other functions for read and write. This calls eeprom\_write\_byte, found here.

This function uses inline assembly, so might not be easily understood. There is a comment that is easily understood though:

> Set programming mode: erase and write

This hints to one of the complexities of dealing with EEPROM - to write to it, you first need to erase it. This means that if you call EEPROM.write(), it will perform a write cycle regardless of the value you are writing.

This means that repeatedly writing 0xFF will likely have the same effect as writing 0xFF,0x00,0xFF,0x00 etc.

There are ways to work around this - you can try calling EEPROM.read() before EEPROM.write() to see if the value is already the same, but this takes additional time.

There are other techniques to avoid excessive EEPROM wear, but their use depends on your application.
> 23 votes

# Answer
I once ran an experiment on an external EEPROM with 1 million max rated cycles. It took about 6 million cycles to become majorly corrupted, and before that it had progressed having sporadic amounts of corruption.

When you say you do not change the value, i am assuming you are writing the same data to an address multiple times. This almost certainly would stress the life, although it would probably not stress the surrounding cells.
> 10 votes

# Answer
The magic solution - if you dont want to code what Cybergibbons said about reading before writing, is the EEPROM.update() function. It does exactly that:

EEPROM.update(address, value);

will only write and stress the memory if value is different from that already stored.
> 4 votes

# Answer
http://hackaday.com/2011/05/16/destroying-an-arduinos-eeprom/

> The Arduino was plugged into a wall wart and sat, “behind a couch for a couple of months.” The EEPROM saw it’s first write error after 47 days and 1,230,163 cycles. This is an order of magnitude better than the spec on the atmel datasheet, but similar to the results of similar experiments.
> 2 votes

# Answer
Couple years ago I made run time logger for piece of equipment. Memory got corrupted after 6 months 40 hours logged with 1s resolution =\> 144000 writes. My solution was to spread writes over entire eeprom.
> 1 votes

---
Tags: eeprom
---


# Question
Title: Trying to read different gas levels with MQ2 Gas Sensor
I found a link on how to connect MQ-2 Gas Sensor to Arduino Uno.

http://electronicsprojectshub.com/how-to-connect-mq2-gas-sensor-to-arduino/

After I bought all the parts and tried it out, the sensor gave me this in the serial monitor

> Ro: 10.81 kohm
>
> LPG:0.00ppm CO:0.00ppm SMOKE:0.00ppm
>
> LPG:0.00ppm CO:0.00ppm SMOKE:0.00ppm

and so on.

Here is the code I used

```
#include <MQ2.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16,2);
int Analog_Input = A0;
int lpg, co, smoke;
MQ2 mq2(Analog_Input);

void setup(){
  pinMode(A0, INPUT);
  Serial.begin(9600);
  lcd.begin();
  lcd.backlight();
  mq2.begin();
}

void loop(){
  float* values= mq2.read(true);
  //lpg = values[0];
  lpg = mq2.readLPG();
  //co = values[1];
  co = mq2.readCO();
  //smoke = values[2];
  smoke = mq2.readSmoke();

  lcd.setCursor(0,0);
  lcd.print("LPG:");
  lcd.print(lpg);
  lcd.print(" CO:");
  lcd.print(co);
  lcd.setCursor(0,1);
  lcd.print("SMOKE:");
  lcd.print(smoke);
  lcd.print(" PPM");
  delay(1000);
}

```

Please help me fix it so that it can perform just the same as the video. Thanks.

# Answer
First this should be like this:

```
float* values= mq2.read(false); //false

```

and then write this to be printed in the serial monitor

```
Serial.print('\n');
  Serial.print("LPG:");
  Serial.print(lpg);
  Serial.print(" CO:");
  Serial.print(co);

  Serial.print('\n');
  Serial.print("SMOKE:");
  Serial.print(smoke);
  Serial.print(" PPM");
  Serial.print('\n');

```
> 1 votes

---
Tags: arduino-uno, sensors, library, pins
---


# Question
Title: Want to create bluetooth audio control (volume up/down, play, pause, etc.) for smartphone
I want to create a bluetooth remote audio control to control smartphone audio, essentially identical in function to this type of equipment:

https://www.amazon.com/FAVOLCANO-Bluetooth-Button-Smartphone-Samsung/dp/B01C5E95XG/ref=pd\_lpo\_147\_bs\_t\_1?ie=UTF8&refRID=1GRBCPDRMD9YPYPGK73Y

This device is simply a bluebooth remote control which allows you to play or pause audio, skip forward or backward and change media volume on the smart phone.

All of the Arduino tutorials I see are about either using the iPhone to control a bluebooth device, or about using bluetooth to control an arduino, neither of which are what I want to do.

Can you point me in the right direction?

# Answer
> 15 votes
Bluetooth supports multiple protocols for multiple purposes. There is low latency low quality monorail bi-directional communication with a little bit of bandwidth for control for Bluetooth phone calls. This is called HFE Bluetooth protocol. If you are interfacing a keyboard or a mouse you would use the Human Interface Device protocol or HID. If you wanted to listen to music and control it's playback you would use the high latency high quality 2 audio sending channels (stereo) no return audio channel with a little bit of bandwidth for controlling playback called Advanced Audio Distribution Profile or A2DP.

In this specific case we are only interested in controlling playback. So we could use the HID Bluetooth protocol. However, the native music players on the platform you are using (Android or iPhone) likely will not be listening to such a device. In order for this to work you will probably have to write your own Android or iPhone music player.

On the other hand, it is likely the native music players will work with A2DP Bluetooth protocol. Unfortunately, it is also suspected that once the A2DP Bluetooth connection is established, the phone's speaker will be shutdown and all audio will be diverted to the Bluetooth connection.

Finally, there is the Audio/Video Remote Control Profile or AVRCP. This protocol is used to control media playback. There are several versions of this protocol so what features are available for a given device / music-application may vary greatly.

# Answer
> 4 votes
I can add something to @st2000's excellent answer (in a better format than our discussion in the comments there).

The original question is vague. Does Bluetooth mean Classic or is Low Energy (BLE) acceptable or preferred. Which smartphones must be supported? Apple and/or Android? And what minimum version must be supported?

The 2.5 years that have passed since this question was asked makes it easier to choose BLE because adoption is so prevalent now.

I've been researching what it would take to implement a media control device as described in the original post. My target smartphone is Android Nougat. My goal is to skip podcast commercials. I have tested using a Bluetooth Classic keyboard. The media control buttons, Play/Pause, skip forward, skip back, etc. seem to do what I need.

I'd prefer to use BLE's support for keyboards and other Human Interface Devices: HID over Gatt Profile (HOGP). The KitKat release notes say that's when HID over GATT support was added, so it's been around for a while.

Having decided on a Bluetooth LE profile, device selection remains. Adafruit Bluefruit LE UART Friend has a HIDKeyboard example. I prefer an MCU with integrated BLE support. While total overkill for this application, I have an ESP32 that I plan to use for this. It has good community support and is cheap. If battery life (or size) becomes a problem, I'll look for a lesser device.

# Answer
> 2 votes
I did it on HC-05 (reflash to RN-42) and use HID profile to send command: Play/pause fwd/rwd vol+/- I can post sample code if needed. Here's the video https://youtu.be/y8PcNbAA6AQ

---
Tags: bluetooth, audio, remote-control
---


title: Slow speed with stepping motor

text:
# Question
Title: Slow speed with stepping motor
I am currently working on a project where I need a stepping motor and a servo running at the same time, the servo turns fine and the speed is ok, but the stepping motors speed is very slow and as a result it is loud. I tried the code for the stepping motor on its own and it runs faster, but when it is ran with the servo it is slow. I have follwed a few tutorials to get this to the stage it is at currently, I have removed any delays that i could find which did help a little, but it is still not enough.

The servo is powered from the arduino and the stepping motor is powered by a 12v plug. I am just not sure if there is something within this code that is causing it to slow down? Thank you for you time! The code that it is running slow from is here:

```
#include <Servo.h>

Servo myservo;

// Configurable Variables
int MaxServoTurn = 20;

// Spooky Variables
int pos = 0;
int customDelay;
int customDelayMapped;
const int pin_LED = 10;
const int pin_switch = 8;
const int stepPin = 3;
const int dirPin = 4;
boolean oldSwitchState = LOW;
boolean newSwitchState1 = LOW;
boolean newSwitchState2 = LOW;
boolean newSwitchState3 = LOW;
unsigned long timeNow = 0;
unsigned long timePrev = 0;
unsigned int timeWait = 100;
boolean flashingLEDisON = false;
boolean LEDstatus = LOW;
boolean keyPressed = false;
boolean buttonToggle = false;

// Setup only, call functions in here
void setup() {
  myservo.attach(9);
  //Sets the two pins as Outputs
  pinMode(stepPin, OUTPUT);
  pinMode(dirPin, OUTPUT);
  //Enables the motor to move in a particular direction
  digitalWrite(dirPin, HIGH);
  pinMode(pin_LED, OUTPUT);
  digitalWrite(pin_LED, LOW);
  pinMode(pin_switch, INPUT);
}

// This is the main controller for the application
void loop() {
  for (pos = 0; pos <= MaxServoTurn; pos += 1) {
    buttonLoop();
    if (buttonToggle == true) {
      myservo.write(pos);
      setupPotentiometer();
    }
  }
  for (pos = MaxServoTurn; pos >= 0; pos -= 1) {
    buttonLoop();
    if (buttonToggle == true) {
      myservo.write(pos);
      setupPotentiometer();
    }
  }
}

void buttonLoop() {
  newSwitchState1 = digitalRead(pin_switch);
  newSwitchState2 = digitalRead(pin_switch);

  newSwitchState3 = digitalRead(pin_switch);

  if (  (newSwitchState1 == newSwitchState2) && (newSwitchState1 == newSwitchState3) )
  {
    if ( newSwitchState1 != oldSwitchState )
    {
      if ( newSwitchState1 == HIGH ) {
        keyPressed = true;
        buttonToggle = true;
      } else {
        keyPressed =  false;
        buttonToggle = false;
      }
      oldSwitchState = newSwitchState1;
    }
  }

  if ( keyPressed )
  {
    // turn on or turn off the blinking LED
    if ( flashingLEDisON == false)
    {
      flashingLEDisON = true;
    }
    else
    {
      flashingLEDisON = false;
      // the LED may be on so to be safe we turn it off. If you wished you could check LEDstatus
      LEDstatus = LOW;  digitalWrite(pin_LED, LEDstatus);
    }
    keyPressed = false;
  }

  // if the blinking LED is on. See if it is time to blink it
  if ( flashingLEDisON == true )
  {
    timeNow = millis();
    if (timeNow - timePrev >= timeWait )
    {
      timePrev = timeNow;
      if (LEDstatus == LOW) {
        LEDstatus = HIGH;
      } else {
        LEDstatus = LOW;
      }
      digitalWrite(pin_LED, LEDstatus);
    }
  }
}

void setupPotentiometer() {
  customDelayMapped = speedUp(); // Gets custom delay values from the custom speedUp function
  // Makes pules with custom delay, depending on the Potentiometer, from which the speed of the motor depends
  digitalWrite(stepPin, HIGH);
  delayMicroseconds(customDelayMapped);
  digitalWrite(stepPin, LOW);
  delayMicroseconds(customDelayMapped);
}

// Function for reading the Potentiometer
int speedUp() {
  int customDelay = analogRead(A0); // Reads the potentiometer
  int newCustom = map(customDelay, 0, 1023, 300, 4000); // Convrests the read values of the potentiometer from 0 to 1023 into desireded delay values (300 to 4000)
  return newCustom;
}

```

# Answer
> 1 votes
I had a project where I needed to run two steppers at the same time as they were moving a heavy load and were moving the same piece.

While a servo is going to move the desired spot, a stepper will not.

In the process of setting up the stepper you designated steps per rev and amount of steps to take at a time.

The stepper is only going to move the "amount of steps" at a time for each run of the code. I ran into a similar problem and I had to put in a 2ms delay after the servo run command to make the motors run smoother and faster, other wise it sounded like a bunch of gears gnashing and skipping. These steppers were facing each other that is why they move opposite directions.

```
if (down==true){
  TLstep.step(-step1);
  TRstep.step(step1);
  delay(2);
}

```

I know it been a year since this was looked at. Hope you got your issue figured out.

# Answer
> 0 votes
A stepper motor requires that you send pulsed control signals to it for each step. If you want it to run at a given number of steps/second, you have to send the controlling pulses at the correct time intervals.

If you have delays in your code, it will slow down the timing of the control pulses, and slow down your steppers. You need to rewrite your code to use millis() to calculate the timing of your control signals instead of using `delay()` or `delayMicroseconds()`

---
Tags: motor, servo, stepper
---