# Question
Title: Access Control System with an 4x3 Keypad & RFID-RC522
hey guys I have a access control system working perfect with rfid and keypad.

I would like to implement : If the PIN is entered more than 3 times incorrectly the card is disabled.

someone could give a help or a tip?

here is my code: https://pastiebin.com/5e4c315d97d5e

```
#include <Keypad.h>                 // This sketch uses the Keypad.h library
#include <SPI.h>                    // This sketch uses the SPI.h library
#include <MFRC522.h>                // This sketch uses the MFRC522.h library

#define SS_PIN 10                   // Define SS_PIN of the RC522 RFID Reader to digital pin 10 of the Arduino
#define RST_PIN 9                   // Define RST_PIN of the RC522 RFID Reader to digital pin 9 of the Arduino
MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance.

int RedLed    = A3;                 // Red LED output is analog pin A3
int GreenLed  = A4;                 // Green LED output is analog pin A4
int Buzzer    = A5;                 // Buzzer output is analog pin A5
unsigned long Timer;                // Variable for the Timer

const byte ROWS = 4;                // Four rows
const byte COLS = 3;                // Three columns

char Keys[ROWS][COLS] = {           // Define the symbols on the buttons of the keypads
  {'1','2','3',},
  {'4','5','6',},
  {'7','8','9',},
  {'*','0','#',}
};

byte rowPins[ROWS] = {5, 4, 3, 2};  // Connect to the row pinouts of the keypad
byte colPins[COLS] = {8, 7, 6};     // Connect to the column pinouts of the keypad
Keypad keypad = Keypad( makeKeymap(Keys), rowPins, colPins, ROWS, COLS); // Initialize an instance of class NewKeypad

int RightCard;                      // Variable for a known Mifare Card
int RightPinCode;                   // Variable for valid key input in combination with a known Mifare Card
int WrongPinCode;                   // Variable for a invalid key input in combination with a known Mifare Card
int PinCodeCounter;                 // Variable Counter for counting the number of pincode inputs on the keypad

int Code1Correct;                   // Variable for the first correct digit (Code) input on the keypad
int Code2Correct;                   // Variable for the second correct digit (Code) input on the keypad
int Code3Correct;                   // Variable for the third correct digit (Code) input on the keypad
int Code4Correct;                   // Variable for the fourth correct digit (Code) input on the keypad
int Code5Correct;                   // Variable for the fifth correct digit (Code) input on the keypad
int Code6Correct;                   // Variable for the sixth correct digit (Code) input on the keypad
int Reset;                          // Reset for the loop

int MifareCard1;                               // We need this specific variable to determine the valid PinCode in combination with the UID nummer of the Mifare Card
const int Code1MifareCard1 = '6';              // Determine here the first digit of your 6 digit PIN
const int Code2MifareCard1 = '6';              // Determine here the second digit of your 6 digit PIN
const int Code3MifareCard1 = '6';              // Determine here the third digit of your 6 digit PIN
const int Code4MifareCard1 = '2';              // Determine here the fourth digit of your 6 digit PIN
const int Code5MifareCard1 = '2';              // Determine here the fifth digit of your 6 digit PIN
const int Code6MifareCard1 = '2';              // Determine here the sixth digit of your 6 digit PIN

int MifareCard2;                               // We need this specific variable to determine the valid PinCode in combination with the UID nummer of the Mifare Card
const int Code1MifareCard2 = '1';              // Determine here the first digit of your 6 digit PIN
const int Code2MifareCard2 = '1';              // Determine here the second digit of your 6 digit PIN
const int Code3MifareCard2 = '1';              // Determine here the third digit of your 6 digit PIN
const int Code4MifareCard2 = '3';              // Determine here the fourth digit of your 6 digit PIN
const int Code5MifareCard2 = '3';              // Determine here the fifth digit of your 6 digit PIN
const int Code6MifareCard2 = '3';              // Determine here the sixth digit of your 6 digit PIN

void setup()

{
  Serial.begin(9600);                                     // Initialize serial communications with the PC
  SPI.begin();                                            // Initialize the SPI bus
  mfrc522.PCD_Init();                                     // Initialize the MFRC522
  pinMode (RedLed, OUTPUT);                               // Define RedLed as OUTPUT
  pinMode (GreenLed, OUTPUT);                             // Define GreenLed as OUTPUT
  pinMode (Buzzer, OUTPUT);                               // Define Buzzer as OUTPUT
}

void loop() {

//----------------------------------------------Code for the reset function of the loop--------------------------------------------------------------------------------------------------------

if (Reset == 1)                                           // If Reset has value 1 (HIGH) all variables will be reset to 0 and the RC522 RFID reader will be waiting for a new Mifare Card.
{
  RightCard = 0;
  MifareCard1 = 0;
  MifareCard2 = 0;
  RightPinCode = 0;
  WrongPinCode = 0;
  Code1Correct = 0;
  Code2Correct = 0;
  Code3Correct = 0;
  Code4Correct = 0;
  Code5Correct = 0;
  Code6Correct = 0;
  PinCodeCounter = 0;
  delay (50);
  Reset = 0;
}

//----------------------------------------------Code for the control for a valid pincode within the timelimit of 7 seconds after presenting/offering a valid Mifare Card ---------------------------

if (millis()- Timer > 7000 && RightCard == 1)            // If the Timer will be larger as 7 seconds and a valid Mifare Card is offered, reset value will be high.
   {                                                     // This means that you have after presenting a valid card, 7 seconds to enter a valid code or the loop resets.
    Reset = 1;
    Serial.println("CardAccesOff");
   }

//----------------------------------------------Reading the presented/offered Mifare Card at the MFRC522 -----------------------------------------------------------------------------------------

if   (mfrc522.PICC_IsNewCardPresent() &&
      mfrc522.PICC_ReadCardSerial())
    {

//----------------------------------------------Code for detect the first Mifare Card in the Database. This is a UID number with 4 pairs of digits. Example: 69 7C 01 9C------------------------------------
     if
     (mfrc522.uid.uidByte[0] == 0x69   &&                // Fill in the first digits of the UID number of your Mifare card
      mfrc522.uid.uidByte[1] == 0x7C   &&                // Fill in the seconds digits of the UID number of your Mifare card
      mfrc522.uid.uidByte[2] == 0x01   &&                // Fill in the third digits of the UID number of your Mifare card
      mfrc522.uid.uidByte[3] == 0x9C)                    // Fill in the fourth digits of the UID number of your Mifare card

     {
      RightCard = 1;                                     // The offered Mifare Card is known in the database, set variable "RightCard" to 1
      MifareCard1 = 1;                                   // This Mifare Card is known as Mifare Card 2 in the Database, so set variable MifareCard2 to value 1.
      digitalWrite (Buzzer, HIGH);                       // Make a beep for the accepted Mifare Card
      delay (150);                                       //
      digitalWrite (Buzzer, LOW);                        //

      PinCodeCounter = 0;                                // Reset the PinCodeCounter to 0
      Timer =  millis();                                 // Reset the Timer. The 7 seconds limit is running now for a valid PinCode
      Serial.println("CardAccesOn");                     // Print the text "CardAccesOn" to the serial monitor
      delay (200);                                       // Wait 200 milliseconds
      }

//-----------------------------------------------Code for detect the second Mifare Card in the Database. This is a UID number with 4 pairs of digits. Example: EB 70 C0 BC----------------------------------------------
     if
     (mfrc522.uid.uidByte[0] == 0xEB   &&                 // Fill in the first digits of the UID number of your Mifare card
      mfrc522.uid.uidByte[1] == 0x70   &&                 // Fill in the seconds digits of the UID number of your Mifare card
      mfrc522.uid.uidByte[2] == 0xC0   &&                 // Fill in the third digits of the UID number of your Mifare card
      mfrc522.uid.uidByte[3] == 0xBC)                     // Fill in the fourth digits of the UID number of your Mifare card

    {
      RightCard = 1;                                       // If the offered Mifare Card is known in the database, set variable "RightCard" to 1
      MifareCard2 = 1;
      digitalWrite (Buzzer, HIGH);                         // Make a beep for the accepted Mifare Card
      delay (150);                                         //
      digitalWrite (Buzzer, LOW);                          //

      PinCodeCounter = 0;                                  // Reset the PinCodeCounter to 0
      Timer =  millis();                                   // Reset the Timer. The 7 seconds limit is running now for a valid PinCode
      Serial.println("CardAccesOn");                       // Print the text "CardAccesOn" to the serial monitor
      delay (200);                                         // Wait 200 milliseconds
    }

    }

//-----------------------------------------------Code for accepting a valid MifareCard + valid PinCode-------------------------------------------------------------------------------------------------

if (Code6Correct == 1 && RightCard == 1)                    // If the PinCode is the correct and you did enter this within 7 seconds
  {
    RightPinCode = 1;                                       // Variable RightPinCode will be set to 1

    digitalWrite (GreenLed, HIGH);                          // Make a nice beep for the correct Pincode and set the Green LED high for 1 second
    delay (150);                                            //
    digitalWrite (Buzzer, HIGH);                            //
    delay (150);                                            //
    digitalWrite (Buzzer, LOW);                             //
    delay (50);                                             //
    digitalWrite (Buzzer, HIGH);                            //
    delay (150);                                            //
    digitalWrite (Buzzer, LOW);                             //
    delay (500);                                            //
    digitalWrite (GreenLed, LOW);                           //

    Serial.println("Correct PinCode");                      // Print the text "Correct PinCode" to the serial monitor
    Reset = 1;                                              // Reset the loop
  }

//-----------------------------------------------Code for refusing a valid MifareCard + invalid PinCode------------------------------------------------------------------------------------------------

if ((Code6Correct == 0) && (PinCodeCounter >= 6) && (RightCard == 1))       // If you offered a valid Mifare Card and the Pincode is not correct and you already entered 6 digitkeys
  {
    WrongPinCode = 1;                                                       // Variable WrongPinCode will be set to 1
    Serial.println("WrongCode");                                             // Print the text "WrongKey" to the serial monitor
    Reset = 1;                                                              // Reset the loop
  }

//-----------------------------------------------Code for refusing a Wrong/Invalid PinCode or the Timer (7seconds) expired----------------------------------------------------------------------------

if ((WrongPinCode == 1) || (millis()- Timer > 7000 && RightCard == 1))      // If you offered a valid Mifare Card and  you entered a wrong PinCode or the timer (7 seconds) expires
  {
    digitalWrite (Buzzer, HIGH);                                            // Make a long beep and set the Red LED HIGH for the wrong code or timer expiry
    digitalWrite (RedLed, HIGH);                                           //
    delay(1500);                                                            //
    digitalWrite (Buzzer, LOW);                                             //
    digitalWrite (RedLed, LOW);                                             //

    Serial.println("WrongCode or Timer expired");                           // Print the text "WrongCode or Timer expired" to the serial monitor
    Reset = 1;                                                              // Reset the loop
  }

//-----------------------------------------------Code for counting the inputs on the keypad----------------------------------------------------------------------------------------------------------

char KeyDigit = keypad.getKey();                                           // Get the DigitKey from the keypad

if ((RightCard == 1) &&                                                    // If you offered a valid Mifare Card and any DigitKey on the keypad is pressed
    ((KeyDigit == '1') ||
    (KeyDigit == '2')  ||
    (KeyDigit == '3')  ||
    (KeyDigit == '4')  ||
    (KeyDigit == '5')  ||
    (KeyDigit == '6')  ||
    (KeyDigit == '7')  ||
    (KeyDigit == '8')  ||
    (KeyDigit == '9')  ||
    (KeyDigit == '0')  ||
    (KeyDigit == '*')  ||
    (KeyDigit == '#')))

    {
      PinCodeCounter++;                                                       // PinCodeCounter value +1 for every press on any Digitkey on the keypad
      digitalWrite (Buzzer, HIGH);                                            // Make a short beep for a DigitKey press on the keypad
      delay (50);                                                             //
      digitalWrite (Buzzer, LOW);                                             //
    }

//-----------------------------------------------Code for determine the correct PinCode for MifareCard1----------------------------------------------------------------------------------------------------------

if ((KeyDigit == Code1MifareCard1) && (RightCard == 1) && (Code1Correct == 0) && (MifareCard1 == 1))           // If you offered the valid MifareCard1, first PinCode and you did not entered it before (Otherwise we conflict with same KeyDigits)
    {
      Code1Correct = 1;                                                                                // Variable Code1Correct is set to 1
      return;                                                                                // Return to begin loop
    }

if ((KeyDigit == Code2MifareCard1) && (Code1Correct == 1) && (Code2Correct == 0) && (MifareCard1 == 1))        // If you offered the valid MifareCard1, second PinCode and you did not entered it before (Otherwise we conflict with same KeyDigits)
    {
      Code2Correct = 1;                                                                                // Variable Code2Correct is set to 1
      return;                                                                                // Return to begin loop
    }

if ((KeyDigit == Code3MifareCard1) && (Code2Correct == 1) && (Code3Correct == 0) && (MifareCard1 == 1))         // If you offered the valid MifareCard1, third PinCode and you did not entered it before (Otherwise we conflict with same KeyDigits)
    {
      Code3Correct = 1;                                                                                // Variable Code3Correct is set to 1
      return;                                                                                // Return to begin loop
    }

if ((KeyDigit == Code4MifareCard1) && (Code3Correct == 1) && (Code4Correct == 0) && (MifareCard1 == 1))         // If you offered the valid MifareCard1, fourth PinCode and you did not entered it before (Otherwise we conflict with same KeyDigits)
    {
      Code4Correct = 1;                                                                                // Variable Code4Correct is set to 1
      return;                                                                                // Return to begin loop
    }
if ((KeyDigit == Code5MifareCard1) && (Code4Correct == 1) && (Code5Correct == 0) && (MifareCard1 == 1))         // If you offered the valid MifareCard1, fifth PinCode and you did not entered it before (Otherwise we conflict with same KeyDigits)
    {
      Code5Correct = 1;                                                                                // Variable Code5Correct is set to 1
      return;                                                                                // Return to begin loop
    }

if ((KeyDigit == Code6MifareCard1) && (Code5Correct == 1) && (Code6Correct == 0) && (MifareCard1 == 1))         // If you offered the valid MifareCard1, sixth PinCode and you did not entered it before (Otherwise we conflict with same KeyDigits)
    {
      Code6Correct = 1;                                                                                // Variable Code6Correct is set to 1
      return;                                                                                // Return to begin loop
    }

//-----------------------------------------------Code for determine the correct PinCode for MifareCard2----------------------------------------------------------------------------------------------------------

if ((KeyDigit == Code1MifareCard2) && (RightCard == 1) && (Code1Correct == 0) && (MifareCard2 == 1))              // If you offered a the valid MifareCard2, first PinCode and you did not entered it before (Otherwise we conflict with same KeyDigits)
    {
      Code1Correct = 1;                                                                                // Variable Code1Correct is set to 1
      return;                                                                                // Return to begin loop
    }

if ((KeyDigit == Code2MifareCard2) && (Code1Correct == 1) && (Code2Correct == 0) && (MifareCard2 == 1))           // If you offered a the valid MifareCard2, second PinCode and you did not entered it before (Otherwise we conflict with same KeyDigits)
    {
      Code2Correct = 1;                                                                                // Variable Code2Correct is set to 1
      return;                                                                                // Return to begin loop
    }

if ((KeyDigit == Code3MifareCard2) && (Code2Correct == 1) && (Code3Correct == 0) && (MifareCard2 == 1))           // If you offered a the valid MifareCard2, third PinCode and you did not entered it before (Otherwise we conflict with same KeyDigits)
    {
      Code3Correct = 1;                                                                                // Variable Code3Correct is set to 1
      return;                                                                                // Return to begin loop
    }

if ((KeyDigit == Code4MifareCard2) && (Code3Correct == 1) && (Code4Correct == 0) && (MifareCard2 == 1))          // If you offered a the valid MifareCard2, fourth PinCode and you did not entered it before (Otherwise we conflict with same KeyDigits)
    {
      Code4Correct = 1;                                                                                // Variable Code4Correct is set to 1
      return;                                                                                // Return to begin loop
    }
if ((KeyDigit == Code5MifareCard2) && (Code4Correct == 1) &&  (Code5Correct == 0) && (MifareCard2 == 1))         // If you offered a the valid MifareCard2, fifth PinCode and you did not entered it before (Otherwise we conflict with same KeyDigits)
    {
      Code5Correct = 1;                                                                                // Variable Code5Correct is set to 1
      return;                                                                                // Return to begin loop
    }

if ((KeyDigit == Code6MifareCard2) && (Code5Correct == 1) &&  (Code6Correct == 0) && (MifareCard2 == 1))         // If you offered a the valid MifareCard2, sixth PinCode and you did not entered it before (Otherwise we conflict with same KeyDigits)
    {
      Code6Correct = 1;                                                                                // Variable Code6Correct is set to 1
      return;                                                                                // Return to begin loop
    }

}

```

