message:
How to stop program while Servo is rotating

If I code like this:
```c
motor.write(0);
Serial.println("Before");
motor.write(180);
Serial.println("After");
```
Both "Before" and "After" is instantly printed, while the motor is still rotating.
I want "After" or whatever statement to be executed AFTER the motor
reaches 180 degree.
How can I implement this? Is it possible to read Servo's statement?

Btw, I don't want to put delay after write(), so other than that strategy.

body:
> How can I implement this? Is it possible to read Servo's statement?

No, it is not possible. When you do a `servo.write()` it just changes the PWM duty cycle. It's then up to the servo to use that to set its position. The Arduino has no concept at all of the *current* position of the servo.

> Btw, I don't want to put delay after write(), so other than that strategy.

The only other way, besides delaying or otherwise using `millis()` to wait for a predefined period after your `write` would be to implement some form of feedback between the shaft of the servo and the Arduino. Maybe a potentiometer, or rotary encoder would do the job.


sender: user

sender: assistant

body:
It's not possible with the servo alone, but you could add feedback. Some options:

 - An encoder (may be expensive or not available for your servo) will tell you the position.
 - You could also make your own encoder by connecting a potentiometer to the axis. The resistance of the pot will be related to the position of the servo.
 - if you don't need to be exact something simple like a switch at the limit you want to reach.
 - If it doesn't have to be exactly when the position is reached, you
   could measure the average time it takes (under load) to move from the
   minimum angle to the maximum angle. This will be the longest it ever
   takes to move. Then in your code wait 150% of that time before
   proceeding (to give a bit of a buffer "just in case").

As Majenko said, if you don't want to use a delay, use millis() or micros() to track the current and previous times a line in the loop executed; if the difference is larger than the required delay, the time has elapsed and you can proceed with the rest of the loop. This way you can track time without having to "block" the rest of the loop while you wait.


message:
Is it possible to run a monochrome LCD without driver circuit with an Arduino Uno?

I have an old monochrome LCD panel that I removed from a calculator. The LCD panel has no standard input pins, because it's directly connected to a driver on which the calculator software runs.

Is it possible to run the LCD without the calculator software? All pins of the LCD would be available (marked in blue). The pins marked in red were connected to the keyboard of the calculator.

[![Image shows old calculator monochrome LCD circuit][1]][1]

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

body:
In theory, maybe yes, in practice it will be hard job.

Some things you need to find out:

- Find the exact model of the LCD
- Find its datasheet
- I see an enormous amount of pins (especially the blue ones), so you need (a lot of) multiplexers or shift registers.
- Speed of the Arduino, is it enough to drive this LCD?
- You have to solder this to test.


body:
Normally such LCDs are custom designed, mass produced displays especially for this calculator product. Thus it is very unlikely to find a datasheet or even a meaningful part number for it.

Most likely the pins on the LCD are directly connected to the corresponding fields on the LCD. In an LCD you have liquid crystals between two electrodes, which change their orientation, when a voltage is applied to the electrodes, which changes the light absorption of the layer. You need to apply the correct voltage to a pair of pins to activate their field. Most likely all of the fields or a few groups of them have a common electrode (which would be 1 pin). Without any documentation you are bound to experiment with the display, until you have found the correct voltages and pin arrangements. You might break the display in the process (for example through excess voltage).

I haven't done this myself, but googling gives an interesting result:

- [This project][1], where they hacked the LCD of a cheap calculator for a waveform generator (though the display seems to be way less complex than yours) They seem to use 1.5V as voltage, so this might be a good starting point.

Your display has many pins. Depending on the Arduino model, that you use, you will fast run out of pins to use. You can try arranging the pins into a matrix, which would mean multiplexing the fields (turning them on and off fast one after another). Or you can buy additional parts to extent your pin count, for example shift registers.

---

As jsotola wrote in the comments (and as several forum threads on web web state), you should not put a constant voltage onto the display, since this will damage it. (I guess the liquid crystals will degrade fast because of their polarity, which make the work in the first place). Instead you have to place an alternating voltage at the pins, which changes it's polarity. The  net voltage (The integrated voltage over time) must be zero. Thus you need to alternate the applied voltage. If you provide a span of 1.5V, you need to change between +0.75V and -0.75V.

As the display shouldn't need too much current and the voltage requirement is relative to the LCD ground, you might get way by setting the LCDs ground with a voltage divider to 2.5V and then operating around that. Though I'm not sure about that.

Otherwise you might need to actually change the polarity. This would also just need 1 extra digital output pin as the ground pin. One polarity would be the LCDs ground pin to Arduino's ground (outputting LOW at the digital pin) and the other pins to the needed positive voltage (HIGH divided down over a voltage divider or similar). The other polarity would be LCDs ground pin to the needed positive voltage (HIGH divided down over voltage divider) and the other pins to ground (outputting LOW).

---

As described above, hooking this bare LCD to the Arduino is not done fast and easy. You can try it, if you like to do it. But if you want to get your project (whatever it is) done fast, you should instead buy a LCD with integrated controller, which are mostly ready to use, and for which there are already libraries.

  [1]: https://hackaday.io/project/12756-a-feature-rich-arduino-waveform-generator
  [2]: https://www.electro-tech-online.com/threads/trying-to-hack-a-calculator-lcd-screen.89499/


message:
ESP8266 compilation error: "previous declaration of 'HTTPMethod HTTP_HEAD'"

I have an ESP8266 program that used to work but is now failing to compile with this error:

    C:\...\Arduino\libraries\WiFiManager/WiFiManager.h:25:24: note: in expansion of macro 'PROGMEM'

     const char HTTP_HEAD[] PROGMEM            = "<!DOCTYPE html><html lang=\"en\"><head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1, user-scalable=no\"/><title>{v}</title>";

                            ^

    In file included from C:\...\MyEsp.ino:14:0:

    C:\...AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.6.3\libraries\ESP8266WebServer\src/ESP8266WebServer.h:33:39: error: previous declaration of 'HTTPMethod HTTP_HEAD'

     enum HTTPMethod { HTTP_ANY, HTTP_GET, HTTP_HEAD, HTTP_POST, HTTP_PUT, HTTP_PATCH, HTTP_DELETE, HTTP_OPTIONS };
                                       ^

I don't recall changing anything, except maybe updating some libraries. Any ideas what could be causing this?  Here are my includes from the ESP8266 program:

    #include <Arduino.h>

    #include <ESP8266WiFi.h>
    #include <ESP8266WiFiMulti.h>
    #include <ESP8266HTTPClient.h>
    #include <WiFiClient.h>

    #include <DNSServer.h>            //Local DNS Server used for redirecting all requests to the configuration portal
    #include <ESP8266WebServer.h>     //Local WebServer used to serve the configuration portal
    #include <WiFiManager.h>          //https://github.com/tzapu/WiFiManager WiFi Configuration Magic

    #define SERIAL_BUFFER_SIZE 256

body: You need a newer version of the WiFiManager.h library. This issue was [fixed August last year.](https://github.com/tzapu/WiFiManager/commit/ff26ed4e4c1c34465e182af1cde0eb9e8dda6c4a)


message:
displaying a 3 digit clock time on a 4 digit 7 segment display

I purchased [one of these 4 digit 7 segment displays][1] using a TM1637.

I installed the [TM1637 display library][2] from the libraries manager and included it:

`(#include <TM1637Display.h>)`.

I am trying to display the time, and I would like, preferably, to display 3 digit times with a colon, but without the leading zero.

[I found this great reference online for using the library.][3], and saw the usage for numbers with colons:

`showNumberDecEx(number, dots, leading_zeros, length, position)`

according to the guide, to have the colon in the center, you would pass `0b01000000` as the `dots` parameter.

And I figured that if I then want to display, for example, the time `1:36`, then my `number` parameter would be 136, my `leading_zeros` parameter would be `0` (false), my length would be `3` for a 3 digit number, and my position would by `1` to start the number in the zero-indexed second position:

`display.showNumberDecEx(136, 0b01000000, false, 3, 1); //displays 5136`

But this displayed `5136` with no colon.

I tried a number of other things, including:

`display.showNumberDecEx(136, 0b01000000, true, 3, 0); //displays 13:66`
`display.showNumberDecEx(136, 0b01000000, false, 3, 0); //displays 13:6A`

I finally found [code from this site][4], which works to display the time (albeit with a leading zero), but I don't fully understand it:

`display.showNumberDecEx(1*100+36, 0x80 >> 1, 1, 4, 0);`

I get that 1*100+36 represents number of hours plus minutes, but I don't get the 0x80 >> 1 bit. I'm assuming the rest of it is just saying make it a 4 digit number and add a leading zero.

Can anyone possibly:
* help me understand the above working code
* tell me an easier way to construct a time so that I can ideally just pass a 3 or 4 digit number and have it automatically render out a clock time with separating colon
* tell me why my previous attempts were incorrect

  [1]: https://www.velleman.eu/products/view/?id=439208
  [2]: https://github.com/avishorp/TM1637
  [3]: https://www.makerguides.com/tm1637-arduino-tutorial/
  [4]: https://thestempedia.com/tutorials/making-digital-clock-using-tm1637-4-digit-display/

body:
I tested your first code line and it outputs a right aligned 136 without colon at my display. (Said I have only a colon at the middle and no decimal points)

The 5 at the fist digit (and also the A at your third code line) must have been set somewhere beforehand. The function does not change the unused digit, so it will stay whatever you set it to beforehand (Even from before the last reset of the Arduino. The display doesn't reset with the Arduino). You can set the segments for that digit to zero (or set all segments to zero, to clear the complete display) before you show the decimal number.

About the colon: Here it is important on which position you start the printing of the number. The colon/decimal point bitmask, that you provide the function with, is seen from the starting position, that you provide. The middle colon of a 4 digit display is wired to the second digit. When providing `1` as the starting position, you start with the second digit. Thus the colon bitmask must set the most significant ("first") bit, to enable the middle colon, since it belongs to the first digit, that is processed by the function. Meaning:

    position = 0 and bitmask = 0b10000000 --> colon/decimal point at first digit on
    position = 0 and bitmask = 0b01000000 --> colon/decimal point at second digit on
    position = 0 and bitmask = 0b00100000 --> colon/decimal point at third digit on
    position = 1 and bitmask = 0b10000000 --> colon/decimal point at second digit on
    position = 1 and bitmask = 0b01000000 --> colon/decimal point at third digit on
    position = 2 and bitmask = 0b10000000 --> colon/decimal point at third digit on
    position = 2 and bitmask = 0b01000000 --> colon/decimal point at fourth digit on

The `0x80 >> 1` is just a different representation of your binary number. `0x80` is the hexadecimal form of the binary `0b10000000`. The `>>` operator shifts the byte to the right, here by one digit. Thus:

    0x80 >> 1 = 0b10000000 >> 1 = 0x40 = 0b01000000

So the code, that you found, enables the colon/decimal point at the second digit.

>  tell me an easier way to construct a time

Easier it relative. I used such a display in a project to display a time and used two `showNumberDecEx()` calls; one for the minutes and one for the seconds:

    display.showNumberDecEx(seconds, 0x00, true, 2, 2);
    display.showNumberDecEx(minutes, 0x40, true, 2, 0);

Having directly minutes and seconds may make it easier for you. About the no-leading-zeros: Since the library always prints left to right, you need to handle that by yourself. But that is rather easy. One if statement to check, if the minutes are greater than 9 or not. Depending on that you set the position to 0 or 1.

    display.showNumberDecEx(seconds, 0x00, true, 2, 2);
    if(minutes > 9){
        display.showNumberDecEx(minutes, 0x40, false, 2, 0);
    } else {
        display.showNumberDecEx(minutes, 0x80, false, 1, 1);
    }

You could put that into a function, so that you don't have to write this code multiple times.

Note: For my last code snippet to work, you should first clear the display (or optionally only the first digit), so that no number from before will be displayed there.


body:
Always start by reading the docs. The README of the TM1637 display
library gives a short summary of the available functions, then states
“Please refer to TM1637Display.h for more information.” It would thus
seem the authoritative documentation is the header file itself, which is
indeed rich ins structured comments. [According to it][doc], the
signature of `showNumberDecEx()` is

```c++
void showNumberDecEx(int num,
                     uint8_t dots = 0,
                     bool leading_zero = false,
                     uint8_t length = 4,
                     uint8_t pos = 0);
```

where the parameters have the following meanings (emphasis mine):

* `num`: the number to be shown
* `dots`: dot/colon enable [...]
* `leading_zero`: when true, leading zeros are displayed, otherwise
  **unnecessary digits are blank**
* `length`: **the number of digits to set**
* `pos`: the position of the most significant digit
  (0 - leftmost, 3 - rightmost)

The `length` and `pos` parameters control which digits are set. It is
important to note that any digits that are not set _are left as is_.
Note also that, if you are setting more digits than needed to display
the number, the leftmost digits are either zeros _or blank_, depending
on the value of `leading_zero`. And that is exactly what you want: you
want the leftmost digit to be blank.

Here are some examples of what various calls display:

```c++
display.showNumberDecEx(136, 0x40, true,  3, 1)  →  "X1:36"
display.showNumberDecEx(136, 0x40, false, 3, 1)  →  "X1:36"
display.showNumberDecEx(136, 0x40, true,  3, 0)  →  "13:6X"
display.showNumberDecEx(136, 0x40, false, 3, 0)  →  "13:6X"
display.showNumberDecEx(136, 0x40, true,  4, 0)  →  "01:36"
display.showNumberDecEx(136, 0x40, false, 4, 0)  →  " 1:36"
```

In the examples above, “X” means “whatever was previously left there”,
as the corresponding digit is not updated by the call. The last example
is the one you want. Incidentally, the last three parameters of this
example have their default values. You can thus achieve this simply
with:

```c++
display.showNumberDecEx(136, 0x40);
```

You can also follow chrisl's advice and display the hours and minutes
separately:

```c++
int hours = 1;
int minutes = 36;
display.showNumberDecEx(hours, 0x40, false, 2, 0);
display.showNumberDecEx(minutes,  0, true,  2, 2);
```

No need to separately handle the case where `hours` is larger than 9.

[doc]: https://github.com/avishorp/TM1637/blob/v1.2.0/TM1637Display.h#L83-L106


message:
Fixing serial communication , condition for serial data available checks out even after reading all the data sent

I have been working on monitoring an aquaculture , where I log the environment variables (temp. , humidity, gas sensor data) to firebase and control feeding mechanism via an app(where data can also be viewed)

The setup has all sensors connected to Uno Board, which transmits data serially to esp8266.

Pin 2 of Uno is connected to Pin 2 of esp8266

Pin 3 of Uno is connected to Pin 3 of esp8266

Right now the boards are being powered by USB ports in the computer.

My understanding is that, once all the data are read, the ```Serial.available()``` becomes 0 and the ```while()``` loop will not execute again, but it worked again and reads data.. to  avoid sending same data over and over again(to FireBase), I used Boolean values to take care of.

The data should be available only once per 30 seconds, so after a string is fully read, I was able to see that pgm entered into ```while()``` loop and reads one/two values

```C

// uploaded to esp8266 Lolin(wemos) d1 r2 and mini

#include<ESP8266WiFi.h>
#include<FirebaseArduino.h>
#include<SoftwareSerial.h>

// Set these to run example.
#define FIREBASE_HOST "@#$%^.firebaseio.com"
#define FIREBASE_AUTH "********"

#define WIFI_SSID "###########"
#define WIFI_PASSWORD "&^*^*%$#"

SoftwareSerial esp(D2,D3);

float temp_fb;
float gas_fb;
float hum_fb;

unsigned long last_chk = 0 ;
unsigned long time_elapsed;

bool t_ar , h_ar , g_ar = false ; //chk arrival of all data b4 sending

char r;
String cu_st = "c";

int found = 1;

void setup() {
  Serial.begin(9600);
  esp.begin(4800);

  // connect to wifi.
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  Serial.print("connecting");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }

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

  Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH);
}

void loop()
{
  time_elapsed = millis();
  if(time_elapsed - last_chk > 5000){
    Serial.print("checking for data from arduino...\tfeeder state\t");
    Serial.println(cu_st);
    last_chk = time_elapsed;
    time_elapsed = millis();
  }
   while(esp.available()>0)
  {
     if(found == 1)
     {
      Serial.println("................found data...............") ;
      found = 0;
     }
     r = esp.read();
     //Serial.print("first char\t"); just for debugging purposes
     //Serial.println(r);
     switch(r)
     {

      case 't':
      {
        Serial.println("got t...") ;
        t_ar = true;
        temp_fb = esp.readStringUntil(',').toFloat();
        break ;
      }

      case 'g':
      {
          Serial.println("got g...") ;
          g_ar = true;

          gas_fb = esp.readStringUntil(',').toFloat();;
          break ;
      }

      case 'h':
      {
        Serial.println("got h...") ;
        h_ar = true;

        hum_fb = esp.readStringUntil(',').toFloat();
        break ;
      }

      case 'c':
      {
        cu_st = "c" ;
        Firebase.setString("feeder" ,"c");
      }
      default: break;

     }

  }

  found = 1 ;

  if(g_ar and t_ar and h_ar)
  {
     //writing to firebase
     Serial.println("got the set.. to fb now");
     Firebase.setFloat("GAS SENSORinst" ,gas_fb);
     Firebase.setFloat("HUMIDITY SENSORinst" ,hum_fb);
     Firebase.setFloat("TEMP SENSORinst" ,temp_fb);
     Firebase.pushFloat("GAS SENSOR" ,gas_fb);
     Firebase.pushFloat("HUMIDITY SENSOR" ,hum_fb);
     Firebase.pushFloat("TEMP SENSOR" ,temp_fb);
  }

  t_ar , h_ar , g_ar = false ;

  cu_st = Firebase.getString("feeder");

   if (cu_st == "o")
   {
    Serial.println("\t\trecd req to feed");
    esp.print('o');
   }

}

```
The arduino sends data every 30 Sec.
The servo connected to Arduino was having jitters every time the data was being sent(apparently due to not enough power to supply for all devices connected and both Softwareserial and servo having same timer) so I have added a LED just for trial
For some reason, ```if``` block in ```close_feed()``` is always executed.

```
//uploaded to arduino Uno
#include <SoftwareSerial.h>
#include<TimerOne.h>

SoftwareSerial ArduinoUno(3,2);
#include<Servo.h>
#include "DHT.h"

//Servo feeder;

int send_rate = 30000; //every 30 secs send data
unsigned long last_time_stamp = 0;
unsigned long cur_time = 0;

String sen_vals = "";
#define led 13
int feeding = 0 ;
const int gas = 0;//gas sensor o/p
#define DHTPIN 8
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);

void setup()
{
  // put your setup code here, to run once:
  Serial.begin(9600);
  ArduinoUno.begin(4800);
  pinMode(led,OUTPUT);
  //feeder.attach(11);
  //feeder.write(85);
  Timer1.initialize(10000); //every 10 millisecond check for arrival of feed command
  Timer1.attachInterrupt(feed_cmd); //chk feed_cmd for every 10 mS
   dht.begin();

  pinMode (3,INPUT); //recieve from esp
  pinMode (2,OUTPUT); //transmit to esp

}

void feed_cmd()
{
  while(ArduinoUno.available())
  {
    char valve = ArduinoUno.read();

    if(valve=='o')
    {
       digitalWrite(led, HIGH);
       //feeder.write(0);
       feeding = 1;
       ArduinoUno.print("c");
       valve = "";
    }
  }
}

void close_feed()
{
  if(feeding == 1)
  {

    feeding = 0;
    delay(5000);
    //feeder.write(85);
    digitalWrite(led,LOW);
    Serial.println("I am closing feeder");

   }
}

void send_data()
{
  float h = dht.readHumidity();
  float t = dht.readTemperature();
  String ht = String('h')+String(h)+String(',')+String('t')+String(t)+String(',');

  float raw_v = analogRead(gas);
  String g = String('g')+String(raw_v)+String(',');

  sen_vals = ht + g ;

  Serial.println(sen_vals);
  ArduinoUno.print(sen_vals);
}

void loop()
{
  // put your main code here, to run repeatedly:

  close_feed();
  cur_time = millis();
  if(cur_time > last_time_stamp + send_rate)
  {

    last_time_stamp = cur_time;
    send_data();

  }

}

```
Some how some blocks are executed even when they shouldn't be.. I wrote the code, but I cant figure out where the code fails, used a lot of serial prints to see how the flow of the code, but it only confused me further!

If somebody can take a look at this code and point out the flaws..I'll greatly appreciate it.

EDIT: I have changed he code as suggested below, but now the Arduino is receiving random things as input(pic attached)
I have added the changed code too(I know this post is getting bigger and bigger, but i thought making changes to already existing code here won't be good for readability )

``` //uploaded to esp
void setup() {
  Serial.begin(9600);
  esp.begin(4800);

  // connect to wifi.
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  Serial.print("connecting");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }

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

  Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH);
}

void loop()
{
  time_elapsed = millis();
  if(time_elapsed - last_chk > 5000){
    Serial.print("checking for data from arduino...\tfeeder state\t");
    Serial.println(cu_st);
    last_chk = time_elapsed;
    time_elapsed = millis();
  }
   while(esp.available()>0)
  {
     if(found == 1)
     {
      Serial.println("................found data...............") ;
      found = 0;
     }
     r = esp.read();
     //Serial.print("first char\t");
     //Serial.println(r);
     switch(r)
     {

      case 't':
      {
        Serial.println("got t...") ;
        t_ar = true;
        temp_fb = esp.parseFloat();
        break ;
      }

      case 'g':
      {
          Serial.println("got g...") ;
          g_ar = true;

          gas_fb = esp.parseFloat();;
          break ;
      }

      case 'h':
      {
        Serial.println("got h...") ;
        h_ar = true;
        hum_fb = esp.parseFloat();
        break ;
      }
      default: break;

     }

  }

  found = 1 ;

  if(g_ar and t_ar and h_ar)
  {
     //writing to firebase
     Serial.println("got the set.. to fb now");
     Firebase.setFloat("GAS SENSORinst" ,gas_fb);
     Firebase.setFloat("HUMIDITY SENSORinst" ,hum_fb);
     Firebase.setFloat("TEMP SENSORinst" ,temp_fb);
     Firebase.pushFloat("GAS SENSOR" ,gas_fb);
     Firebase.pushFloat("HUMIDITY SENSOR" ,hum_fb);
     Firebase.pushFloat("TEMP SENSOR" ,temp_fb);
  }

  t_ar , h_ar , g_ar = false ;
  if (cu_st == "c")
  {
    sent = 0;
  }
  cu_st = Firebase.getString("feeder");
   if (cu_st == "o")
   {
    Serial.println("\t\trecd req to feed");
    if(sent == 0)
    {
      esp.print('o');
      sent =1;
      cu_st = "c";
      Serial.println("setting feeder to close in firebase");
      Firebase.setString("feeder" ,"c");

   }

  }
}

```

```//to arduino
#include <SoftwareSerial.h>

SoftwareSerial ArduinoUno(3,2);
#include<Servo.h>
#include "DHT.h"

//Servo feeder;

int send_rate = 30000; //every 30 secs send data
unsigned long last_time_stamp = 0;
unsigned long cur_time = 0;
unsigned long close_time = 0;
unsigned long open_time = 0;
#define led 13
int feeder = 0 ;
const int gas = 0;//gas sensor o/p
#define DHTPIN 8
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);

void setup()
{
  // put your setup code here, to run once:
  Serial.begin(9600);
  ArduinoUno.begin(4800);
  pinMode(led,OUTPUT);
  //feeder.attach(11);
  //feeder.write(85); //closing position
   dht.begin();

  pinMode (3,INPUT); //recieve from esp
  pinMode (2,OUTPUT); //transmit to esp

}

void feed_cmd()
{
  while(ArduinoUno.available())
  {
    char valve = ArduinoUno.read();
    Serial.print("feeder cmd recd ");
    Serial.println(valve);
    if(valve=='o')
    {
       digitalWrite(led, HIGH);
       //feeder.write(0); //open position
       open_time = millis();
       feeder = 1 ;
       Serial.println("I am opening feeder");
    }
  }
}

void close_feed()
{

  if(feeder == 1)
  {
   close_time = millis();
   if(close_time - open_time > 5000)
  {
    feeder = 0;
    digitalWrite(led , LOW);
    Serial.println("I am closing feeder") ;
  }
  }
}

void send_data()
{
  float h = dht.readHumidity();

  float t = dht.readTemperature();

  float raw_v = analogRead(gas);

  ArduinoUno.print("h");
  ArduinoUno.print(h);
  ArduinoUno.print(",t");
  ArduinoUno.print(t);
  ArduinoUno.print(",g");
  ArduinoUno.print(raw_v);
  ArduinoUno.print(",\n");
}

void loop()
{
  // put your main code here, to run repeatedly:

  feed_cmd();
  close_feed();
  cur_time = millis();
  if(cur_time - last_time_stamp > send_rate)
  {

    last_time_stamp = cur_time;
    send_data();

  }

}
```
[![here's a pic showing random char][1]][1]
Thanks for your time!!!

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

body:
I cannot really narrow down the source of your observed problems, since the problem descriptions are not clear enough. But there are some obvious problems/potential for making it better in your code.

In the Uno Code:

- It is totally unnecessary to use a timer interrupt for reading the SoftwareSerial interface. Instead you should write your `loop()` function non-blocking, meaning, that it does not wait for something to happen, but it will execute other code in the meantime (so no delay in `close_feed()`). Then you can just read the serial data in the loop function. You are saving a timer this way.

- In `send_data()` you are using the `String` class to concat a string of human readable data together and then send it. Using the `String` class in that way is evil, since on every concat operation it will allocate a new buffer for the string, deleting the old one. That makes Swiss cheese out of your heap memory (called heap fragmentation). That can lead to instability. Look at [Majenko's blog entry about the Evils of Arduino Strings][1] for more information. Instead of concatting you should simply print the information one after another:

        Serial.print("h");
        Serial.print(h);
        Serial.print(",t");
        Serial.print(t);

    and so forth.

- Your handling of the `millis()` function should be different. It will roll over after 52 days. To prevent, that your code misfunctions at that time, you need to always take the time difference:

        if(cur_time - last_time_stamp > send_rate)

    instead of

        if(cur_time > last_time_stamp + send_rate)

In the ESP Code:

- Your SoftwareSerial read code seems weird to me, but I think it should work. I would introduce a message protocol to the data stream, meaning to mark the end of a full message (a message containing one frame with all relevant data) with a special delimiter character, for example a newline character `\n`. Then you can read the message until this character into a buffer and then process the message as a whole.

---

That's about what I can say to this point. If you need a more focused answer, you have you describe further and more detailed the symptoms (what behavior you are seeing and what you expected).

  [1]: https://hackingmajenkoblog.wordpress.com/2016/02/04/the-evils-of-arduino-strings/


message:
Can we burn Arduino bootloader into any microcontroller chip?

I am new to this Arduino community
I noticed on youtube that while the prototype is complete people purchase new ATmega328p chips and flash bootloaders into them using in-system-programmers so that the chip could actually understand and interpret the instructions that are written in the high-level language if I am right(No I was wrong, it's actually the compiler that sits on Arduino). so I thought what if we could burn the atmega328p bootloader into any other microcontroller. So that we could program it in Arduino programming language(C/C++). Is this possible? sorry if I am dumb, but I wanted to know. And can anyone tell me whether could we use ATmega328p for production purposes(consumer electronics)? Thanks in advance.

body:
You cannot just load a sketch into any microcontroller, because every microcontroller has different memory layout, peripherals, ways of uploading, FLASH size etc.

You can use the atMega (or any microcontroller) for production purposes though. Of course each MCU type has operation conditions (like min/max temperature), so in e.g. automotive or military environments not all MCUs are allowed to be used, but for consumer electronics, afaik all MCUs can be used (meaning they will pass by themselves the needed certifications, which may not be true for components added and the circuit/enclosure resulting out of it).


body:
The answer needs to have multiple parts:

**Yes, in principle you can create a bootloader for any microcontroller, which acts like the Arduino's.**

Please be aware that there are different bootloaders, not just the common STK500 compatible one. Each of these bootloaders implements a certain protocol to transfer the binary code to the target system.

Additionally, some protocols also include commands to restart the microcontroller, to set configuration registers, and maybe more.

You need to read the bootloader's documentation to become familiar with its capabilities.

But it is your decision whether such a bootloader on a non-AVR system or an non-Arduino-AVR system is good for you.

**No, the bootloader does *not* enable the microcontroller to "understand" the high-level language.**

The standard Arduino IDE uses the specific compiler for the target microcontroller to translate the C++ source code to machine language. The resulting binary commonly runs on this target microcontroller only.

The bootloader just implements the protocol. In general, it is completely unaware of the meaning of the transferred data.

Microcontrollers in general use different processors with possibly different machine languages, contain different kinds of memory of different sizes, include different sets of different peripherals. But you know this for sure. You need to write and compile your source code for the specific part you're targeting.

**Yes, you can use ATmega328P for a consumer product, as Michel already said.**

You need to take the common measures that you take with *any* part of your product, though.


message:
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.

body:
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.


body:
1.initialize a global variable ```int failcount=0,MiFareCardMode=0;```

2. for reset put it in an if statement that checks fail count
      ```
         if(failcount==0)
                      {reset code}```
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");}

```


body:
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][1] 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]: https://arduino.stackexchange.com/questions/63488/wanted-to-control-2-servos-with-serial-read/63491#63491


message:
Determining which raw IR code to use for AC

I'm new on this so go easy on me.

I'm trying to make an IR blaster to control my TV and ACs. I realized that when I capture the IR code, power button/temp up and down/mode send raw codes that are almost similar to each other.

I've searched the net(maybe missed some answers) and came through [this][1]. The raw IR code provided on the blog did turned on my AC but I wasn't able to turn it off. So I think that the code isn't the power button. That's because I remember leaving the AC off at 23°C and when I send that code, my AC started at 20°C.

 So, how do I know which code to use for off, temp up etc? The codes I captured seems not to work when I send the codes to the AC. Nothing happened. No beep or anything. I'm using a GREE AC by the way.

Here's an example of the raw code that turned on my AC:

    uint16_t irACon1[139] = {9050, 4500, 800, 1600, 750, 550, 700, 550, 700, 1600, 750, 550, 700, 550, 700, 550, 700, 550, 700, 550, 700, 550, 700, 1600, 750, 550, 700, 550, 700, 550, 700, 550, 700, 550, 700, 550, 700, 550, 700, 550, 700, 550, 700, 550, 700, 1600, 750, 1600, 750, 550, 700, 550, 700, 550, 700, 550, 700, 550, 700, 1600, 750, 550, 700, 1600, 750, 550, 700, 550, 700, 1600, 750, 550, 700, 19950, 750, 500, 700, 550, 700, 550, 700, 550, 700, 550, 700, 550, 700, 550, 700, 550, 700, 550, 700, 550, 700, 550, 700, 550, 700, 550, 700, 1600, 750, 550, 700, 550, 750, 550, 700, 550, 700, 550, 700, 550, 700, 550, 700, 550, 700, 550, 700, 550, 700, 550, 700, 550, 700, 550, 700, 550, 700, 1550, 800, 550, 750, 500, 700, 1600, 750};

And few other codes that I had captured:

    Raw: (139) 9068, -4404, 708, -1580, 712, -488, 712, -484, 712, -1580, 712, -1580, 708, -1580, 712, -488, 708, -488, 708, -1584, 708, -1584, 708, -1580, 708, -492, 708, -488, 704, -496, 704, -492, 708, -492, 708, -492, 704, -492, 708, -492, 708, -488, 712, -488, 712, -1580, 708, -1580, 712, -488, 712, -484, 712, -488, 712, -488, 712, -484, 712, -1580, 712, -484, 712, -1580, 712, -484, 716, -484, 712, -1580, 712, -484, 712, -19848, 684, -512, 704, -496, 708, -492, 708, -488, 708, -492, 708, -488, 712, -488, 712, -488, 708, -488, 712, -488, 712, -484, 712, -488, 712, -488, 708, -1580, 712, -488, 712, -484, 712, -488, 708, -488, 712, -488, 712, -488, 708, -488, 712, -488, 708, -488, 712, -488, 712, -488, 708, -488, 712, -488, 708, -492, 708, -488, 708, -492, 708, -1584, 704, -1584, 708,

    Raw: (139) 8988, -4540, 556, -1736, 564, -688, 520, -676, 524, -652, 548, -1688, 600, -1688, 604, -648, 548, -652, 548, -1688, 604, -1684, 604, -1688, 604, -648, 548, -652, 548, -648, 548, -652, 548, -652, 548, -648, 548, -652, 548, -652, 548, -648, 548, -676, 524, -1688, 600, -1688, 604, -676, 520, -676, 524, -676, 524, -672, 524, -676, 524, -1712, 576, -680, 520, -1688, 604, -756, 440, -788, 412, -1688, 600, -816, 384, -20092, 468, -840, 348, -848, 352, -848, 352, -820, 384, -812, 388, -788, 412, -784, 412, -784, 416, -760, 440, -760, 436, -760, 440, -756, 444, -756, 440, -1824, 468, -780, 416, -760, 440, -756, 444, -728, 468, -732, 468, -728, 472, -700, 496, -704, 496, -700, 496, -676, 524, -676, 520, -652, 548, -648, 552, -624, 572, -624, 576, -620, 580, -1740, 548, -620, 580,

PS: Sorry for my bad English. And I somehow feel that the title isn't specific so let me know if there's a better title I should put.

**UDPATE**: Now the off and temp up is working but the temp is somewhat like an on button. It instantly put my AC on 23°C and won't increase when pressed multiple time. I understand that AC's remote fires the whole setup string when a button is pressed so which means different temps has different codes?

  [1]: https://myesp8266.blogspot.com/2016/05/keep-your-house-cool-with-esp8266.html

body:
It appears from the data you've posted, the remote is holding the presets for what the A/C unit needs to be doing when after every button is pressed.  This will keep the remote with LCD disply? in Sync with the A/C master.

Ie.  The remote is sending an entire setup string EVERY time ANY button is pressed.

Can you post a capture of an ON and OFF Raw's only?  Do not press any other buttons after pressing ON, or before pressing OFF.


message:
Reading DHT22 reboots arduino

I’ve got a quite weird behavior of DHT library.

I’ve got DHT22 sensor. If it’s signal cable is not connected, reading the sensor causes a problem: Arduino reboots or hangs in unpredictable places.

If I connect the signal cable again, the problem vanishes.

Is this normal behavior or some sort of bug? I think unsuccessful reading affects some part of Memory.

PS. The project is quite big and I can’t share the code here.

It happens that I found an evidence that dht object influences foreign memory. Look at this code:

    DV("pClock->isInited 3", pClock->isInited); // prints 1
    dht1.readHumidity();
    DV("pClock->isInited 4", pClock->isInited); // print 0 !!!!
    // nothing more can be called between these lines.

    // DV is a macro which prints label and value.
    // Both objects created before this.

    DHT dht1(11, DHT22);
    …
    dht1.begin();
    …
    pClock = new ZhClock(); // uses RTC_DS1307
    pClock->init(&rtc); // rtc is RTC_DS1307

body:
This problem is usual if you are in shortage of RAM.
Adafruit's libraries wastes lots of memory. You should be very careful to run their stuff if you are in shortage of memory.

I suggest you to try another library which quite old, but uses much lesser memory to read DHT sensor’s data:
https://github.com/markruys/arduino-DHT


message:
How to use any module that has no library for arduino?

I am 2 years old in this Arduino world.
I am currently working on a project where I am about to make use of a fingerprint sensor. Now my question is that could we be able to make use of a sensor that we usually find in our mobile phones with ATmega328p microcontroller chip. And what if that there were no libraries written for Arduino so that will make my life easier. And I wonder how these tech companies make use of any sensor they would like to use without any trouble while there is no existing textbook that taught these employees while pursuing a degree in CSE or ECE about how to write code for a particular sensor. Now I know that there are certain protocols like SPI, I2C, UART, etc. But how do they do it, and how do they know about microcontrollers and IC's that were never taught to them in any degree or course? I always scratch my head while looking at the consumer electronics, and the IC's and Chips that they have on their PCB board were never found on google, And by chance, if an IC or microcontroller is found then I barely understand the datasheet or the documentation which was written in Chinese or some other language. I hope someone could help me understand how all this happens.

body:
About the fingerprint sensors from mobile phones: You might find the answers to [this question][1] useful. They explain in detail, why it is not really worth the effort to try interfacing such a fingerprint sensor with Arduino.

> How to use any module that has no library for arduino?

You need to read the datasheet of the module. It should explain in detail, how the module is used. When you understood, how it works, (and understanding it is really really important) you can start implementing it in code, for example by writing your own library. A library is just a wrapper around the interfacing code for that module. If the module uses common used interfaces or is even a commonly used component, you can often stand on the shoulders of giants by making use of other libraries in your library (for example using the Wire library in a library for a specific I2C sensor). That makes it easier.

> But how do they do it, and how do they know about microcontrollers and IC's that were never taught to them in any degree or course?

The engineers don't get taught to use specific controllers or ICs. They get taught the fundamental principles, including common interfaces like I2C, SPI, UART, I2S ... . In the end it all comes down to the datasheet of a component. It should explain all details, that are needed to use the component correctly, or at least reference to further documents. For example most microcontroller datasheets directly explain, how I2C is implemented in these microcontrollers. You can use that to implement I2C communication, even without a preexisting library. Yes, that can be a tedious and complex task, but it is totally possible. Keep in mind, that most Arduino libraries are not written by the manufacturer of the used component, but by third party people (sometimes the community, sometimes resellers like Adafruit, e.g.).

I would say "it is not rocket sience", but yes, it can be rather difficult to dig into the very detail of interfacing a component. Without considering myself an especially smart guy, I'm writing a library for multi-master I2C communication on Attiny's (without having any degree in that field). I could start with code from others, which made the entry easier. But it also involves much time, to dig into it, write the code and test it correctly. It is difficult, but it is possible.

> And by chance, if an IC or microcontroller is found then I barely understand the datasheet or the documentation which was written in Chinese or some other language.

Good manufacturers and resellers provide a datasheet in english for their products. That cannot be said for every product, that you can purchase. Writing documentation takes time and thus costs money. Chips directly from China (where most electronics is produced these days) might have less good or no documentation at all, though these chips are often way cheaper. As a hobbyist you should stick to the good documentated components, if you don't want to really dig into it.

> the IC's and Chips that they have on their PCB board were never found on google

PCB designs are only found in the internet, if they are published under some open source license (or if they were illegally leaked by someone). If a company doesn't want to publish it's product designs, that is totally ok.

About the components in consumer electronics: I think you refer to that the chips often don't have a googleable product number/marking to find a datasheet. That is because often these chips are custom chips, made maybe only for this company or even this specific product. Why would they want to publish a datasheet for it? They are not meant for public use for all. The design of components is often a good kept secret, that the companies are not willing to share, since it generates their revenue.

Hobbyists and small companies use publicly available, good and publicly documented parts to make their life and investment in the project easier. Big companies can easily hire people to design a custom chip, that will only contain the needed features. (With mass produced products you can save money this way, by not always needing to buy even the unused resources of a standard controller). Another reason to use a custom (maybe even a not programmable) chip is to keep the code in it secret.

---

All in all keep in mind, that the hobbyist world of Arduino and the world of consumer electronics like smart phones are rather different. Sure, they rely on the same principles, but the way, how things are done and created, is very different.

  [1]: https://arduino.stackexchange.com/questions/68807/interface-a-mobile-phones-finger-print-scanner-with-arduino/68810#68810


message:
Do we have to calibrate LDR before using it in a project?

I am doing a [project][1] with Arduino, making a synthesizer, in which an LDR is used.

Before connecting the Arduino to a power source and use the project, do I need to calibrate the LDR like it is explained in Arduino [website][2] ?

  [1]: https://www.instructables.com/id/The-Arduino-Synthesizer/
  [2]: https://www.arduino.cc/en/tutorial/calibration

body:
An LDR is a pretty inaccurate device. It just gives you a number which relates to darkness or brightness. How do those numbers relate to darkness and brightness? Well, only in a very vague way. All you can really say with any confidence is that bigger numbers mean brighter light, and smaller numbers mean darker darkness.

Even after "calibration" the numbers are pretty meaningless in any real-world sense.

All the "calibration" does is give a rough guide to the range of the numbers produced in any given lighting situation. It's then up to you to program your sketch in such a way that it works within the ranges of those numbers.

And yes, those numbers will change depending on the current lighting situation.

You could incorporate some form of "calibration" routine in your sketch to adjust any relevant values and calculations, or you could just provide some interface for tweaking values. Or your system may just really not care. It's impossible to know until you actually start creating your system.


body:
My application was a little different. My illumination/light source was fixed (and exact). I compensated the sensor for temperature. The results I obtained were very exact and repeatable.

Here are my temperature compensation results.

[![Temp Compensation of LDR sensor][1]][1]

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


message:
Random characters transmitted from ESP8266 to Arduino

Below is  the code for getting a value from Firebase and sending the received data to arduino for performing necessary action.
The code here here sends a string ```"o"``` to arduino once
```
//uploaded to ESP8266
.
.
.
if (cu_st == "c")
  {
    sent = 0;
  }
  cu_st = Firebase.getString("feeder");
   if (cu_st == "o")
   {
    Serial.println("\t\trecd req to feed");
    if(sent == 0)
    {
      esp.print("o");
      sent =1;
      cu_st = "c";
      Serial.println("setting feeder to close in firebase");
      Firebase.setString("feeder" ,"c");

   }
.
.
.
```
Below is the code that gets the value, carries out necessary actions.

```
//uploaded to arduino
.
.
.
void feed_cmd()
{
  while(ArduinoUno.available())
  {
    char valve = ArduinoUno.read();
    Serial.print("feeder cmd recd ");
    Serial.println(valve);
    if(valve=='o')
    {
       digitalWrite(led, HIGH);
       //feeder.write(0); //open position
       open_time = millis();
       feeder = 1 ;
       Serial.println("I am opening feeder");
    }
  }
}

void close_feed()
{

  if(feeder == 1)
  {
   close_time = millis();
   if(close_time - open_time > 5000)
  {
    feeder = 0;
    digitalWrite(led , LOW);
    Serial.println("I am closing feeder") ;
  }
  }
}
.
.
.
```

My expectation/understanding is that:

```feed_cmd()``` continually checks for any data
As soon as it receives data LED turns ON and after 5 sec ```close_feed()``` turns OFF the LED.

But what happens is that the ```while()``` in ```feed_cmd()``` continually executes showing some random data and also all of what I said above is also being carried out! (pic attached)

[![showing data received][1]][1]

[![showing action taken][2]][2]

Why is there random serial data, even after sending only once and even after reading the sent data?

Is it bad coding / hardware?

Thanks for reading through and would really appreciate it if you can help me sort it out!!

__Edit__ I found this link [smthg abt pin voltages ][3] when I was looking for possible explanation for my code's behaviour, If somebody can simplify it and explain it, it'd be better !!

  [1]: https://i.stack.imgur.com/JdtZ1.jpg
  [2]: https://i.stack.imgur.com/ssvnG.jpg
  [3]: https://forum.arduino.cc/index.php?topic=356079.0

body:
The baud rates, voltages, and timing all have to match up for serial communication to work right.

So, set both of your devices to the same baudrate (you specify the number in Serial.begin()), and ensure they're connected properly. (voltages match, TX to RX, and ground is connected)

You can just read/print the serial input to the arduino with something like Serial.print(softSerial.read()) in your code if you think you don't have serial wired up right.

Also in an unrelated issue; the esp32 spits out data on its main serial line at 115200 when it boots up which you can not disable. you can use the serial port afterwards though.

Here's a copy of what gets printed out on one of mine;

    rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
    configsip: 0, SPIWP:0xee
    clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
    mode:DIO, clock div:1
    load:0x3fff0018,len:4
    load:0x3fff001c,len:1044
    load:0x40078000,len:8896
    load:0x40080400,len:5816
    entry 0x400806ac


message:
i am having Strange issues when trying to read form gps serial connection

I have an Adafruit Ultimate GPS connected to a MEGA2560. I am trying to get the data from the buffer and do other data processing at the same time, however. when i allow other processing to be done the output becomes garbled such as below. the first out is correct and then becomes garbled and outputs now useful data.

16:34:54.466 -> $GPGGA,163453.155,,,,,0,00,,,M,,M,,*7F

16:34:57.111 -> $GPRMC,163453.155,V,,,,$GP$GPGGA,1$GPGGA,$GPGGA

```Arduino

    void loop()
    {

    GetTotalPressure();
      char c = GPS.read();
      Serial.print(c);
       if (GPS.newNMEAreceived()) {

        if (!GPS.parse(GPS.lastNMEA()))   // this also sets the newNMEAreceived() flag to false
          return;  // we can fail to parse a sentence in which case we should just wait for another
      }
      if (timer2 > millis())  timer2 = millis();

      if (millis() - timer2 > 1000) {
        timer2 = millis(); // reset the timer
    GPSScreenUpdate();
      SDcardSave();

      }
```

When GetTotalPressue is commented out The GPS serial output is correct when it is no the error above happens.

GetTotalPressure is below the sensor is connected to a I2C bus

    void GetTotalPressure() {
      Totalpressure = ms5611.readPressure();

Many Thanks

body:
You are not reading the GPS often enough. The method
`Adafruit_GPS::read()` is documented in the [comments embedded in the
source code][doc]:

> Read one character from the GPS device.
>
> Call very frequently and multiple times per opportunity or the buffer
> may overflow if there are frequent NMEA sentences. An 82 character
> NMEA sentence 10 times per second will require 820 calls per second,
> and once a loop() may not be enough. Check for newNMEAreceived() after
> at least every 10 calls, or you may miss some short sentences.
>
> returns: The character that we received, or 0 if nothing was available

Accessing the I2C bus makes `loop()` slower, slow enough that you get a
buffer overflow, as explained above. I suggest that, instead of reading
a single character per loop iteration, you read as many as are present
in the buffer:

```c++
void loop()
{
    GetTotalPressure();

    // Empty the GPS port receive buffer.
    while (GPS.available()) {
        char c = GPS.read();
        Serial.print(c);
    }

    // Parse any newly received NMEA sentence.
    if (GPS.newNMEAreceived()) {  // clears the newNMEAreceived flag
        if (!GPS.parse(GPS.lastNMEA()))
            return;
    }

    // Display and log location every second.
    if (millis() - timer2 > 1000) {
        timer2 = millis(); // reset the timer
        GPSScreenUpdate();
        SDcardSave();
    }
}
```

As an aside, I removed the line

```c++
if (timer2 > millis()) timer2 = millis();
```

which serves no useful purpose. If you are trying to detect `millis()`
overflows, [you are almost certainly doing something wrong][millis].

[doc]: https://github.com/adafruit/Adafruit_GPS/blob/96625de7d35302294ee648af6a050332e0d30186/src/Adafruit_GPS.cpp#L352-L359
[millis]: https://arduino.stackexchange.com/questions/12587/how-can-i-handle-the-millis-rollover


message:
ESP8266 not working with MPU 6050 over wire library and I2C

I'm trying to use this version of ESP8266 to access MPU 6050. However, it's not working.

https://www.amazon.com/gp/product/B07HF44GBT/ref=ppx_yo_dt_b_asin_title_o07_s00?ie=UTF8&psc=1 i.e. NodeMCU CP2102 ESP-12E

The code worked with nano very fine. However, when I tried to scan the I2C device, it's said I2C device not found.

I have tried

      Wire.begin(D2, D1);

and

      Wire.begin(4, 5);
i.e. to change the pin to GIOP 4 5 in case if the default was not working.
I have also tried to put a large capacitor between the power lines, still not working.

Why ESP8266 does not work with MPU 6050?(Serial and wire together)

**Updates:**
Sometimes it does say device found, but after two updates, it turned to be not found again.

**Updates 2:**
I watched [the video][1] and did what G6EJD suggested, i.e. restarted the IDE and everything. Now it's reading data. However, the data reading was somehow incorrect by a large factor.
For example, at flat the device is reading

    42.63/-38.37/7.82

for angle x,angle y,and angular speed z with complementary filter applied and steady at flat surface. It worked for nano but not for ESP 8266.

Also, I tried to adjust the circuit like the spectrum dandavis suggested. I tried resistor range from 4.7 k to 10, even directly connect to the power source. The attempts also included 100 $\mu$F capacitor and power board to stabilize the noise. Both pull up and pull down has been attempted as well as changing boards. However, none of those were working and the issue persisted. The pull up resistor did not seem to be response to what the device was reading.

**Update 3:**
The power consumption has been ruled out and a pair of 100k resistor was also attempted. Not working.

  [1]: https://www.youtube.com/watch?v=F4lzRPF7o0I

body:
try to use

    Wire.begin(0x68);

instead of

      Wire.begin(D2, D1);


body:
I've been struggling with getting anything with the MPU6050's to work with either a D1 Mini or an older NodeMCU v1. I'm using D1/D2.
I've used the i2cdevlib MPU6050 library as well as the Electronic Cats' version.
I've used an assortment of sketches and even tried code which uses just Wire (no MPU6050 specific libs).
* The best I've been able to get is the Electronic Cats MPU6050 library, without DMP, where at least it thinks the MPU6050 has been connected to, but it just puts out 0's as raw values.
* The second "best", maybe, was some code that just used plain Wire, but except for Wire.endTransmission() returning success (and I had to slow loop() down for that), its numbers are gibberish (either 0's, or Z will just increment.  Nothing is affected by the movement of the board itself).

The DMP versions always fail to initialize the DMP.
I've tried 8.2k and 4.1k pullups on D1 and D2.

It works fine on an atmega32u4-based Pro Micro 16.


message:
How can I set up outputs without using digitalWrite?

Consider the following:

    #define IN1 9
    #define IN2 10

    pinMode(IN1, OUTPUT);
    pinMode(IN2, OUTPUT);

    void LeftMotor(Direction direction) {
      digitalWrite(IN1, direction == Forward ? LOW : HIGH);
      digitalWrite(IN2, direction == Forward ? HIGH : LOW);
    }

How can I modify the `LeftMotor` method to achieve the same result without using digitalWrite?

body:
Setting ports directly is a great way to learn AVR programming. I might recommend this book [Make: Avr Programming.][1]

  [1]: https://www.amazon.com/AVR-Programming-Learning-Software-Technology/dp/1449355781

First you need to set the direction of the port in the Data Direction Register as either input or output. If Input, check its state and handle it. Here is a small example.

    #define HIGH 1
    #define LOW 0

    #define  SWI_PIN PORTB0
    #define  BUTTON PORTB4

    int main (void)
    {
        // set the pin directions
        DDRB |=  (1 << SWI_PIN); // output
        DDRB &= ~(1<<PORTB4); //input
        while(true){

          if ((PINB & (1<<BUTTON)) == 0){ // pin is high! Rising edge
              PORTB &= ~(1<<SWI_PIN); // LOW turn off swi_pin
          }else {
              PORTB |= (1<<SWI_PIN); // HIGH  turn on swi_pin
          }

    }


body:
`digitalWrite()` is just a convenience function to hide away complexity from the user, so that she/he can just use a pin number and a value. This complexity takes some time to execute. If this is too slow for you, you need to go a bit deeper into the rabbit hole and use direct port manipulation:

Inside the microcontroller on the Arduino all the special functions for peripherals and such (digital IO, ADC, Serial(UART), SPI, Timer, ...) are configured via Special Function Registers (SFR). These are specific memory places, that are directly connected to the peripherals. You can configure the whole microcontroller by setting these registers to specific values.

For digital IO you first need to know, that the microcontrollers pins are ordered into groups of max 8 pins. These groups are called Ports. Each available port of the microcontroller gets a character, like PORTB. On the Arduino Nano for example PORTD includes the pins 0 to 7.

For each port we have 3 different SFRs (with the x being the character for the corresponding port), where each bit inside the registers corresponds to one pin:

- `DDRx` controls the direction of the pins. If you set a bit to 1 in there, the corresponding pin is set as output. If you set it to zero, the pin will be an input (which is also called High-Z for high impedance, because a digital input pin has a very high resistance).

- `PORTx` controls the output hardware of the digital pins. If you have set a pin as output (as described above) you can use the corresponding bit in the `PORTx` register to set it's state. If you write a 1 to the bit, the pin will become HIGH (means, the voltage on the pin will go to the same level as Vcc, the supply voltage of the micrcontroller). If you write a zero, the pin will go to LOW (meaning the same level as ground). The `PORTx` register has a different function, when you configured a pin as input. In this case, a 1 will turn on the interal pullup resistor of the pin, which pulls the level of the pin to HIGH, when nothing is pulling it down to ground (like a switch for example). A zero disables the pullup.

- `PINx` reflects the current state of the pins. If you configured the pins as input, this is the voltage level, that currently lies at the corresponding pin (about the actual voltage levels, see below). A 1 at a bit means, that the corresponding pin is HIGH, else it is LOW.

You can read all of this in the datasheet of the used microcontroller. The datasheet is a must read (at least the relevant chapters), if you want to control the microcontroller via its registers. In most microcontrollers these registers are named as above. But some microcontrollers might define other names. The corresponding datasheet will list all the registers with rather detailed descriptions.

Now let's take that knowledge into actual code. Here I assume an Arduino Nano, though you can exchange that for most other microcontrollers.

    // Configure pin D3 as output
    DDRD |= (1 << PD3);
    // Configure pin D2 as input
    DDRD &= ~(1 << PD2);
    // Check, if pin D2 is HIGH
    if(PIND & (1 << PD2)){
        // Set pin D3 to HIGH
        PORTD |= (1 << PD3);
    } else {
        // Set pin D3 to LOW
        PORTD &= ~(1 << PD3);
    }

---

**Excourse on bitwise operators:** The code above can only be understood by knowing bitwise operators, which are very important for direct port manipulations. I will break down the operations, that are done there:

- First we have `PD2` and `PD3`. These are defines from the Arduino core. They are set to the index of the bit, that corresponds to the named pin. So `PD2` is defined as 2, `PD3` is defined as 3, `PD0` as 0.

- `1 << PD3`: The `<<` operator does a bitwise left shift, which means all bits of the value on the left are shifted to the left by the amount standing on the right of the operator. We shift the value 1 three digits to the left here. In binary that looks like this:

        0b00000001 << 3 = 0b00001000

    That set bit in the result is exactly at the place, where the bits for pin PD3 will be in the Special Function Registers.

- `DDRD |= (1 << PD3)`:  This is the same as doing `DDRD = DDRD | (1 << PD3)`, so the `|=` operator is just an abbreviation for it. The bitwise OR operator `|` will unite the bits from both sides. If a bit is set to 1 at either side, the result will also have set this bit to 1. This means, that we can set a bit to 1 with this.

- `~(1 << PD2)`: The tilde `~` takes the inversion of the data. Alike above, the value inside the paranthesis can be written as binary value `0b00000100`. The inversion will flip all bits to the other value: `0b11111011`

- `DDRD &= ~(1 << PD2)`: The abbreviation is similar to the above. The bitwise AND operator `&` will also unite the bits of the values around it, but it will only set the resulting bits to 1, if both of the corresponding bits of the values are also set. Here this results in the third bit (the one for D2) being cleared to zero. All other bits (where you can see a 1 at the right value) are left untouched.

- `PIND & (1 << PD2)`: This is similar to the above, but now we don't have an inversion. We are doing `PIND & 0b00000100` here. All bits of the result will be set to zero, except for the bit for D2. It will only be zero, if the corresponding bit was zero in `PIND`. Thus we have isolated the needed bit by this way.

You can also combine the same operations on a single register. Let's say we want to set both D2 and D3 as output. Then we can either write this as two seperate statements

    DDRD |= (1 << PD2);
    DDRD |= (1 << PD3);

or we can combine them into one statement by connecting them with the bitwise OR

    DDRD |= (1 << PD2) | (1 << PD3);

---

The [Arduino documentation][1] also provides a site to explain direct port manipulation. Also again you should take the time to look into the datasheet of your used microcontroller. At first it will seems very difficult, but doing these direct port manipulations is a great way of learning how to use the SFRs, and then you can do all sorts of cool stuff with your microcontroller. So it really is worth it. You don't need to read or understand the whole datasheet at once.

---

> How can I modify the LeftMotor method to achieve the same result without using digitalWrite?

After all this text now to the specific question. On the Nano pin 9 and 10 are PB1 and PB2. You used a conditional inside your `digitalWrite()` statement, which I will replace by a complete if statement here. So you can use

    if(direction == Forward){
        PORTB &= ~(1 << PB1);
        PORTB |= (1 << PB2);
    } else {
        PORTB |= (1 << PB1);
        PORTB &= ~(1 << PB2);
    }

instead of your two `digitalWrite()` statements.

  [1]: https://www.arduino.cc/en/Reference/PortManipulation


body:
chrisl provided a very good reference answer. Here I am just adding a
few bits of information about the pin mapping and the pin electrical
states.

## Pin mapping

One of the firs things you need when dealing with direct port access is
the mapping between the Arduino pin names and the names of the
microcontroller (MCU) pins as given by the manufacturer. For the Arduino
Nano the mapping is the following:

```text
 Arduino │ MCU
─────────┼─────
   RX0   │ PD0
   TX1   │ PD1
   D2    │ PD2
        ...
   D7    │ PD7
   D8    │ PB0
        ...
   D13   │ PB5
   A0    │ PC0
        ...
   A5    │ PC5
```

where “PD0” means “pin number 0 of port D” and so on. Notice that pins
A6 and A7 are not listed here, as they are analog only, with no digital
I/O capability.

The information above can be found on the product page of the board,
under the “Documentation” tab. Alternatively, an image search for
“Arduino <board name> pinout” will find some nice schematics like
the one below:

[![Arduino Nano pinout][1]][1]

## Pin states

This has already been covered by chrisl's answer in the description of
the `DDRx` and `PORTx` registers. Below is a summary table showing the
four available electrical states of the pins, and how they are selected
with the DDR and PORT bits:

```text
 DDR │ PORT │ electrical state │ equation
─────┼──────┼──────────────────┼─────────────────
  0  │   0  │  INPUT (high-Z)  │ I = 0
  0  │   1  │  INPUT_PULLUP    │ V = Vcc − Rpu I
  1  │   0  │  OUTPUT LOW      │ V = 0
  1  │   1  │  OUTPUT HIGH     │ V = Vcc
```

The provided equations relate the output voltage (V) and the output
current (I) of the pin. Beware that these are just rough approximations,
as:

 * they neglect the output resistance, which is of the order of
   25 Ω
 * an input pin can have some (sub-µA) leakage current
 * the pullup resistor is not completely linear
 * the datasheet only provides weak guaranties, such as a range for the
   output voltage, conditioned on the output current being low enough.

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


body:
> How can I set up outputs without using digitalWrite?

So this question is actually about the fastest possible implementation of digitalWrite.

As described in other answers this can be achieved by using direct port manipulation. But there are actually libraries (for instance, https://github.com/mikaelpatel/Arduino-GPIO) that does this in a portable way and avoids some of the errors that can occur. The library is 10-100X faster than the Arduino core digital pin functions.

Pins in a MCU are organized in ports. On the AVR there are a set of 8-bit port registers that hold the current pin setting. To change the value of a pin the CPU has to read the register and change the corresponding bit associated with the pin. This has to be done as an atomic operation, i.e. an interrupt may not occur during the update of the port register.

To allow a very fast update, i.e. one instruction/1-2 clock cycle, the CPU has a set of special instructions. For the AVR there are bit set and clear instructions for the 32 first special registers. On the Arduino Mega some of the pins/ports have higher address special registers and cannot use the special instructions. To make the pin operation atomic explicit interrupt handling must be added.

Other issues with direct port manipulation is portability. Code written using the AVR io handling cannot be used on SAM (e.g. Arduino Due). There is actually even issues when changing between AVR MCUs.

In short, a portable faster implementation of digital pin functions is recommended.

Below is the code written with the [GPIO][1]. It is portable and as fast as direct port manipulation.

    #include "GPIO.h"

    GPIO<BOARD::D9> IN1;
    GPIO<BOARD::D10> IN2;

    IN1.output();
    IN2.output();

    void LeftMotor(Direction direction) {
      IN1 = (direction == Forward ? LOW : HIGH);
      IN2 = (direction == Forward ? HIGH : LOW);
    }

or

    void LeftMotor(Direction direction) {
      IN1 = direction != Forward;
      IN2 = direction == Forward;
    }

or

    void LeftMotor(Direction direction) {
      if (direction == Forward) {
        IN1.low();
        IN2.high();
      }
      else {
        IN1.high();
        IN2.low();
      }
    }

  [1]: https://github.com/mikaelpatel/Arduino-GPIO