thank you very much.

# Answer
Add `int passCount = '0';` to the top of your file and then increment that value by one every time the wrong password gets entered (For example replace `Reset = 1;` with `passCount ++;` on line 199) And add `passCount = '0'` to your reset on line 85. And add another if statement to reset loop if password has been entered more than 3 times. `if (passCount == 3) {Reset = 1;}`

Hope this helps :-)

EDIT:

You can comment out/delete the If statement on lines 222 - 232 `if ((WrongPinCode == 1) || (millis()- Timer > 7000 && RightCard == 1))`.

And add your Buzzer and Led code to the if statement above (same statement with `passCount ++;` in it) The timeout reset will be take care of code on lines 108 - 112.
> 2 votes

# Answer
1.initialize a global variable `int failcount=0,MiFareCardMode=0;`

2. for reset put it in an if statement that checks fail count
<pre><code>   if(failcount==0)
                {reset code}```
</code></pre>
3. in this piece of code increase the failcount number(line 195:200) also add an if statement to check which card was detected initialize a global variable to set the card status MiFareCardMode(0=unblocked,1=card1 block,2=card2 block)

```
if ((Code6Correct == 0) && (PinCodeCounter >= 6) && (RightCard == 1))
  {
    WrongPinCode = 1;
    Serial.println("WrongCode");
    Reset = 1;
    failcount++       ///here increase the value with each wrong password
    if (failcount>=3)
     {   if(MifareCard1==1)
              MifareCardMode=1; ///create a variable for mode (blocked OR non blocked)
         if(MiFareCard2==1)
               MifareCardMode=2;
}
 failcount=0; }

```

4.In lines 125:142 put them in an if statement which check the variable MiFareCardMode

```
       if(MiFareCardMode==0)
                 {
                    lines 125 to 142
                    }
         if(MiFareCardMode==1)
                   { Serial.println("Card 1 blocked permanently");
                    //add anything you want to do after blocking }

```

4.In lines 146:163 put them in an if statement which check the variable MiFareCardMode for card 2

```
    if(MiFareCardMode==0)
          {   lines 146:163  }
    if(MiFareCardMode==2)
           {Serial.println("Card2 blocked permanently");}

```
> 1 votes

# Answer
Your code written more complex, than it has to be, and you have much repeated code, that makes it harder to understand and change the code. So I will first describe, how to shorten and generalize your code. That will make it easier to implement new features, like invalidating a card after 3 wrong PIN entries.

* **Handling the RFID cards:** Currently you are using single variables for each card (for example `RightCard`). Your if statements all have to reference these single variables for each card, which makes it hard to not write repeated code. Instead you should use arrays to store the information. See this piece of code:

```
#define MAX_CARD_N        2
#define SERIAL_LENGTH     4
uint8_t card_serials[MAX_CARD_N][SERIAL_LENGTH] = {
    {0x69, 0x7C, 0x01, 0x9C},
    {0xEB, 0x70, 0xC0, 0xBC}
};

#define PIN_LENGTH        6
char card_pins[MAX_CARD_N][PIN_LENGTH] = {
    {'6','6','6','2','2','2'},
    {'1','1','1','3','3','3'}
};

int current_card = -1;
uint8_t current_pin_position = 0;
bool pin_correct = true;

```

What happens here? First we set defines for later use, where we can centrally set the number of cards, that we want to use, and the length of their serial data. Then we declare a 2 dimensional array, which stores the serial for each card (for example in a loop). We can now access the serials of the cards by simple integer indices. Then we do the same with the PINs of these cards. (And declare variables for holding the current card index, the current pin position and the correctness of the pin for later use.) We can implement a function, that will give us the index of the currently scanned card in our card arrays:

```
int find_card(){
    if(mfrc522.uid.uidByte[0] == 0x00) return -1;
    for(uint8_t card_index=0; card_index < MAX_CARD_N; card_index++){
        uint8_t found_card_flag = 1;
        for(uint8_t serial_index=0; serial_index < SERIAL_LENGTH; serial_index++){
            if(card_serials[card_index][serial_index] != mfrc522.uid.uidByte[serial_index]){
                found_card_flag = 0;
                break;
            }
       }
       if(found_card_flag){
           return card_index;
       }
   }
   return -1;
}

```

This function will return -1, if the scanned card serial can not be found in our `card_serials` array. If it was found, the function returns the index of the card. I also added an if statement at the start, that forbids to find cards with the first element being zero, which will come in handy at a later time (I only used the first element here for making it easy, but you can also check every of the 4 serial bytes, if you want to forbid zeros everywhere in the serial).
* **Organizing your code:** Currently you have many individual if statements, which all need extra variables, so that you can execute the right code at the right situation. A better approach for something like this is a Finite State Machine (FSM). It is an important concept, that sound more difficult, than it is. Basically you divide your code into different states, where specific things should happen. Actions or specific situations can do a transition to a different state. Every state only executes it's own code. The current state is held in a variable, called state variable. In my answer to this question I already explained the principle in detail (including some graphs). You should really learn this principle; it changed my coding style completely for better.

I would use 2 different states: `WAIT_FOR_CARD` and `WAIT_FOR_PIN`, so that we can seperate the RFID and the keypad code. Look at this piece of code:

```
enum State {WAIT_FOR_CARD, WAIT_FOR_PIN};
State state = WAIT_FOR_CARD;

void loop() {
    switch(state){
      case WAIT_FOR_CARD:
          if(mfrc522.PICC_IsNewCardPresent() &&
             mfrc522.PICC_ReadCardSerial()){
              int scanned_card = find_card();
              if(scanned_card != -1){
                  current_card = scanned_card;
                  current_pin_position = 0;
                  code_correct = true;
                  // Insert code for correct card in here (buzzer, setting timestamp, ...)
                  state = WAIT_FOR_PIN;
              } else {
                  // Insert code for incorrect card in here
              }
          }
          break;
      case WAIT_FOR_PIN:
          char KeyDigit = keypad.getKey();
          if(KeyDigit != NO_KEY){
            if(KeyDigit != card_pins[current_card][current_pin_position]) pin_correct = false;
            current_pin_position++;
            if(current_pin_position >= PIN_LENGTH){
                if(pin_correct){
                    // Insert code for correct pin in here
                } else {
                    // Insert code for wrong pin in here
                }
                current_card = -1;
                state = WAIT_FOR_CARD;
            }
          }
          break;
    }
}

```

We first define our states as an `enum`, since this makes the code more readable. Then we declare a state variable from that `enum`. In the `loop()` function we use a `switch case` statement to execute the code corresponding to the current state. In the `WAIT_FOR_CARD` state, we are constantly scanning for a new card. If we found one, we check with the `find_card()` function, if we have the serial of this card saved in our array. If yes, we set our variables accordingly, execute the needed code for a valid card and then set the state variable to the next state. The `break` will get us out of the switch statement, but on the next loop iteration, we are now executing the other case (since we changed the state variable). We are now constantly checking for a pressed key. If the pressed key was not the one defined in our PIN array for the current position, we set `pin_correct` to `false` (If every key is correct, it will stay `true`. If any is incorrect, it will get set to `false`). We increment the PIN position and then check if we reached the end of the PIN, where we decide, if the PIN was correct or not, doing the appropriate things, and at the end reset our `current_card` variable and the state variable. (I left out the timeout feature. When you have understood the FSM principle, it should be easy to add this to the code.)

This code is better structured and way shorter. Also it can easily handle extensions (more cards, other functions,...). You can add more states and transitions to insert new features.
* **Disabling cards on 3 wrong pin entries:** I assume, that you want, that 3 incorrect PIN entries will disable the RFID card, so that it is no longer accepted as valid. For that you could remove the corresponding serial from the `card_serials` array. First we need to track the number of consecutive wrong PIN entries. For that I would use another array and a define for the max number of wrong entries (here 2, since 2 wrong entries are still allowed; the third wrong entry will trigger the invalidation of the card):

```
uint8_t pin_strikes[MAX_CARD_N] = {0};
#define MAX_STRIKES    2

```

When we have a wrong PIN, you can increment this counter by 1:

```
pin_strikes[current_card]++;

```

When we have a correct PIN, we want to reset this counter:

```
pin_strikes[current_card] = 0;

```

After incrementing in the case of a wrong PIN we can check, how many times the pin was already wrong consecutively, and then remove the serial, if it was too much:

```
if(pin_strikes[current_card] > MAX_STRIKES){
    for(uint8_t i=0; i < SERIAL_LENGTH; i++) card_serials[current_card][i] = 0;
    current_card = -1;
}

```

We should reset the `current_card` variable here, since this index doesn't point to a valid card anymore. We can invalidate the card by setting the serial to zero, since we ruled out all card with a zero in the first byte at the start of the `find_card()` function.
> 1 votes

---
Tags: arduino-uno, arduino-ide, rfid
---


# Question
Title: First time arduino attempt. 4 switch inputs controlling 8 LED outputs
This is my first venture into Arduino. I am unsure which one to use even for this. As this will be a dedicated unit, and size is a small priority, the smaller the better.

Here is more info on the scheme I am looking for.

Switch 1 on turns on LED groups 1 and 2

Switch 2 on turns on LED groups 3, 4, 5, 6, 7 and 8

Switch 3 on turns on 1 for say 500 ms, then turns 1 off, turns on 3 for 500 ms, then turns off 3, then turns on 5 for 500 ms, then turns off 5, turns on 7 for 500 ms, then turns off 7, then loops back and turns on 1 repeating the cycle.

Switch 4 on turns on 2 for say 500 ms, then turns 2 off, turns on 4 for 500 ms, then turns off 4, then turns on 6 for 500 ms, then turns off 6, turns on 8 for 500 ms, then turns off 8, then loops back and turns on 2 repeating the cycle.

Will I need an Arduino uno, nano or micro? I am hoping this will be an easy to do project in order to learn the world of Arduino

# Answer
> 1 votes
Micheal well easy solution is to use arduino nano as its bread board friendly and easy as it comes with the arduino IDE installed, well if size is what you are looking for then digispark attiny 85 can also do the task and its size is almost equal to a coin but for that youll need to install it in the arduino IDE which is a bit difficult. if you need any help with attiny 85 you can come here

# Answer
> 1 votes
First of all, you need to have an overview over the whole project because you need to know what components you are going to use, how many digital/analog pins do you need, then check the official Arduino website to see if the board fulfills your needs.

If there is no special need, like more EEPROM or more analog inputs, almost most of the board will work for you (because most of them have the same microcontroller: ATMEGA328P), so it is up to what form factor you prefer more.

Personally, I would like to go with the Micro board because it has microusb connector, it is breadboard friendly (which is a big plus when you are prototyping) and it can be recognised as a mouse or keyboard.

---
Tags: led, led-strip
---


title: Problem with PWM pins on Arduino uno

text:
# Question
Title: Problem with PWM pins on Arduino uno
I am working on an Arduino Uno Project of a car with two motors. The motor driver board is an L9110 H-Bridge. Here is how everything is connected:

And here is the code I am trying to run:

```

//Define all the pins for the motors
#define motorPinA1 3  //A pin right motor
#define motorPinB1 5  //B pin right motor
#define motorPinA2 6 //A pin left motor
#define motorPinB2 9 //B pin left motor

//Movement functions
void stopCar();
void frwrd(int motorSpdRight, int motorSpdLeft);
void back(int motorSpdRight, int motorSpdLeft);

//Global Variables
int motorSpeedRight = 0;  //The speed of the right motor
int motorSpeedLeft = 0;   //The speed of the left motor

void setup() {
  //Movement
  pinMode(motorPinA1, OUTPUT);
  pinMode(motorPinB1, OUTPUT);
  pinMode(motorPinA2, OUTPUT);
  pinMode(motorPinB2, OUTPUT);

  //Serial Monitor for debugging
  Serial.begin(9600);

  motorSpeedLeft = 100;
  motorSpeedRight = 100;

  frwrd(100, 100);
  delay(2000);
  stopCar();
  delay(1000);

  back(100, 100);
  delay(2000);
  stopCar();
  delay(1000);
}

void loop() {

  Serial.print("Forward");
  Serial.print("\n");

  frwrd(motorSpeedRight, motorSpeedLeft);
  delay(2000);
  stopCar();
  delay(1000);

  back(motorSpeedRight, motorSpeedLeft);
  delay(2000);
  stopCar();
  delay(1000);

}

// functions we need to make the code run
void stopCar(){
    Serial.print("Stoping Car\n");
    // Put motor 1 in halt
    analogWrite(motorPinA1, 0);
    analogWrite(motorPinB1, 0);

    // Put motor 2 in halt
    analogWrite(motorPinA2, 0);
    analogWrite(motorPinB2, 0);
}

// For the farward direction A pins will be high
void frwrd(int motorSpdRight, int motorSpdLeft){
    // Put motor 1 (Right) in forward motion with speed = motor_spd
    analogWrite(motorPinA1, motorSpdRight);
    analogWrite(motorPinB1, 0);

    // Put motor 2 (Left) in forward motion with speed = motor_spd
    analogWrite(motorPinA2, motorSpdLeft);
    analogWrite(motorPinB2, 0);

    /*
    // Put motor 1 (Right) in forward motion
    digitalWrite(motorPinA1, HIGH);
    digitalWrite(motorPinB1, LOW);

    // Put motor 2 (Left) in forward motion
    digitalWrite(motorPinA2, HIGH);
    analogWrite(motorPinB2, LOW);
    */
}

// For the backward direction B pins will be high
void back(int motorSpdRight, int motorSpdLeft){
    // Put motor 1 (Right) in backward motion with speed = motor_spd
    analogWrite(motorPinA1, 0);
    analogWrite(motorPinB1, motorSpdRight);

    // Put motor 2 (Left) in backward motion with speed = motor_spd
    analogWrite(motorPinA2, 0);
    analogWrite(motorPinB2, motorSpdLeft);

    /*
    // Put motor 1 (Right) in backward motion
    digitalWrite(motorPinA1, LOW);
    digitalWrite(motorPinB1, HIGH);

    // Put motor 2 (Left) in backward motion
    digitalWrite(motorPinA2, LOW);
    digitalWrite(motorPinB2, HIGH);
    */
}

```

Pins 3, 5, 6 and 9 are PWM so I can `alalogWrite()` to them and control the speed of the motors. Code uploads fine but although both motors move forward normally motor 1 (on pins 3, 5) doesn't move backward. The strange thing is that if I use `digitalWrite` (the commented code in the two functions) instead everything works normally but the motors move in full speed so it's not usable for my project. I have tested all the pins in other projects and everything worked fine so I know my board is not faulty.

I have also taken some measurements with a multimeter while the code was running. In the forward motion, both pairs of pins measured 1.95V. In the backward motion, the problematic pins measured 0V.

Any help would be appreciated!!

# Answer
> 1 votes
Try different pins than 5 and 6, because those PWM generators share the timer with `delay()`, which I'd interpret as: You use `analogWrite()` to set the timer to fire every n microseconds to toggle your PWM signal -- and then you call `delay(1000)`, which sets that same timer to fire in one second to continue the program.

Pins 10 and 11 do use a different timer, so try these.

Reference: https://www.arduino.cc/reference/en/language/functions/analog-io/analogwrite/

> "The PWM outputs generated on pins 5 and 6 will have higher-than-expected duty cycles. This is because of interactions with the millis() and delay() functions, which share the same internal timer used to generate those PWM outputs."

---
Tags: pwm, arduino-motor-shield
---


# Question
Title: Bluetooth OBD2 ELM327 connectivity issues
I made a little project using an Arduino UNO, a 3.5" display, a HC-05 bluetooth module and an ELM327 (cheap ebay clone). I managed to establish communication, read the data, interpret and display it, but only one problem remains that keeps bothering me.

After some exchanges of data between Arduino and the OBD2 adapter, communication just drops. I don't know if its from the HC-05 or ELM327. As far as I could debug it, the data from ELM327 comes incomplete. Usually the response from it, transformed into chars, is like "0103141 03 02 00 \>" and I use the "\>" char in the program as data exchange complete. When the problem occurs I receive fewer bytes from the OBD adapter and without the "\>" char, something like "0103141 03 ".

I made a function that resets the HC-05 module and reconnects, but it takes a few seconds and I want my data to come as a continuous flow.

I tried a few methods of debugging, such as changing baud rate of the HC-05, and adding some delays, but I haven't come to a solution.

I believe that the problem might me one of these three:

1. The cheap ebay clone messing things up.
2. The HC-05 not sending the complete data.
3. A problem with my code.

Below I have attached the part of the code that does the sending of the command and reading the response. When the problem occurs, it gets stuck in the while loop because I have no terminating "\>" char and I have to break it, call another function that re-establishes communication and so on.

So my question is: has anyone confronted this problem where ELM327 sends incomplete data that cannot be used?

```
 BTSerial.println("010F1");
 BTSerial.flush();
 delay(10);
  if (BTSerial.available()>0)
      busy = true;
  while(busy = true && inData != 62)
  {
      temp++;
      if (temp>500000){
          resetBT();
          BTSerial.println("ATWS");
          break;
      }
      if (BTSerial.available()>0){
          inData=0;
          inData = BTSerial.read();
          if(inData != 32) {
              buf[i] = inData;
              Serial.print(char(buf[i]));
              i++;
          }

      }

  }
Serial.println();
busy=false;
inData = 0;
i = 0;
memset(buf, 0, sizeof(buf));
temp = 0;

```

# Answer
I managed to solve the issue. After some more testing, I ended up noticing that the problem was somehow the data exchange through the HC-05 bluetooth module. I changed it from being via SoftwareSerial library to the main serial com port and I had no issues since then. I don't know how that library may have caused the problem, but that was it.
> 1 votes

# Answer
You can much more easily interface your Arduino with an ELM327 in software with the library ELMduino.h. It's downloadable through the Arduino IDE and includes examples.
> 1 votes

---
Tags: bluetooth, softwareserial, hc-05
---


# Question
Title: Getting wdt reset + reboots every 5 seconds on simple button/relay code that has worked previously, now it does not and I changed nothing
I have some arduino code I adapted from a simple 2 button 2 relay code I found online. I just multiplied everything so I could have 5 buttons/5relays. I am using a NodeMCU (ESP-12E) for this.

I have not changed anything, and now trying to upload it to other boards, and the same existing board I used before. Same results every time.

I have verified arduino is updated, the board manager link is up to date, and verified the code. Drivers re-installed. I have tried using different boards such as nodemcu 0.9, generic esp8266 module etc. Code is verified, no error messages upon upload.

But every single time I get this error in the serial monitor over and over:

```

 ets Jan  8 2013,rst cause:4, boot mode:(3,6)

wdt reset
load 0x4010f000, len 1392, room 16
tail 0
chksum 0xd0
csum 0xd0
v3d128e5c
~ld

```

And here is the code I am using: (But please keep in mind this WORKS and has worked before)

```
//Buttons

int button1 = 4;
int button2 = 13;
int button3 = 12;
int button4 = 15;
int button5 = 10;

//Relays
int rl1 = 5;
int rl2 = 0;
int rl3 = 14;
int rl4 = 16;
int r15 = 9;

//States for Relay and Button (1)

int state1 = HIGH;      // the current state of the output pin
int reading1;           // the current reading from the input pin
int previous1 = LOW;    // the previous reading from the input pin

//States for Relay and Button (2)

int state2 = HIGH;      // the current state of the output pin
int reading2;           // the current reading from the input pin
int previous2 = LOW;    // the previous reading from the input pin

//States for Relay and Button (3)

int state3 = HIGH;      // the current state of the output pin
int reading3;           // the current reading from the input pin
int previous3 = LOW;    // the previous reading from the input pin

//States for Relay and Button (4)

int state4 = HIGH;      // the current state of the output pin
int reading4;           // the current reading from the input pin
int previous4 = LOW;    // the previous reading from the input pin

//States for Relay and Button (5)

int state5 = HIGH;      // the current state of the output pin
int reading5;           // the current reading from the input pin
int previous5 = LOW;    // the previous reading from the input pin

// the follow variables are long's because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long time1 = 0;          // the last time the output pin was toggled
long time2 = 0;
long time3 = 0;
long time4 = 0;
long time5 = 0;

long debounce1 = 60;   // the debounce time, increase if the output flickers
long debounce2 = 60;
long debounce3 = 60;
long debounce4 = 60;
long debounce5 = 60;

void setup()
{
  pinMode(button1, INPUT);
  pinMode(button2, INPUT);
  pinMode(button3, INPUT);
  pinMode(button4, INPUT);
  pinMode(button5, INPUT);

  pinMode(rl1, OUTPUT);
  pinMode(rl2, OUTPUT);
  pinMode(rl3, OUTPUT);
  pinMode(rl4, OUTPUT);
  pinMode(r15, OUTPUT);

}

void loop() {

  reading1 = digitalRead(button1);
  reading2 = digitalRead(button2);
  reading3 = digitalRead(button3);
  reading4 = digitalRead(button4);
  reading5 = digitalRead(button5);

  // if the input just went from LOW and HIGH and we've waited long enough
  // to ignore any noise on the circuit, toggle the output pin and remember
  // the time
  //Condition Relay 1
  if (reading1 == HIGH && previous1 == LOW && millis() - time1 > debounce1) {
    if (state1 == HIGH)
      state1 = LOW;
    else
      state1 = HIGH;

    time1 = millis();
  }

  //Condition Relay 2
    if (reading2 == HIGH && previous2 == LOW && millis() - time2 > debounce2) {
    if (state2 == HIGH)
      state2 = LOW;
    else
      state2 = HIGH;

    time2 = millis();
  }

  //Condition Relay 3
    if (reading3 == HIGH && previous3 == LOW && millis() - time3 > debounce3) {
    if (state3 == HIGH)
      state3 = LOW;
    else
      state3 = HIGH;

    time3 = millis();
  }

  //Condition Relay 4
    if (reading4 == HIGH && previous4 == LOW && millis() - time4 > debounce4) {
    if (state4 == HIGH)
      state4 = LOW;
    else
      state4 = HIGH;

    time4 = millis();
  }

  //Condition Relay 5
    if (reading5 == HIGH && previous5 == LOW && millis() - time5 > debounce5) {
    if (state5 == HIGH)
      state5 = LOW;
    else
      state5 = HIGH;

    time5 = millis();
  }

  digitalWrite(rl1, state1);
  digitalWrite(rl2, state2);
  digitalWrite(rl3, state3);
  digitalWrite(rl4, state4);
  digitalWrite(r15, state5);

  previous1 = reading1;
  previous2 = reading2;
  previous3 = reading3;
  previous4 = reading4;
  previous5 = reading5;
}

```

If I google this error I get a myriad of results that so far have not helped me. Any help or insight on how I can better understand this error, where to start, and what I need to do to get this "simple" sketch working would be awesome. I'm at my wits end and all I want is a simple lighting panel to work.

# Answer
> 0 votes
For anyone that has a similar issue, I figured it out. GPIO 9 could not be used for a relay/output for whatever reason. Wish I knew why. Switched it to GPIO2 (D4) and the reboots stopped.

# Answer
> 0 votes
First thing to realize for you is that the externally set status of three of the GPIO pins determine the boot mode for the ESP8266 used on your NodeMCU. So you must take care to check that your external wiring will not interfere with the boot mode:

* GPIO15/D8 must be LOW on boot (i.e. no external pull-up resistors may be connected between D8 and 3.3V)
* GPIO2/D4 must be HIGH on boot (i.e. no external pull-down resistors may be connected between D4 and GND)
* GPIO0/D3 must be free of pull-up/down resistors so that the USB-to-serial chip can switch between RUN and FLASH mode.

Also, holding GPIO16/D0 LOW for an extended amount of time while running may have unintended side effects like triggering the watchdog, especially if the board manufacturer decided to add the deep sleep wakeup resistor between D0 and RST (you most certainly have a NodeMCU clone, so this might actually be possible).

So it might very well be that you need to reverse the button logic on GPIO15/D8 (i.e. connect the button between D8 and 3.3V). It also might be that the pin numbering on your NodeMCU is confusing; better use the D0-D10 constants.

Depending on the type of your relays, your relays may act as a pull-up/down resistor, too, further adding to the confusion.

I'd try this sketch without anything connected (no buttons, no relays) and when it works, I'd add buttons and relays one by one until you find the culprit. Sometimes it might be sufficient to swap a relay and a button, sometimes you need to reverse the logic on a button.

I would say that using any ESP8266 with that many input/output lines requires very careful consideration on where to connect what. The GPIO pins on an Arduino Nano are not involved in boot mode nor watchdog, so at least there you'd not get any interference.

# Answer
> 0 votes
According to Esp8266 documentation this is a software reset. After a fast peek, I didn't find delay() or yield() in your code. The esp8266 needs to attend some time to WiFi related background tasks, and it is does when your arduino code delays or yields the processor.

---
Tags: esp8266, nodemcu, timers, watchdog
---


# Question
Title: Displaying when Button has been pressed for LED and returning 1
I've just started using Arduino and I'm having trouble getting my code right.

Here is the task I need to do.

"Create a button read function Hint: the function header should be `int checkbutton ( void )` in the loop function, add code such that if the button has been pressed (i.e. the checkbutton function returns 1), a message is sent to the serial monitor with your username."

There are no errors in the code but nothing happens in the serial monitor when I press the LED button and it does not return 0 when i don't press the LED button. Any sort of help would be appreciated!

Thanks!

```
int Button = 15; //LED and output are on the same pin

int last = 0;

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

int button() {
  pinMode(Button, INPUT);

  int current = digitalRead(Button);

  if (current and not last) {
    delay(5);

    pinMode(Button, OUTPUT);

    Serial.print("Hey");
    return 1;
  }

  else {
    pinMode(Button, OUTPUT);

    current == last;

    return 0;
  }
}

void loop() {
  if (button >=0)
  {
    button();
  }

  else
  {
    ;
  }
}

```

# Answer
In your button() function, the line

```
if (current and not last) {

```

is less common syntax. The more common equivalent is:

```
if (current && !last) {

```

(see https://stackoverflow.com/questions/2376448/the-written-versions-of-the-logical-operators)

This line:

```
current == last;

```

Has no effect and is incorrect. This ( “==“ ) is not an assignment but a comparison and does not do what you want it to do.

I also think you have this the wrong way around. You want to save the “last” button state to compare it with the current button state when you call `button()` the next time. So you would need to set “last” to the current button state, like this:

```
last = current;

```

The next time you call `button()`, “last” contains the previous button state, so your comparison to the current button state will work.

And I think your button detection code would work better if you set `last = current` each time you call button(), whether a button has been pressed or not. Otherwise your code would repeatedly keep printing “Hey” until you stop pushing the button (unless that’s what you want). Like so:

```
int button() {
  pinMode(Button, INPUT);

  int current = digitalRead(Button);

  if (current &&  !last) {
    ...
    ...

    Serial.print("Hey");
    last = current; // Insert here
    return 1;
  }

  else {
    pinMode(Button, OUTPUT);
    ...

```

(This has not been tested but should give you a general idea).
> 1 votes

# Answer
Your problem may only be that you are not calling the button function. Try changing `if (button >=0)` to `if (button() >=0)`.
> 0 votes

---
Tags: led, button
---


title: Run servo when image is capture

text:
# Question
Title: Run servo when image is capture
I am trying to create a program when the camera capture the servo will rotate in 90 degrees continously, but my code will stop in `print output 2` any idea to run the servo continously?

Here's the Code

```
import numpy as np
import cv2
import serial
import struct
import time

ser = serial.Serial('COM11',9600)

x=0

while(True):

 # Capture frame-by-frame
    cap = cv2.VideoCapture(0)
    #framerate = cap.get(5)
    ret, frame = cap.read()
    cap.release()
    # Our operations on the frame come here

    filename = 'C:/Users/DELVO/Desktop/tryTest/bruises/main/images' +  str(int(x)) + ".png"
    x=x+1
    cv2.imwrite(filename, frame)
    print(ser.write(x))
    time.sleep(5)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()

```

Arduino Code

```
#include <Servo.h>
int data_x = 0;
int data_y = 0;
int data[1];
Servo myservo_x;
Servo myservo_y;// create servo object to control a servo
// twelve servo objects can be created on most boards

int pos = 0;    // variable to store the servo position

void setup() {
  Serial.begin(9600);
  myservo_x.attach(7);  // attaches the servo on pin 9 to the servo object
  myservo_y.attach(10);
  myservo_x.write(90);
  myservo_y.write(90);
}

void loop() {
  while (Serial.available() >= 2) {
    //    data_x=Serial.read();
    //    data_y=Serial.read();
    for (int i = 0; i < 2; i++) {
      data[i] = Serial.read();
    }

    myservo_x.write(data[0]);
    myservo_y.write(data[1]);

    Serial.println(data[0]);
    Serial.println(data[1]);
  }

}

```

# Answer
> 0 votes
is the arduino code giving error because you have initialized the array data with length of 1 (`int data[1];`) and in the for loop the length is exceeding the allocated length of the string: `for (int i = 0; i < 2; i++) {
 data[i] = Serial.read();
 }`

---
Tags: python, opencv
---


title: Arduino Nano 33 battery power/charging

text:
# Question
Title: Arduino Nano 33 battery power/charging
I have a project with an Arduino Nano 33 BLE Sense. My project is working great, but I need to transition it to battery power, and I'm having a bit of confusion about exactly what's required.

I have a small 3.7V Li-ion battery I'd like to use (similar to this one {0}) if possible.

I have read what seems to be some conflicting information, so I'd like to see which of the following are true:

* I can power the Arduino directly from the 3.3v pin? I'm suspicious of this advice since on the datasheet the 3.3v pin is marked output only. There's a note on the product page that says:

> Note: for ultra low-power functionality, you should cut the 3V3 jumper on the back of the board, and use an external battery at 3V3.

Is this something I should do? It seems difficult to reverse, I'm worried I might break my project.

* I can power the Arduino directly from the VIN pin? This again seems to contradict the datasheet, which says the VIN pin can only handle 4.5 - 21V. 3.7V is less than this.
* I could use a Step-up DC-DC transformer - like this {1}? I'd rather not wait for shipping from China.

Furthermore, I'd like to be able to charge the battery, so if I use a charging board like this one {2}, would that just work?

I don't want to connect the battery anywhere it might not be welcome for the risk of frying anything. Any help would be appreciated.

---

Link references (in case ebay listings go away):

0: Lithium Ion Battery - 110mAh

1: Mini 3V 3.3V 3.7V 5V 9V to 12V Step Up Boost Converter Module Voltage Regulator

2: 4.2V 5V 1A Micro USB Li-ion Battery Charger TP4056 Protection Chip Lithium-ion

# Answer
> 2 votes
The VIN (and the USB) goes into a 3.3V switching regulator. This has a minimum input voltage of 4.5V.

You isolate the output of that regulator from the rest of the circuit by cutting that one link (which is easy to re-solder). You are then free to feed 3.3V from your own power source directly into the board.

Yes, if you provide more than 3.3V you are liable to damage the board (note that a Li-Poly can be around 4.2V when fully charged).

You need to take your battery power and feed it through a nice efficient switching voltage regulator that has a low enough "dropout" voltage to allow good use from the battery. Note that many devices "rated" at 3.3V will also work much lower. For example:

* Nina-B3 series module will run at down to 1.7V.
* The APDS-9960 will operate down to 2.4V.
* The HTS221 will run at down to 1.7V.
* MP34DT06J can go as low as 1.6V.
* LSM9DS1 can run from 1.9V.
* LPS22 is 1.7V minimum

So it could be good to reduce your power to 2.5V instead of 3.3V to give more life from the battery. You should check each of the components in the both the device schematic and the rest of your circuit (by reading the datasheets) to find the highest "minimum" voltage they will work on.

---
Tags: voltage-level, battery, arduino-nano-ble
---


# Question
Title: First time working with arduino, need help adapting project from UNO to NANO
This is my first time working with an arduino and I'm having some issues when trying to copy a program I found online on my Nano.

Basically, my project consists in a pulse sensor that sends the pulse information to the arduino and then to the hc-05 Bluetooth module so my phone can receive this information in real-time.

On my nano: D2 receives the output of the sensor, D8 and D9 are connected to pins RX/RT on HC05 and D13 has a LED connected to it.

Now here's the thing, I really don't know much about this and the code I found uses different pins from the ones I'm using.

The LED keeps blinking and isn't synchronized with the sensor output, when the led blinks I receive a response in the Bluetooth serial app but I would like to synchronize the heart sensor with the led so than I can receive the pulses on my phone. I've been trying to solve this but I still can't find a solution.

Full code can be found at https://www.instructables.com/id/Pulse-Sensor-With-Bluetooth-and-Arduino/

Here's part of my code

//bluetooth
#include <SoftwareSerial.h>// import the serial library

SoftwareSerial Genotronex(8, 9); // RX, TX
int ledpin=13; // led on D13 will show blink on / off
int BluetoothData; // the data given from Computer

//  Variables
int pulsePin = 2;                 // Pulse Sensor purple wire connected to analog pin 0
int blinkPin = 13;                // pin to blink led at each beat
int fadePin = 5;                  // pin to do fancy classy fading blink at each beat
int fadeRate = 0;                 // used to fade LED on with PWM on fadePin

// Volatile Variables, used in the interrupt service routine!
volatile int BPM;                   // int that holds raw Analog in 0. updated every 2mS
volatile int Signal;                // holds the incoming raw data
volatile int IBI = 600;             // int that holds the time interval between beats! Must be seeded!
volatile boolean Pulse = false;     // "True" when User's live heartbeat is detected. "False" when not a "live beat".
volatile boolean QS = false;        // becomes true when Arduoino finds a beat.

// Regards Serial OutPut  -- Set This Up to your needs
static boolean serialVisual = true;   // Set to 'false' by Default.  Re-set to 'true' to see Arduino Serial Monitor ASCII Visual Pulse

void setup(){
  pinMode(blinkPin,OUTPUT);         // pin that will blink to your heartbeat!
  pinMode(fadePin,OUTPUT);          // pin that will fade to your heartbeat!
  Serial.begin(115200);             // we agree to talk fast!
  interruptSetup();                 // sets up to read Pulse Sensor signal every 2mS
   // UN-COMMENT THE NEXT LINE IF YOU ARE POWERING The Pulse Sensor AT LOW VOLTAGE,
   // AND APPLY THAT VOLTAGE TO THE A-REF PIN
//   analogReference(EXTERNAL);
Genotronex.begin(9600);
  Genotronex.println("Bluetooth On please press 1 or 0 blink LED ..");
  pinMode(ledpin,OUTPUT);
}

//  Where the Magic Happens
void loop(){

    serialOutput() ;

  if (QS == true){     //  A Heartbeat Was Found
                       // BPM and IBI have been Determined
                       // Quantified Self "QS" true when arduino finds a heartbeat
        digitalWrite(blinkPin,HIGH);     // Blink LED, we got a beat.
        fadeRate = 255;         // Makes the LED Fade Effect Happen
                                // Set 'fadeRate' Variable to 255 to fade LED with pulse
        serialOutputWhenBeatHappens();   // A Beat Happened, Output that to serial.
        QS = false;                      // reset the Quantified Self flag for next time
       }
      else {

      digitalWrite(blinkPin,LOW);            // There is not beat, turn off pin 13 LED
      }

   ledFadeToBeat();                      // Makes the LED Fade Effect Happen
  if (Genotronex.available()){
BluetoothData=Genotronex.read();
   if(BluetoothData=='1'){   // if number 1 pressed ....
   digitalWrite(ledpin,1);
   Genotronex.println("LED  On D12 ON ! ");
   }
  if (BluetoothData=='0'){// if number 0 pressed ....
  digitalWrite(ledpin,0);
   Genotronex.println("LED  On D12 Off ! ");
  }
}
  delay(20);                             //  take a break
}```

# Answer
> 0 votes
First: There is no need to change pin assingments, when changing from Uno to Nano. They use the same microcontroller and have the same pins.

You have set `pulsePin` to 2, which corresponds to pin D2. But the pulse sensor gives you an analog signal. D2 is not capable of measuring analog voltages, it can only measure digital voltages. Meaning you need to use one of the analog pins, A0 to A7, so use one of these pins in the declaration of `pulsePin`.

The reason for this is, that the microcontroller uses an extra peripheral device included in it for measuring analog voltages: the ADC (Analog to Digital Converter). It can only be connected to a limited number of pins (internally via a multiplexer). That also means, that you can only measure the analog voltage at one pin at a time.

---
Tags: arduino-nano, bluetooth, hc-05
---


# Question
Title: On compiling I get #endif without #if error. Here is the code. Please help!
```
#include <Arduino.h>
#endif
#include <ESP8266WiFi.h>
#define watersensor D2
const char* ssid = "pooja";
const char* password = "ranip2780@";
WiFiServer server(301);
IPAddress ip(192, 168, 43, 67);
IPAddress gateway(192, 168, 43, 1);
IPAddress subnet(255, 255, 255, 0);
IPAddress dns(192, 168, 43, 1);
void setup() {
  Serial.begin(115200);
  delay(10);

  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.config(ip, dns, gateway, subnet);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");

  server.begin();
  Serial.println("Server started");

  Serial.print("Use this URL to connect: ");
  Serial.print("http://");
  Serial.print(WiFi.localIP());
  Serial.println("/");
}

void loop()
{
  // Check if a client has connected
  < WiFiClient client = server.available();
  if (!client) {
    return;
  }

  // Wait until the client sends some data
  Serial.println("new client");
  while (!client.available()) {
    //    delay(1);
    client.setNoDelay(1);
  }

  String request = client.readStringUntil('\r');
  Serial.println(request);
  client.flush();

  client.println("HTTP/1.1 200 OK");
  client.println("Content-Type: text/html");
  client.println("");
  client.println("");
  client.println("<html>");
  client.println("<meta http-equiv='refresh' content='20'>");
  client.println("<title>WATER OVERFLOW ALARM WITH ONLINE UPDATES</title>");
  client.println("<center>");
  client.println("<style>");
  client.println("H1 {");
  client.println("background-color: blue;");
  client.println("}");
  client.println("</style>");
  client.println("<H1 style='color:white'><table>");
  client.println("<tr>");
  client.println("<td><div class='inner'><font size= '+3' color='white'><b>");
  client.println("WATER OVERFLOW ALARM WITH ONLINE UPDATES<br>");
  client.println("USING NODEMCU 1.0 BOARD</font></b>");
  client.println("</div></td>");
  client.println("<td><div class='relative'>");

  if (digitalRead(watersensor) == LOW)
  {
    client.println("<button style='background-color:red;width:200px;height:100px'><font size= '+2' color='white'><b>FULL LEVEL ALERT</b></font></button><br>");
  }
  else
  {
    client.println("<button style='background-color:gray;width:200px;height:100px'<font size= '+2' color='white'><b>NOT FULL</b></font></button><br>");
  }

  client.println("</div></td>");
  client.println("</tr>");
  client.println("</table><hr></center>");
  client.println("<body style = 'background-color:lightgray;'>");
  client.println("<br>");
  client.println("<style>");
  client.println("div.relative {");
  client.println("position: relative;");
  client.println("left:100px;");
  client.println("}");
  client.println("div.inner {");
  client.println("position: relative;");
  client.println("left:10px;");
  client.println("}");
  client.println("div.sample1 {");
  client.println("position: relative;");
  client.println("left:85px;");
  client.println("}");
  client.println("</style><hr><br>");
  client.println("<b>LEGENDS: </b> <button style='background-color:gray;width:100px;height:50px'><font color='white'<b>NOT FULL</b></font></button>");
  client.println("<font color='black'><b>WATER LEVEL IS BELOW SENSOR.</b></font><p>");
  client.println("<div class='sample1'><button style='background-color:red;width:100px;height:50px'><font color='white'><b>FULL LEVEL ALERT</b></font></button><font color='black'><b> WATER LEVEL IS ALREADY FULL.</b></font>");
  client.println("</div><br><hr>");
  client.println("</body>");
  client.println("</html>");
  delay(1);
  Serial.println("Client disconnected");
  Serial.println("");
  delay(500);
}

```

# Answer
The Arduino IDE gives you a massive clue

```
Arduino: 1.8.12 (Windows 10), Board: "Arduino Uno"

sketchX:2:2: error: #endif without #if

 #endif

  ^~~~~

sketchX:3:10: fatal error: ESP8266WiFi.h: No such file or directory

 #include <ESP8266WiFi.h>

          ^~~~~~~~~~~~~~~

compilation terminated.

exit status 1
#endif without #if

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

```

That's pointing at lines #2 & #3 in the sketch as having the error. So we fix those and try again

```
//#endif

```

I'll also install the ESP8266 stuff since that's missing on my new laptop.

```
Arduino: 1.8.12 (Windows 10), Board: "Generic ESP8266 Module, 80 MHz, Flash, Legacy (new
can return nullptr), All SSL ciphers (most compatible), dtr (aka nodemcu), 26 MHz, 40MHz,
DOUT (compatible), 1MB (FS:64KB OTA:~470KB), 2, nonos-sdk 2.2.1+100 (190703), v2 Lower
Memory, Disabled, None, Only Sketch, 115200"

C:\Users\winuser\Arduino\sketchX\sketchX.ino: In function 'void loop()':

sketchX:42:3: error: expected primary-expression before '<' token

   < WiFiClient client = server.available();

   ^

sketchX:42:16: error: expected primary-expression before 'client'

   < WiFiClient client = server.available();

                ^

sketchX:42:16: error: expected ';' before 'client'

sketchX:43:8: error: 'client' was not declared in this scope

   if (!client) {

        ^

sketchX:49:11: error: 'client' was not declared in this scope

   while (!client.available()) {

           ^

sketchX:54:20: error: 'client' was not declared in this scope

   String request = client.readStringUntil('\r');

                    ^

sketchX:4:21: error: 'D2' was not declared in this scope

 #define watersensor D2

                     ^

C:\Users\winuser\Arduino\sketchX\sketchX.ino:79:19: note: in expansion of
macro 'watersensor'

   if (digitalRead(watersensor) == LOW)

                   ^

exit status 1
expected primary-expression before '<' token

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

```

So all in all it's simple to use the messages that the IDE gives you to find your error and correct them, working from top to bottom in your sketch. It's not something that needs to be posted on StackExchange until you've corrected the basics.
> 2 votes

---
Tags: arduino-uno, esp8266, sensors
---


# Question
Title: Reading data from an Ohaus Defender 3000 with a RS-232 shield
I have a project where we have to read the weight from an Ohaus Defender 3000 by using an Arudino Mega 2560 and a RS-232 shield. Right now we have the RX of the Arduino to the TX of the shield, and the TX of the Arduino to the RX of the shield. In our code, we get both the RX and the TX lights of the shield to light up but we can't receive data from the scale into the Arduino. Could someone help me understand what is going on or am I doing something wrong. This is the following code that I used for the Arduino. I found this code at: Reading Arduino Serial Input. Thank you for the help in advance.

```
#define HWSERIAL Serial1

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

void loop() {
  int incomingByte;

  if (Serial.available() > 0) {
    incomingByte = Serial.read();
    Serial.print("USB received: ");
    Serial.println(incomingByte, DEC);
    //HWSERIAL.print("USB received:");
    //HWSERIAL.println(incomingByte, DEC);
  }
  if (HWSERIAL.available() > 0) {
    incomingByte = HWSERIAL.read();
    Serial.print("UART received: ");
    Serial.println(incomingByte);
    //HWSERIAL.print("UART received:");
    //HWSERIAL.println(incomingByte);
  }
}

```

# Answer
Can you provide a photo of your hardware setup, and the full code for your project? Please use the "code sample" formatting widget (the "{}" icon) to surround the code section, and look at the preview to make sure the code is formatted correctly.

Just a guess, but you may have the TX/RX lines to the scale connected to 'Serial' on the Mega instead of 'Serial1'. That would definitely cause problems
> 1 votes

---
Tags: serial, arduino-mega, rs232
---


title: Matching incoming data with a variable

text:
# Question
Title: Matching incoming data with a variable
I have a system where an RFID tag can be checked and Its individual 4byte UID will be printed. My task is to check if subsequent tags have the same UID and if not, print “access denied”. I'm assuming i need to use `const char` but I'm not sure. I get an error at `if (myrfid.serNum[i] == ID)` saying comparison between pointers and integers are forbidden. Any sort of clarity would be appreciated, thanks!

(Code is only a section from the for loop)

```
void loop()
{
    int i;
    const char ID[] = "111 11 11 11";

    cardpresent = myrfid.isCard();

    if (cardpresent && ! lastcardpresent)
    {
        if (myrfid.readCardSerial())
        {
            for (i = 0; i < 4; i++)
            {
                if (myrfid.serNum[i] == ID)
                {
                    Serial.print("Acess granted ");
                }
                else
                {
                    Serial.print("Acess not granted ");
                }
            }
        }
        Serial.printf("%3d ", myrfid.serNum[i]);
    }
    Serial.print("\n");

    // ...
}

```

# Answer
> 1 votes
The accepted way to initialize an array in C follows this example:

```
const char ID [] = {111, 11, 11, 11};

```

You can read more about it here.

You later use an array name ("ID") with no index ("ID\[0\]"). The C compiler assumes the programmer who uses an array name with no index is interested in the memory address of the first element of the array. But you wanted the value in that memory location. So you should use the array name with the appropriate index. Guessing, it would appear you intended to use "ID\[i\]" in the above code fragment.

---
Tags: serial, rfid, compilation-errors
---


title: ESP8266 and WPA2 PSK network

text:
# Question
Title: ESP8266 and WPA2 PSK network
I'm having some issues with esp8266 connecting to a wifi network. I'm testing with a hotspot from a mobile phone. If I set the network to open (no security) my code below works without any issue. If I enable security, WPA2 PSK (I'm assuming that means the personal version) and add the password to the code it fails to connect. Any suggestions as to what the issue might be?

```
//load softserial library
#include <SoftwareSerial.h>

//set a boolean constant variable to true
//#define DEBUG true
const boolean DEBUG = true;

//RX (pin 2) goes to TX on esp8266, TX (pin 3) goes to RX on esp8266
SoftwareSerial esp8266(2, 3);

//LED pin anode (long leg) is 13 and cathode (short leg) GND
int LED = 13;

//LED status array - led 0 is OFF (0) at startup.
int ledarray[] = {0};

void setup()
{
  //set the LED pin as output
  pinMode(LED, OUTPUT);

  //open the serial port
  Serial.begin(9600);

  //start esp8266 module (note: your esp's baud rate might be different)
  esp8266.begin(115200);

  //reset esp8266 module
  senddata("AT+RST\r\n", 2000, DEBUG);

  //set esp8266 as access point mode
  //senddata("AT+CWMODE=1\r\n", 1000, DEBUG);

  //set esp8266 as wireless station mode (web server)
  senddata("AT+CWMODE=1\r\n", 1000, DEBUG);

  //set network SSID and password if esp8266 is activate as station mode else comment out
  senddata("AT+CWJAP=\"test\", \"\"\r\n", 6000, DEBUG);

  //get ip address for esp8266
  senddata("AT+CIFSR\r\n", 2000, DEBUG);

  //configure esp8266 for multiple connections
  senddata("AT+CIPMUX=1\r\n", 1000, DEBUG);

  //turn on esp8266 server on port 80
  senddata("AT+CIPSERVER=1,80\r\n", 1000, DEBUG);
}

void loop()
{
  //is the esp8266 sending a message
  if(esp8266.available())
  {
    //if received data from esp8266
    if (esp8266.find("+IPD,"))
    {
      //subtract 48 because the read() function returns the ASCII decimal
      //value and 0 (the first decimal number) starts at 48
      int connectionid = esp8266.read() - 48;

      //read the url sent by the client, look for the variable (?)
      String msg;
      esp8266.find("?");
      delay(100);
      msg = esp8266.readStringUntil(' ');
      String command = msg.substring(0);

      //HTML served to browser
      String webpage = "<html><head><title>LED WEB SWITCH</title>";
      webpage += "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><style>.button {background-color: orange;border: none;color: white;padding: 15px 32px;text-align: center;display: inline-block;font-size: 16px;} .centre {text-align: center;}</style>";
      webpage += "</head><body class=\"centre\"><h1 class=\"centre\">LED WEB SWITCH</h1>";

      //if command is T (variable passed in button link on webpage)
      if (command == "T")
      {
        //if position 0 of ledarray is 1
        if (ledarray[0] == 1)
        {
          //turn LED off
          digitalWrite(LED, LOW);

          //set position 0 of ledarray to 0
          ledarray[0] = 0;

          //add text to webpage
          webpage += "<p>LED STATUS OFF</p>";
        }
        else
        {
          //turn the LED on
          digitalWrite(LED, HIGH);

          //set position 0 of ledarray to 1
          ledarray[0] = 1;

          //add text to webpage
          webpage += "<p>LED STATUS ON</p>";
        }
      }
      else
      {
        //add text to webpage
        webpage += "<p>LED STATUS OFF</p>";
      }

      //add the button (notice the href has a '?T')
      webpage += "<a class=\"button\" href=\"?T\">TAP</a></body></html>";

      //create a senddata string to send the wenbpage to the esp8266
      String cipsend = "AT+CIPSEND=";
      cipsend += connectionid;
      cipsend += ",";
      cipsend += webpage.length();
      cipsend += "\r\n";
      senddata(cipsend, 500, DEBUG);
      senddata(webpage, 500, DEBUG);

      //create a string closecommand, append the connection id, a return and newline
      String closecommand = "AT+CIPCLOSE=";
      closecommand += connectionid;
      closecommand += "\r\n";

      //send the closecommane
      senddata(closecommand, 500, DEBUG);
    }
  }
}

void senddata(String command, const int timeout, boolean debug)
{
  //send the received command to the esp8266
  esp8266.print(command);

  //set int variable to the number of millisends since Arduino began
  long int time = millis();

  //while the time and the timeout is less than the number of millisends since Arduino began
  while((time + timeout) > millis())
  {
    //while the esp8266 is sending messages
    while(esp8266.available())
    {
      //display output in the serial window
      Serial.write(esp8266.read());
    }
  }
}

```

# Answer
The solution to this was nothing to do with WPA2 PSK security or the baud rate being used. In my code I had a space between the WIFI server name and password (me correctly formatting). Apparently the ESP8266 does not like this one bit and the space needs to be removed - like so:

```
//set network SSID and password if esp8266 is activate as station mode else comment out
senddata("AT+CWJAP=\"test\",\"\"\r\n", 6000, DEBUG);

```
> 1 votes

---
Tags: arduino-uno, esp8266, wifi
---


# Question
Title: Multiple data packets with CIPSEND, associate each with pathway
When using a CIPSEND from an Arduino Uno to a ESP8266 connected to the Uno is there a way to associate the data packet sent with a pathway so it can be retrieved at said pathway from the browser?

For example ESP8266WebServer.h has a command like this:

```
server.on(“/specificArgs”, handleSpecificArg);   //Associate the handler function to the path

```

where the first argument is the path/filename - what's the equivalent of this using using CIPSEND?

# Answer
Your "CIPSEND" is already associated with a path.

The sequence is generally:

1. You configure the ESP8266 as a server, including turning on multiple connections
2. You browse to the IP
3. The browser sends a HTTP request including a path. This has a "channel" number associated with it.
4. You generate a HTTP response and send it to the channel given in 3 using `AT+CIPSEND`.

The fact that you're sending the response to the browser through the channel that the request came in through "associates" the response with the request.

To do different things depending on the path it's up to you to recognise that path in the request and generate a different response accordingly.
> 0 votes

---
Tags: arduino-uno, esp8266
---


# Question
Title: Arduino Firebase connection refused error
I am making a project for school where I have to send data from a sensor to a webpage. After doing some research I decided to use a Real-Time Firebase database. Security is not really important and I want to focus on other aspects of the project, so this seemed like an easy and quick option. I am using a d1 mini (esp8266) and a DHT11 humidity and temp sensor. For libraries I am using DHT, FirebaseArduino and ESP8266WiFi. The code is:

```
#include <ESP8266WiFi.h>                                                    // esp8266 library
#include <FirebaseArduino.h>                                                // firebase library
#include <DHT.h>                                                            // dht11 temperature and humidity sensor library

#define FIREBASE_HOST "xx"                   // the project name address from firebase id
#define FIREBASE_AUTH "xx"            // the secret key generated from firebase

#define WIFI_SSID "xx"                                             // input your home or public wifi name
#define WIFI_PASSWORD "xx"                                        //password of wifi ssid

#define DHTPIN D5                                                           // what digital pin we're connected to
#define DHTTYPE DHT11                                                       // select dht type as DHT 11 or DHT22
DHT dht(DHTPIN, DHTTYPE);

void setup() {
  Serial.begin(9600);
  delay(1000);
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);                                     //try to connect with wifi
  Serial.print("Connecting to ");
  Serial.print(WIFI_SSID);
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }
  Serial.println();
  Serial.print("Connected to ");
  Serial.println(WIFI_SSID);
  Serial.print("IP Address is : ");
  Serial.println(WiFi.localIP());                                            //print local IP address
  Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH);                              // connect to firebase
  dht.begin();                                                               //Start reading dht sensor
}

void loop() {
  float h = dht.readHumidity();                                              // Reading temperature or humidity takes about 250 milliseconds!
  float t = dht.readTemperature();                                           // Read temperature as Celsius (the default)

  if (isnan(h) || isnan(t)) {                                                // Check if any reads failed and exit early (to try again).
    Serial.println(F("Failed to read from DHT sensor!"));
    return;
  }

  Serial.print("Humidity: ");  Serial.print(h);
  String fireHumid = String(h) + String("%");                                         //convert integer humidity to string humidity
  Serial.print("%  Temperature: ");  Serial.print(t);  Serial.println("°C ");
  String fireTemp = String(t) + String("°C");                                                     //convert integer temperature to string temperature
  delay(4000);

  Firebase.pushString("Humidity/", fireHumid);                                       //setup path and send readings
  Firebase.pushString("Temperature/", fireTemp);                                //setup path and send readings

}

```

replaced some 'sensitive' information with "xx". When running this code, it connects to my wifi connection and shows data from the DHT11 in the serial monitor. However NOTHING changes in Firebase. After enabling the feature to display extensive feedback/errors in the serial monitor, I noticed it's displaying this:

```
[HTTP-Client][begin] host: https://testtesttest-bd679.firebaseio.com/ port: 443 url: /Temperature/.json?auth=xxxx httpsFingerprint: 03 D6 42 23 03 D1 0C 06 73 F7 E2 BD 29 47 13 C3 22 71 37 1B
[HTTP-Client][sendRequest] type: 'POST' redirCount: 0
[HTTP-Client] failed connect to https://xxx-xxx.firebaseio.com/:443
[HTTP-Client][returnError] error(-1): connection refused
[HTTP-Client][returnError] error(-4): not connected
[HTTP-Client][end] tcp is closed
Humidity: 43.00%  Temperature: 22.50°C

```

I have tried the following things:

* Using a different version of the FirebaseArduino library (5.13.x (still using this one))
* Manually updating the fingerprint of the FirebaseArduino library (see current fingerprint in 2nd code section above)
* Using different versions of the Arduino IDE, using 1.8.12 now

And some other minor changes like creating a new Firebase Database or using something different from pushString to add data to the database.

None of this helped and I am running out of time for my project, hope someone here knows what's wrong and can help me out! :)

# Answer
> 2 votes
You added a `/` to the end of the Humidity and Temperature collections. e.g Firebase.pushString("Humidity/", fireHumid);
Firebase.pushString("Temperature/", fireTemp);

The firebase API translates it to an address

```
https://testtesttest-bd679.firebaseio.com/Temperature/.json?auth=xxxx`

```

as we can see in the output.

I'm pretty sure the correct address is `...Temperature.json...` and not `...Temperature/.json...`.

Please try to remove the slashes from the end of the collection names in the `pushString` statements..

```
Firebase.pushString("Humidity", fireHumid);
Firebase.pushString("Temperature", fireTemp);

```

If this does not help, it is possibly a problem with the auth string or the Host name. e.g trailing or leading space characters or something like that.

---
Tags: arduino-ide, http, error
---


# Question
Title: Continue playing sound during interrupt routine
I'm trying to play a tone (on an Arduino Mega through the tone library) and have the tone not be interrupted if an interrupt routine is called while the tone is playing. I'm not sure it's possible. The code block is below. Relevant functionality is:

-A while loop runs indefinitely until Button S1 is pressed. Pressing Button S1 triggers an interrupt routine in which interruptFlag\_s1 is set to 1.

-This starts a tone playing for 300ms.

-There's a possibility that another button press interrupt is triggered during the 300ms tone. This interrupts the tone for about 0.5ms, enough to make a perceptible break in the tone that I'd like to avoid.

-Ideal scenario is that the audible tone isn't interrupted by the interrupt routine.

```
    while (restart == 0) {
      if (interruptFlag_s1 == 1 || interruptFlag_s2 == 1) {
        if (interruptFlag_s1 == 1) {
          primary_sensor = 1;
          interruptFlag_s1 = 0;
          rBot = false;
          gBot = true;
          bBot = false;
        } else if (interruptFlag_s2 == 1) {
          primary_sensor = 2;
          interruptFlag_s2 = 0;
          rBot = false;
          gBot = false;
          bBot = true;
        }

        interruptFlag_rtc = 0;
        finish_id = 0;
        button_flag = 0;
        time_diff = 0.00;
        alt_finish_time = 0.00;
        tone(speakerPin, 3000, 300); // Start tone
        restart = 1;
      }
    }

```

# Answer
The sound is itself generated by an interrupt routine. Since only one interrupt routine can happen at a time, if your own interrupt routine takes too long, then you will get interruption in the sound.

There is nothing you can do about that other than making your interrupt routine short enough that it doesn't cause any interruption in the sound.
> 1 votes

---
Tags: interrupt
---


# Question
Title: How is this code working?? val3 is defined as constant
```
const int val3 = 7;
void setup(){
  Serial.begin(9600);
  int val3 = 8;
  int val4 = 4;
  Serial.print(calc(val3,val4));
}

void loop()
{}

int calc(int val1, int val2)
{
  return val1 + val2;
}

```

this code gives output as 12.

# Answer
> 3 votes
In your code, the `const int val3 = 7;` definition, is outside of any functions so it defines a **global** constant/variable (available in every part of your code).

The `int val3 = 8;` definition is inside your `setup ()` function, so it acts as a **local** variable only within that function. This overrides the `val3` constant defined outside of the `setup ()` function. I.e. the global `val3` constant and the local `val3` variable inside of `setup ()` are not the same variable, which will inevitably lead to confusion (as in your case).

It’s valid syntax but I don’t consider it good coding practice. It’s good to know why it works that way though.

# Answer
> 0 votes
You have declared val3 two times: One time as constant int and another time as int (in setup loop). Replace the statement `int val3=8 by val3 = 8`. You will know the difference.

The first declaration is of no use in this case. As a try, you may first declare val3 as int and in the second declaration you may declare val3 as const int.

Just try and note the difference. Happy coding!

---
Tags: arduino-uno
---


# Question
Title: How to create large progmem arrays and not annoy the linker
I have a rather complex project (PlatformIO, but I've also had this happen in the vanilla IDE) with several nested includes. Let's say that there are three files and a main sketch. The main sketch includes #2 and #3. File #3 includes file #1 and file #2.

If file #2 is a .h file containing something like a font, of the format:

```
const char foo[] PROGMEM = {0xDE,0xAD,0xBE,0xEF};

```

Then I get linker errors of **multiple definitions of 'foo'** in both #3 and main.

Weirdly, the default fonts included in my OLED library are placed in a header file, EXACTLY like how I did it, and yet multiple files including that library (or files that themselves included it) do not cause this issue with the library's header file.

Yes, I do have a working include guard. For some reason it doesn't ever seem to help.

I have been using `extern` to solve this issue, but it's annoying and I'm not sure that it's proper behavior, either...

Could it have something to do with `#include <font.h>` vs `#include "font.h"`? What is the difference? My reference said they mean the same thing, but now I'm not so sure.

# Answer
> 2 votes
Include Guards only protect against inclusion of a header file multiple times within the same *translation unit*. This is important. If you include a header file (1) in a source file, then include another header file (2) in the same source file, said header file also including the previous header file (1), then the include guard will perform its function.

If you have two source files and you include the same header in both, then the include guard will do nothing.

If you have a variable or function defined in a header file and you include that header into two different source files, when you link those source files together you will get a multiple definition error, since you have two translation units that have the same thing in them, and the linker doesn't like that.

The only time you should ever define variables or functions in a header file are if they are *simple constant* types, like a `const int` or a `const char` \- something where the compiler can replace it verbatim in the code and optimize out the symbol completely (arrays of any kind are not *simple*), or if the symbol is declared "static", where it will be forced to remain "within" the translation unit and not get exported for linking.

Normally you will only declare your *complex* constants in the header file, and define them once and once only in a single source file. That way there is only one instance of the symbol in one translation unit.

For example, in the header file you would declare your constant:

```
extern const char foo[] PROGMEM;

```

And in your source file define the constant:

```
#include "foo.h"
const char foo[] PROGMEM = {0xDE,0xAD,0xBE,0xEF};

```

And in answer to the question "what's the difference between `#include <...>` and `#include "..."` \- when it comes to Arduino, nothing whatsoever.

Officially it denotes a separation between "system" and "local" headers. That is, headers that are installed in the OS as part of the compiler, and headers that are contained within the project. However there isn't that distinction with Arduino, and the two mean the same thing - just a header.

And finally a note on terminology - a glossary if you will:

* *Translation unit* \- One compilable source file (and any included headers) that forms a single file of object code to be linked.
* *Declaration (Declare)* \- The indicating of a symbol's type and any attributes, but not the content of that symbol
* *Definition (Define)* \- Associating a symbol, whilst declaring it, with the content of that symbol.
* *Symbol* \- the name of any variable, function, class, etc.

---
Tags: arduino-ide, c++, progmem, linker
---


# Question
Title: How to display CAN BUS information on EPS32 web server?
I try to display the transmitted information from CAN bus on ESP32 web server. I saved the `CAN.read()` in a buffer `receivedChars[i]` and try to display the data by `client.println(receivedChars[i]);}`. However, nothing shows on the webserver... The complete code shows below,

```
// Copyright (c) Sandeep Mistry. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#include <CAN.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <WiFi.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels

// Replace with your network credentials
const char* ssid     = "NGW_2.4G";
const char* password = "NextGW2018";

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

// Variable to store the HTTP request
String header;

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

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

  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for (;;);
  }
  delay(2000);
  display.clearDisplay();
  display.setTextColor(WHITE);

  Serial.println("CAN Receiver");
  CAN.setPins(16, 17);
  // start the CAN bus at 500 kbps
  if (!CAN.begin(500E3)) {
    Serial.println("Starting CAN failed!");
    while (1);
  }

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

void loop() {

    char receivedChars[10];
  // try to parse packet
  int packetSize = CAN.parsePacket();

  if (packetSize) {
    // received a packet
    Serial.print("Received ");

    if (CAN.packetExtended()) {
      Serial.print("extended ");
    }

    if (CAN.packetRtr()) {
      // Remote transmission request, packet contains no data
      Serial.print("RTR ");
    }

    Serial.print("packet with id 0x");
    Serial.print(CAN.packetId(), HEX);

    if (CAN.packetRtr())
    {
      Serial.print(" and requested length ");
      Serial.println(CAN.packetDlc());
    }
    else
    {
      Serial.print(" and length ");
      Serial.println(packetSize);

      // only print packet data for non-RTR packets
      while (CAN.available())
      {
         for (int i=0; i<5; i++)
         {
           receivedChars[i] = (char)CAN.read();
           Serial.print(receivedChars[i]);
         }
      }
      Serial.println();
    }

    Serial.println();
  }

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

            // Display the HTML web page
            client.println("<!DOCTYPE html><html>");
            client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
            client.println("<link rel=\"icon\" href=\"data:,\">");
            // CSS to style the table
            client.println("<style>body { text-align: center; font-family: \"Trebuchet MS\", Arial;}");
            client.println("table { border-collapse: collapse; width:35%; margin-left:auto; margin-right:auto; }");
            client.println("th { padding: 12px; background-color: #0043af; color: white; }");
            client.println("tr { border: 1px solid #ddd; padding: 12px; }");
            client.println("tr:hover { background-color: #bcbcbc; }");
            client.println("td { border: none; padding: 12px; }");
            client.println(".sensor { color:white; font-weight: bold; background-color: #bcbcbc; padding: 1px; }");

            // Web Page Heading
            client.println("</style></head><body><h1>Can bus</h1>");
            client.println("<tr><td>text: </td><td><span class=\"sensor\">");

         for (int i=0; i<5; i++)
         {
           receivedChars[i] = (char)CAN.read();
           client.println(receivedChars[i]);
         }

            client.println(" .</span></td></tr>");

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

```

# Answer
It looks like the CAN-BUS can not be activated in web server session, I save the transmitted information in a buffer before starting the web server session, and print out the information from the buffer.
> 1 votes

---
Tags: wifi, communication, esp32, web-server, can-bus
---


# Question
Title: 5V on HIGH Digital Pins, Only While Using USB Power
So I have a small problem with my Arduino Pro Mini here. May be worth noting that it is a clone, but otherwise this is still some weird functionality. I have done some experimenting so I'll just set the scene for you. I have everything that requires power connected to the + and - lines on my breadboard, that way I can avoid drawing more than about 20mA across any individual pins. I currently have my Arduino Pro Mini hooked up to the 5V power supply via the RAW and GND pins, but the supply is a regulated 5v wall supply. It actually is currently outputting 5.36V.

I have made sure all my pins I'm using for output are indeed set as output, the problem only arises when I attempt to power the device from something OTHER than USB power. I tested the output from my wall adapter connected to RAW and to a random VCC pin, both have the same effect.

When powering the device via USB (USB to Deek-Robot ASP, then to Pro Mini), if I set my digital output pin to HIGH, I get 5v. This is enough to turn on a 5v relay that then supplies power from the supply to a small water pump. However, if I use the regulated wall-power, I get about 3.7 to MAYBE 4.15v, which sadly is not enough to switch the relay to the NO position.

I have tested the voltage coming from the USB ASP as well, it is 4.95v.

EDIT: The wall-plug voltage drops from 5.36 with no load except the meter to 4.7v with the Arduino and a couple LEDs attached, if that means anything.

# Answer
> 0 votes
Power supply was dropping to 3.8 volts under basic load, once it turned on some LEDs it was just too low to activate the relay switch. Crappy Chinese parts.

# Answer
> 1 votes
"Arduino Pro Mini hooked up to the 5V power supply via the RAW and GND pins, but the supply is a regulated 5v wall supply. "

That is the problem. RAW pin expects more like 6V to 6.5V for the regulator to output 5V.

If you are supplying 5V, connect to the 5V, or VCC and GND pins.

If you are connecting to USB via an FTDI Basic or equivalent, and the 5V supply at the same time, then the computer may not like having the USB 5V line back driven from an external source (mine complains about a "power surge" and shuts down the USB port). Make up a breakout cable between the FTDI and the Promini and either disconnect the 5V line, or put a diode in series so the Promini can't supply 5V back thru the FTDI and into the USB port. That way the FTDI chip is powered from USB, but the Promini is not, and all the hardware is happy.

Make sure to use series resistors with LEDs to avoid overcurrent from the Promini output pin, which will either damage the IO pin, possibly damaging the 328P, or damaging the LED from overheating from excess current. (5.36V - 2.2V)/.02A = 156 ohm. A 180 ohm, 220, 270, 330, some value in that range will do. 1K will probably be fine, LEDs these days can be quite bright even at lower current; 20mA can be blindingly/annoyingly bright.

---
Tags: power, relay, voltage
---