body:
The "final" form of an Arduino "project" is not an Arduino project at all.

Arduino and the associated shields and breadboards are just development tools. They are intended to be used *during development* only.

As soon as you want to take the next step (certainly if you don't want to be laughed at by professionals) and create a product you need to learn about building your own PCBs. That means taking the schematics of all the shields and boards you are using and combining them all into one schematic, then designing a board from that schematic - and that, of course, means being able to understand what a schematic means.

It's kind of like taking the step from playing with LEGO® to building a house (or a garden shed maybe). There's a lot of learning you have to go through between the two stages.

There are plenty of online resources to get you started with schematic design and PCB layout, but to do it properly takes years of proper training. If you are serious about moving from just tinkering as a hobby you should consider formal training with a reputable educational establishment.


sender: user

message:
How can I pulse a stepper motor whilst also wanting to handle other tasks?

A Polulo [`A4988`](https://www.pololu.com/product/1182) driver board listens for a `LOW -> HIGH` pulse on a digital pin to step a stepper motor.

A simple way to pulse this with a delay of say `100μs`, is to use the `delayMicroseconds` function:

    #define STEP_PIN  3
    #define DELAY     100

    void setup(){
        pinMode(STEP_PIN, OUTPUT);
    }

    void loop(){
        //heavy computation taking time
        digitalWrite(STEP_PIN, LOW);
        digitalWrite(STEP_PIN, HIGH);
        delayMicroseconds(DELAY);
    }

Although this works, the issue is that all the time that the processor spends in the `delayMicroseconds` function is *wasted*. This means that if I wanted to, for example, handle inputs from a serial line, I would have no time to do this. In addition, the time for these computations to complete would result in the pulse time increasing which is not ideal as the speed of the stepper would no longer be uniform.

How can I efficiently pulse the stepper at the correct time, whilst leaving my self room to run other tasks between pulses?

---

P.s. This is for this project: https://github.com/joeiddon/chess_robot.

sender: assistant

body:
Instead of delaying between pulses, loop around the main `loop()` function as fast as possible *constantly checking the time to see if we should pulse the motor*.

This means that computations can occur in the loop (so long as they are reasonably fast).

To implement this, the `micros()` function can be used to get an unsigned long representing the microseconds that have passed since the start of the program.

Then in each loop cycle, we need to check if the difference between the current time and the last time that we pulsed is `>=` the pulse delay. In which case, we send a pulse to the motor

However, instead of setting the last pulse time variable to the current time, we instead increment the last pulse variable by the delay time. This has the affect that even if we were slightly late in pulsing, we pretend that we *did* in fact pulse at the right time so that they do not drift over time.

This would look something like:

    #define STEP_PIN  3
    #define DELAY     100

    uint32_t last_pulse;

    void setup(){
        pinMode(STEP_PIN, OUTPUT);
        last_pulse = micros();
    }

    void loop(){
        //heavy computation taking time
        if (micros() - last_pulse >= DELAY){
            last_pulse += DELAY;
            digitalWrite(STEP_PIN, LOW);
            digitalWrite(STEP_PIN, HIGH);
        }
    }

---

*Note that there is a slight subtlety here in that the result from `micros()` and therefore the value of `last_pulse` will overflow after [`~70` minutes](https://www.arduino.cc/reference/en/language/functions/time/micros/). However, because we are taking a __difference__ of two unsigned numbers, this method [will still work](https://stackoverflow.com/questions/2061245/how-to-subtract-two-unsigned-ints-with-wrap-around-or-overflow), so long as `micros()` is never a whole cycle ahead of `last_pulse` which in practice will never be the case.*


message:
Nodemcu 1.0 and boot mode (1,6) after soft reset

I have a problem with a nodemcu 1.0 (lolin) board. Sometime a soft reset is performed from the watchdog and the board freezes in boot mode (1,6) (I have to manually reset the board to restart it).
I have read many thinks on this topic and I have carefully avoided to use the GPIO0, GPIO2 and GPIO15. I have also verified that these pins are correctly pulled-up (GPIO0 and GPIO2) and pulled-down (GPIO15) but when the board frezes I have noticed that the voltage of the GPIO0 is not 3.3V but 2.0V.
Has anybody experienced a similar problem? Could you help me in solving it?

I wish you all a happy new year.
Cheers.

body:
The esp8266 has [a bug][1] (documented). After Serial upload the program is started without reset and then at soft reset the state of "start bootloader" is still active.

  [1]: https://github.com/esp8266/Arduino/issues/4057


message:
Software serial conflict with WiFi on ESP8266

I'm trying to use an ESP8266 (Wemos D1 mini) to read from a 19.2K serial port and report the results over WiFi. Programming is via Arduino IDE. The code to read the port works just fine if WiFi is not enabled. Once WiFi is enabled I lose chars from the input stream. I've seen several posts in various places that point to problems with using SoftwareSerial and WiFi at the same time, apparently having to do with timing conflicts. My latest attempt calls

    WiFi.disconnect();

before the code that reads the chars from the serial stream, then calls

    WiFi.reconnect();

after reading the serial stream but before making the calls to send data over the web. This did not work.

My code is reading from the serial port in a (blocking) loop, which other posts suggest is the problem. This is not a problem when there is no WiFi object connection. I could restructure the code to create a non-blocking read, but that would be a significant effort (and make the code much harder to understand), so before I go that route I'm wondering if there is a different solution.

body:
WiFi uses interrupts. Alot. SoftwareSerial doesn't work well with interrupts.  On the Arduino all interrupts are disabled while SoftwareSerial does its work. I don't know how it is implemented on the ESP8266, nor how interrupts operate on the ESP8266, so cannot comment on how to work around it.

However, if you can't use one of the hardware UART channels then maybe you need to start thinking outside the box. And by "the box" I mean "the ESP8266".

Maybe the ESP8266 isn't for you. It's a great chip for making a WiFi interface, but it's not good for much else. It simply lacks the internal peripherals to be useful.  Maybe upgrading to the ESP32 would be a good option for you (that's the ESP8266's big brother). It has a far more feature-rich peripheral set.

Also don't be afraid of using more than one microcontroller. If the ESP8266 doesn't have the interfacing you need then add another MCU to it which does have the interfacing you need - and then get them to communicate using whatever interface you *do* have available (I2S, SPI, etc).  Yes, it means more programming and a more complex project, but learning such things will certainly unlock more doors for future projects.


body:
As noted, there are conflicts between Wifi and SoftwareSerial. The attempt in the question to disconnect WiFi is a step in the right direction, but not enough. You have to actually turn off the WiFi. The challenge is to reliably shut down the WiFi and then start it up again. This has been discussed extensively in the ESP8266/Arduino Git repository [here][1] and is referred to by some as "Issue 644".  An sample implementation of the code to reliably is presented [here][2].

Here's what the on/off functions look like. I strongly urge you to go to the code linked above and copy from there rather than here, though.

    extern "C" {
    #include "user_interface.h"
    #define WIFI_RETRIES 25

    int conn_tries = 0;
    bool WiFiOff() {
        WiFi.disconnect();
        WiFi.mode(WIFI_OFF);
        WiFi.forceSleepBegin();
        yield();

        /*
         * It can take a while for the ESP to disconnect, so we need
         * to give it a couple of seconds before returning a fail.
         */
        while ((WiFi.status() == WL_CONNECTED)
               && (conn_tries++ < WIFI_RETRIES)) {
            delay(100);
    #ifdef DEBUG
            Serial.print(".");
    #endif
        }
        if (WiFi.status() != WL_CONNECTED)
            return (true);
        else
            return (false);
    }

    /*
     * Turn the WiFi back on again with forceSleepWake().
     * NOTE:-  =Your= SSID and password must be in the
     *         user_config.h file.
     */
    bool WiFiOn() {
        conn_tries = 0;

        WiFi.forceSleepWake();
        WiFi.mode(WIFI_STA);
        wifi_station_connect();
        WiFi.begin("corazon_del_bosque", "");

        /*
         * It may take a while for the ESP to re-connect, depending
         * upon external factors (e:- has the access-point moved out
         * of range since we were last connected?).  This loop will
         * give us a reasonable time to re-connect without blocking
         * permanently.
         */
        while ((WiFi.status() != WL_CONNECTED)
               && (conn_tries++ < WIFI_RETRIES)) {
            delay(100);
    #ifdef DEBUG
            Serial.print(".");
    #endif
        }
        if (WiFi.status() == WL_CONNECTED)
            return (true);
        else
            return (false);
    }

I'm using this code in my program via the Arduino IDE. The author used it in PlatformIO. Other build systems may have other requirements.

  [1]: https://github.com/esp8266/Arduino/issues/644
  [2]: https://github.com/PuceBaboon/ESP_Power_Save


message:
How to blink led and run another code at same time?

I had written a code to calculate rpm of the motors using IR sensor and
Arduino nano and displaying it on OLED . With that I want an LED to
blink always. Here is the code what I did:

You can **skip** the declarations and `setup()` part. Just move directly
to `loop()`. I have **problem in loop**. In `loop()`, only LED goes on
blinking and further rpm calculation with OLED displaying codes are not
performed.

    #include "avr/sleep.h"
    #include "avr/power.h"
    #include "SPI.h"
    #include "Wire.h"
    #include "Adafruit_GFX.h"
    #include "Adafruit_SSD1306.h"

    #define OLED_RESET 4

    Adafruit_SSD1306 display(OLED_RESET);

    int led = 12;
    int in = 13;
    int pushbutton=10;
    unsigned long duration = 0;
    float rpm = 0;
    float rpm_a = 0;
    int counter = 0;
    int present = 0;
    int previous = 0;
    unsigned long elapsed = 0;
    unsigned long elapsed_prev = 0;
    int disabled = 0;

    void setup() {
        Serial.begin(9600);
        pinMode(led, OUTPUT);
        pinMode(in,INPUT);
        pinMode(pushbutton,INPUT);
        display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
        display.clearDisplay();
        display.setTextSize(1);
        display.setTextColor(WHITE);
        display.setCursor(35,1);
        display.print("xyz");
        display.display();
        display.setTextSize(2);
        display.setTextColor(WHITE);
        display.setCursor(25,13);
        display.print("abc");
        display.display();

        delay(5000);

        display.clearDisplay();
        display.setTextSize(1);
        display.setTextColor(WHITE);
        display.setCursor(0,0);
        display.println("RPMmeter");
        display.display();
        display.setTextSize(2);
        display.setTextColor(WHITE);
        display.setCursor(0,19);
        display.println("RPM:");
        display.setCursor(80,19);
        display.println(rpm);
        display.display();

        elapsed = micros();
    }

    void loop()
    {
        /** led blink part **/
        digitalWrite(led, HIGH);
        delay(70);
        digitalWrite(led, LOW);
        delay(70);
        digitalWrite(led, HIGH);
        delay(70);
        digitalWrite(led, LOW);
        delay(900);

        /** led blink part over and rpm calculation and displaying on
         * oled part starts **/

        if(digitalRead(pushbutton))
        {
            //Arduino low power enabled
            if(disabled==0)
            {
                sleep_disable();
                disabled = 1;
            }
            if (digitalRead(in) == 1 && previous == 0)
            {
                previous = 1;
                duration = elapsed - elapsed_prev;
                elapsed_prev  = micros();
            }
            if (digitalRead(in) == 1 && previous == 1)
            {
                previous = 1;
            }
            if (digitalRead(in) == 0 && previous == 1)
            {
                previous = 0;
            }
            if (digitalRead(in) == 0 && previous == 0)
            {
                previous = 0;
                elapsed = micros();
            }

            rpm = 60000000/duration;

            //We add a small error in the rpm value (in this case +-2)
            if ((rpm_a-2) < rpm  &&  rpm < (rpm_a+2))
            {
                rpm_a = rpm;
                counter = counter + 1;
                if (counter == 50)
                {
                    display.clearDisplay();
                    display.setTextSize(1);
                    display.setTextColor(WHITE);
                    display.setCursor(0,0);
                    display.println("JARVIS RPMmeter");
                    display.setTextSize(2);
                    display.setTextColor(WHITE);
                    display.setCursor(0,19);
                    display.println("RPM:");
                    display.setCursor(80,19);
                    display.println(rpm);
                    display.display();
                    counter = 0;
                }
            }
            if (!( (rpm_a-2) < rpm  &&  rpm < (rpm_a+2)))
            {
                rpm_a=rpm;
            }

        }//end if pushbutton=1
        else {
            display.display();
            display.clearDisplay();
            delay(10);
            duration = 0;
            rpm = 0;
            rpm_a = 0;
            counter = 0;
            present = 0;
            previous = 0;
            //Arduino low power enabled
            set_sleep_mode(SLEEP_MODE_PWR_DOWN);
            sleep_enable();
            disabled = 0;
        }
    }

This was the code. The problem is **without** that led blinking code
part in the **loop**, the code works fine, but if we include that LED
blinking part, the code *doesn't move further*. I mean only LED goes on
blinking and further codes are *not performed*. Why is it so? And how to
make both **rpm calculation with display on OLED** as well as **LED
blinking** happen through a single code simultaneously?

body:
While executing the 'Delay' commands your arduino doesn't really do anything. The best thing you can do is have a look at [BlinkWithoutDelay][1] and adapt your code accordingly.

  [1]: https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay


body:
There are a few options to use millis() for this.
Is it okay if I change the 900ms into a multiple of 70ms? Then I can count intervals of 70ms.

    // blink led: 70ms on, then 70ms off, then 70ms on, then 910ms off

    unsigned long previousMillis;
    int count = 0;

    void setup() {
      pinMode(13, OUTPUT);
    }

    void loop() {
      unsigned long currentMillis = millis();

      if(currentMillis - previousMillis >= 70) {
        previousMillis = currentMillis;

        switch(count) {
          case 0:
            digitalWrite(13, HIGH);
            break;
          case 1:
            digitalWrite(13, LOW);
            break;
          case 2:
            digitalWrite(13, HIGH);
            break;
          case 3:
            digitalWrite(13, LOW);
            break;
        }
        count++;

        if(count >= 16)
          count = 0;
      }
    }

When the values of the intervals are in a array, then the code is probably smaller.

    // blink led: 70ms on, 70ms off, 70ms on, 900ms off

    unsigned long previousMillis;
    const int intervals[4] = {70, 70, 70, 900};
    int index = 0;

    void setup() {
      pinMode(13, OUTPUT);
      digitalWrite(13, HIGH);  // turn led on, after 70ms it will be turned off
    }

    void loop() {
      unsigned long currentMillis = millis();

      if(currentMillis - previousMillis >= intervals[index]) {
        previousMillis = currentMillis;

        int level = (index % 2) == 0 ? LOW : HIGH;
        digitalWrite(13, level);

        index++;

        if(index > 3)
          index = 0;
      }
    }

This second sketch is smaller, but I prefer the first one.


body:
Look at [my answer to a similar question][1]. Apply the same principle to your problem:

 - Move each task (blinking; calculating RPM) into its own separate function.
 - Make loop() call those functions as often as possible.
 - Make each function decide whether it is time to do its task, do it or not, and return.
 - Those functions must never wait.

This kind of program organization - called non-blocking - is extendable to as many tasks as you wish, until you run out of memory, or the processor runs out of time to do everything as fast as you need it to (that will be a great many more than the two you've described!).

  [1]: https://arduino.stackexchange.com/questions/58675/data-loging-while-browsing-a-menu-on-lcd-shield/58680#58680


body:
The only thing that I can see that makes your code faulty is the fact that you use a if statement to check if your button is pushed and then you have a lot of code to be executed in that statement rather set up a bool outside of your loop and set it with the if function then use a while to do all the rest of the work that was in your if statement that way when the button is released the code will still be executed and when it is pressed again it will happen again

Almost forgot the good stuff yes the blinkwithoutdelay is the way to go on the blink code


message:
Why is this failing after 3 iterations?

I simply cannot figure this out, why is this failing after 3 iterations? Other than that, what better way is there to do this? Thanks!

    #define rotary_encoder_topic  "/rotary/encoder"
    #define remote_button_topic  "/remote/button"
    #define remote_2x_toggle_topic  "/remote/2xtoggle"
    #define rotary_button_topic  "/rotary/button";
    char* devices[] = { "ledrpi", "lamprpi", "mediaroom" };
    int currentDevice = 0;

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

    void incrementCurrentDevice() {
      currentDevice++;
      if (currentDevice >= sizeof(devices)) {
        currentDevice = 0;
      }
     Serial.println(concatenateChars("Switched device to: ", devices[currentDevice]));
    }

    char* concatenateChars(const char* one, const char* two) {
      char result[150] = "";
      strcat(result, one);
      strcat(result, two);
      return result;
    }

    void loop() {
      Serial.println(concatenateChars(devices[currentDevice], remote_2x_toggle_topic));
      incrementCurrentDevice();
      delay(1000);
    }

body:
As Jaromanda X pointed out in the comments, `sizeof(array[0])` (size of first element) will not return the size of the literal strings, but the size of a `char` pointer.

---

It doesn't work (whatever that means for you), because `sizeof(devices)` doesn't return the number of entries in the array, but the size of the array in bytes, e.g. something like (following is wrong: 24 (1 byte per character plus 1 byte with the concluding null character for each string) ) 6 (The size of a `char` pointer is 2 bytes on most microcontrollers; I'm not sure, if this is the same for Node MCU). So after 3 iterations (which can use the string literals in the array) `currentDevice` doesn't go back to zero, but counts further. With the access to the array with exceeding index you are accessing memory, that doesn't belong to the array anymore (e.g. random data).

There is no native function, that gives you the length of an array. But it can be calculated with `sizeof(array)/sizeof(array[0])`, which is the size of the array in bytes divided by the size of one element in bytes. In your case you would have an array size of 6 and an element size of 2, resulting in a calculated element count of 3, which is correct.

Another simple solution, which is easier to understand for beginners, but not as flexible, is to set a constant or define, that contains the size of your array. You can then use it in your code, whenever you need the size, including, when you define the array.


message:
Docs for using i2C LCD with Newliquidcrystal_1.3.5 library?

I bought a 20x4 I2C LCD from OddWires. (https://www.oddwires.com/20x4-lcd-display-with-i2c-interface/) It came with ZERO specs or documentation. After some hair-pulling I was able to figure out how to get it working. (I had to use the commands

    LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address and pin assignments, including the backlight pin and polarity
<br>
and

      lcd.begin(20,4);               // initialize the lcd to 20 characters, 4 lines

To get the LCD working (The tricky bit was figuring out the pin assignments. They're not documented.)

I'm assuming this LCD unit is a lot like all the others out there.

It works, and If found the basic commands to clear the screen, position the cursor, and print text.

I've also found commands `lcd.cursor()` and `lcd.noCursor()` that let me show/hide the cursor.

I'd like to know if I can do things like blink characters between normal and inverse, underline text, etc using the standard LCD library (I've seen code that uploads custom character maps, so I assume I could upload an alternate underlined character set, but that sounds like a LOT of work for something I'm hoping is built in to the library.)

Can somebody point me to docs on the full suite of commands commonly available for these LCD units in the Arduino Newliquidcrystal_1.3.5 library?

(Sorry to be vague on the specifics of my LCD module. I did not get specs from the vendor, so I have had to guess as to how to use it.)

I'm using the I2C LCD NewLiquidCrystal LCD library. (https://github.com/fmalpartida/New-LiquidCrystal)

body:
Often in software development, the code **is** the documentation. The merits of this are debated *ad nauseam* elsewhere.

As you have provided a link to the GitHub repository of the library you are using, you have all you need, though the provided `utility/docs` path doesn't fully document the I2C interface.

The function prototype (that is, the function, its return type, and parameters, but without the actual code) is found in *header files* which usually have the `.h` suffix.

Since you have an LCD with a I2C interface, you can look at the GitHub repo for the file [`LiquidCrystal_I2C.h`][1]

Within this file, you can see that the class is defined with name `LiquidCrystal_I2C` and has multiple constructors, each with a different list of parameters. The particular class constructor used is the one that matches the count and type called in your *declaration* of the object of that class.

The code in the header file is well documented. The first prototype listed includes good commenting:

    /*!
        @method
        @abstract   Class constructor.
        @discussion Initializes class variables and defines the I2C address of the
        LCD. The constructor does not initialize the LCD.

        @param      lcd_Addr[in] I2C address of the IO expansion module. For I2CLCDextraIO,
        the address can be configured using the on board jumpers.
        */
       LiquidCrystal_I2C (uint8_t lcd_Addr);
       // Constructor with backlight control
       LiquidCrystal_I2C (uint8_t lcd_Addr, uint8_t backlighPin, t_backlighPol pol);

This block shows the first 2 constructor options: With a `uint8_t` type that defines the I2C address of an I/O expansion module (which is what many "LCD backpacks" are -- that, or shift registers), and one with an I2C address, a backlight pin, and the polarity of the backlight.

Proceeding down, we find the one with 10 parameters, which is what you ended up using:

      /*!
        @method
        @abstract   Class constructor.
        @discussion Initializes class variables and defines the I2C address of the
        LCD. The constructor does not initialize the LCD.

        @param      lcd_Addr[in] I2C address of the IO expansion module. For I2CLCDextraIO,
        the address can be configured using the on board jumpers.
        @param      En[in] LCD En (Enable) pin connected to the IO extender module
        @param      Rw[in] LCD Rw (Read/write) pin connected to the IO extender module
        @param      Rs[in] LCD Rs (Reset) pin connected to the IO extender module
        @param      d4[in] LCD data 0 pin map on IO extender module
        @param      d5[in] LCD data 1 pin map on IO extender module
        @param      d6[in] LCD data 2 pin map on IO extender module
        @param      d7[in] LCD data 3 pin map on IO extender module
        */
       LiquidCrystal_I2C(uint8_t lcd_Addr, uint8_t En, uint8_t Rw, uint8_t Rs,
                         uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7 );
       // Constructor with backlight control
       LiquidCrystal_I2C(uint8_t lcd_Addr, uint8_t En, uint8_t Rw, uint8_t Rs,
                         uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7,
                         uint8_t backlighPin, t_backlighPol pol);

That last constructor is used to override the default pin mappings from the I/O Expander to the LCD. This is tricky -- what were the mappings based on? An I/O expander is basically a way to access multiple pins on an external chip through a single two-wire interface (I2C). How an LCD is connected depends on what pins of the I/O Expander are connected to which pins of the LCD. There is not a formal standard, though there may be convention.

Reading the [GitHub page][2], you see that this is a

> Clone of the new liquid crystal library from: https://bitbucket.org/fmalpartida/new-liquidcrystal

Following that link takes us to some kind of documentation, noting that one of the connection types is:

> I2C IO bus expansion board with the PCF8574* I2C IO expander ASIC such as [I2C LCD extra IO][3].

A link to that hardware is helpfully provided! We can follow the link to see that the hardware is discontinued, but helpfully documented with some schematics and PCB layouts that tell us which pins of the I/O expander are connected to which pins of the LCD:

[![enter image description here][4]][4]

`P0` is pin 0 of the I/O expander -- the top row are the I/O expander pins. `Vo`, `RS`, `R/W`, etc. are the LCD pins.

    LCD Pin  |  I/O Expander Pin
         En  |  P4
        R/W  |  P5
    E (rst)  |  P6
         D4  |  P0
         D5  |  P1
         D6  |  P2
         D7  |  P3

(And the backlight is a passthrough pin, not on the I/O Expander. It appears the definition of the backlight pin and polarity refer to I/O Expander pins.)

This is the point where you have to find out if the I/O expander on your purchase has the same pinout as the product for which this library was written.

Your "working" instance is called as (with annotations to the constructor being called)

    LiquidCrystal_I2C lcd(
      0x27,       // lcd_Addr
      2,          // En (enable pin)
      1,          // Rw (read/write pin)
      0,          // Rs (reset pin)
      4,          // d4 (data)
      5,          // d5 (data)
      6,          // d6 (data)
      7,          // d7 (data)
      3,          // backlight
      POSITIVE    // backlight polarity
    );

This indicates that the I/O expander on your LCD **does not** have the same pin connections as that for which the library was written, which is why you had success only when remapping them in the constructor.

All that to just re-state the hair-pulling you had to do!

The actual functions available [are noted to be][5]:

> This library provides the same interface to applications as the LiquidCrystal library sourced by the Arduino SDK.

But to be absolutely sure, you can also see their prototypes in the header file: https://github.com/fmalpartida/New-LiquidCrystal/blob/master/LCD.h

It provides scrolling, blinking, enable/disable, etc.

  [1]: https://github.com/fmalpartida/New-LiquidCrystal/blob/master/LiquidCrystal_I2C.h
  [2]: https://github.com/fmalpartida/New-LiquidCrystal
  [3]: http://www.electrofunltd.com/2011/10/i2c-lcd-extra-io.html
  [4]: https://i.stack.imgur.com/dDE04.jpg
  [5]: https://bitbucket.org/fmalpartida/new-liquidcrystal/wiki/Home


message:
I keep gettint the error expected construcotr,destructor or type conversion before = token

#include <dht.h>
    dht DHT;
    #define DHT11_PIN 2     // what pin we're connected to  // DHT 11

    String TextForSms ;
    String humidity = " Humidity: %";
    String temperature = "   Temperature";
    String sign = " *C";
    char fromc;

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

    void loop() {
      int chk = DHT.read11(DHT11_PIN);
      float h = DHT.humidity;
      float t = DHT.temperature;
      delay(2000);
      }

      TextForSms = TextForSms + t + "," + h + ",";
    Serial.println(TextForSms);
         TextForSms = "";
       delay(1000);

body:
This whole section:

      TextForSms = TextForSms + t + "," + h + ",";
    Serial.println(TextForSms);
         TextForSms = "";
       delay(1000);

is outside a block. Code must be inside a block.

There are strict rules governing what can go where in a C or C++ program. I suggest you learn them.


message:
Sparkfun CAN Shield BMW OBD2 reading

I bought the CAN-Shield from Sparkfun https://www.sparkfun.com/products/13262 and I also got the Uno from Sparkfun just to be sure everything works fine.

Some info about my car:

 - BMW E91 2006
 - OBD2 is available
 - KWP 2000 and other lines are available
  like the ones with the same baud rates from the demo

I tried the SparkFun_CAN_Demo which is available on their website and GitHub.

My output is that
CAN init is successful but I don´t know if that´s true...
If I try to read the RPM, for example, I get a buffer with a size of 1 -> " ".

My questions are:

 - Did I something wrong with the MCP2515 how do I know if it´s dead?
 - Does anybody know if the demo is working properly or not?
 - What´s the right way to get data from an BMW with OBD2?

body:
First off I cannot say much about the library that you are using I have't tried that one yet as for the shield i have some of those and there are two versions of them check your PIN outs on them the cs pin is either on d9 or d10

the other thing is make sure that you are in the right operation mode ie. Normal and maybe give this library a try I have had lots of success with this one:
https://github.com/coryjfowler/MCP_CAN_lib

as for the baud rate I have tried all types of ways of getting the right baud rate for certain vehicles but the best remains start small and step it up till you get the one that gives you reply

make sure that you ground the Arduino to the car as well it works without that but sometimes it does nothing If you are using the OBDII cable it should be grounded by default


message:
let Arduino limit it's own input power

My current project will be sitting next to a 12VDC power line. It seems a waste no to tap it to power into the Arduino board too. Now I read everywhere that with 12V input quite  a lot power gets dissipated by the voltage regulator. Wouldn't it then a wise move to use the board 's own PWM capabilities to throttle the input voltage?

Nother point is whether it is sensible at all when the board is using little current (in this case less than 5mA over the pins for 0.1 sec every few seconds, plus the board in deep sleep mode).

body: There are some models of clone boards that have a DC-DC switching regulator instead of linear regulators to do just that.  The extra cost for the regulator chip, inductor, diode, etc. are probably not worthwhile in the majority of applications tho.


body:
How did you measure that it's going to be 5mA? Because if that's really the case, the regulator dropping 7V (I'm assuming it's a regular 5V arduino) will need to dissipate ~35mW of heat which is not much and it should not cause a lot of problems for your board.

Another option would be using a step-down power supply module, there are tons of available dc-dc converters, mostly based on LM2596 (search for _LM2596 DC-DC module_) which will handle your 12 power rail with ease.


message:
Controlling multiple stepper motors non-simultaneously

I want to control multiple stepper motors one after another and at different speeds/directions. I am using the ULN2003 driver and the stepper has 5 coils.

My current code for controlling one motor is:
<!-- language-all: lang-cpp -->

    #include <Stepper.h>

    const int stepsPerRevolution = 500;  // change this to fit the number of steps per revolution
    // for your motor

    // initialize the stepper library on pins 8 through 11:
    Stepper myStepper(stepsPerRevolution, 8, 10, 9, 11);

    void setup() {
      // set the speed at 60 rpm:
      myStepper.setSpeed(50);
      // initialize the serial port:
      Serial.begin(9600);
    }

    void loop() {
      // step one revolution  in one direction:
      Serial.println("clockwise");
      myStepper.step(stepsPerRevolution);

      // step one revolution in the other direction:
      Serial.println("counterclockwise");
      myStepper.step(-stepsPerRevolution);
    }

How would I define each stepper motor differently?

Sorry if I have not asked the question properly. I will try to clarify as time goes on.

body:
Like @chris! suggested, you could include two Stepper variables. So in the line where you were initializing the variable, you could instead have:

    Stepper steppermotor1(stepsPerRevolution, 8, 10, 9, 11);

    Stepper steppermotor2(stepsPerRevolution, 4, 5, 6, 7);

and then continue on with the code for speed, rotation and so on for each motor.


message:
Why can't I print boolean variable values (0 and 1) through println function?

source code :

    int buttonPin = 8;
    boolean buttonState = 0;

    void setup()
    {
       Serial.begin(9600);
       pinMode (buttonPin, INPUT);
    }

    void loop()
    {
       buttonState = digitalRead(buttonPin);
       Serial.println(buttonState);
       delay(500);
    }

But when, instead of boolean I specify an int data type for buttonState variable it produces the result I want i.e. 1 when pressed and 0 when not pressed.
Is it related to the way these variables when stated with different data types give different values to the println() function to convert them into ASCII values?

body:
First, you are not supposed to use `boolean` with digitalRead.

The function prototype in Arduino.h is:

    int digitalRead(uint8_t);

Thus, the *correct* data type for `buttonState` in your code is `int`. Then your other problem goes away. What I am guessing is happening is that the version of the IDE you are using does not have an overloaded function for `Serial.println` that takes a `boolean` argument, and the compiler is casting it to `byte`, in which case it would print as 0x00 (LOW) or 0x01 (HIGH) which are not printable characters.

Unfortunately the [documentation for digitalRead](https://www.arduino.cc/reference/en/language/functions/digital-io/digitalread/) on the Arduino site does not mention the datatype, it just mentions that it returns `HIGH` or `LOW` which isn't very helpful to help you work out what data type to use. BTW, neither of those values are, per se, booleans. If they had said it returns `true` or `false` you might reasonably put the result into a boolean field.

I have [tried to get the Arduino developers to improve the documentation](https://github.com/arduino/reference-en/issues/15) in this respect, something they have declined to do. I raised the issue almost 4 years ago, and no-one is even assigned to this particular task.

---

If you insist on using the boolean type, then a reasonable way of printing would be:

    Serial.println(buttonState ? "HIGH" : "LOW");

---

## In response to some comments ...

> Works fine for me. – Majenko

...

> boolean is a typedef for bool. bool gets promoted to int, not byte - Majenko

What you mean by "is a typedef for bool" is *in some (later) versions of the IDE*.

Looking at, for example, Arduino pre-release version 0023 I see in the file wiring.h:

    typedef uint8_t boolean;
    typedef uint8_t byte;

So you can clearly see that boolean and byte are the same, and therefore that using boolean would be treated as byte. Now if you look at the Print class in that release:

    class Print
    {
      private:
        void printNumber(unsigned long, uint8_t);
        void printFloat(double, uint8_t);
      public:
        virtual void write(uint8_t) = 0;
        virtual void write(const char *str);
        virtual void write(const uint8_t *buffer, size_t size);

        void print(const String &);
        void print(const char[]);
        void print(char, int = BYTE);
        void print(unsigned char, int = BYTE);
        void print(int, int = DEC);
        void print(unsigned int, int = DEC);
        void print(long, int = DEC);
        void print(unsigned long, int = DEC);
        void print(double, int = 2);

        void println(const String &s);
        void println(const char[]);
        void println(char, int = BYTE);
        void println(unsigned char, int = BYTE);
        void println(int, int = DEC);
        void println(unsigned int, int = DEC);
        void println(long, int = DEC);
        void println(unsigned long, int = DEC);
        void println(double, int = 2);
        void println(void);
    };

So you can see that the overload for `print` and `println` treats an unsigned char (effectively `uint8_t`) to be printed with `BYTE` default treatment and not `DEC` treatment.

`BYTE` is declared:

    #define BYTE 0

And the writing is done thus:

    void Print::print(unsigned long n, int base)
    {
      if (base == 0) write(n);
      else printNumber(n, base);
    }

What this boils down to is that both `byte` and `boolean` will be written as "binary" bytes, not converted into decimal.

As Majenko says, things are different today, and `boolean` is now equivalent to `bool` which is promoted to `int`.

---

ElectroManiac did not respond to a question about what version of the IDE s/he is using, however my point is that *for some versions of the IDE* my explanation is true.

---

> Oh, and assigning the return of digitalRead to a bool is perfectly valid ...

Yes, for `bool`, but the question was about `boolean`. Whilst we know, by reading the code and reading the documentation, that digitalRead will return a 0 or 1, the fact that the return type is `int` means that the compiler can potentially see that you are stuffing a 16-bit return value into a 8-bit variable which will possibly lead to data truncation.

I must admit I don't get a warning when compiling with the Arduino IDE, however there is certainly the potential for truncation. A test program written in C++ and compiled with the `-Wconversion` flag gives a suitable warning:

    warning: conversion to ‘uint8_t {aka unsigned char}’ from ‘int’ may alter its value [-Wconversion]

(There is no warning if you are placing the result into `bool`, however that is not the version of the IDE that the OP is using).


message:
CPU information on Arduino Serial Monitor

how to show the

CPU temperature,
CPU usage (percentage) and
the memory usage(percentage)

in Arduino Serial Monitor.

body:
**CPU temperature**

Some Arduino boards have a microcontroller with a temperature sensor inside. For example the Arduino Uno can measure the temperature inside the microcontroller.

As far as I know, no one uses it. It is not accurate and a microcontroller should not get hot in the first place. The microcontroller or processor on the Arduino board can run at 100% load and it does not get hot.
The internal temperature sensor is not accurate enough to measure the ambient temperature.
The internal temperature is therefore (almost) useless.

See [this page on the Arduino Playground][1] and [this forum thread][2] for the internal temperature sensor.

**CPU usage**

There is no CPU usage. There is no idle task. The microcontroller or processor usually runs all the time at full speed.

It is possible to determine how long the Arduino board stays in delays (via the yield function).
With a external RTC clock it is possible to determine how long the Arduino board stays in sleep mode (some battery powered Arduino projects use the sleep mode).
However, those are very specific things. Perhaps a project requires to measure them, but there is no common use for them.

A good sketch is not supposed to do nothing, it is supposed to check all the inputs and check millis-timers and act if needed. The Arduino loop() function is supposed to run as often as possible to make the Arduino run fast and smooth.

**Memory usage**

The memory usage is something to be aware of when writing a sketch. An Arduino board has much less memory than a typical computer.

It is possible to determine the unused memory between the stack and the heap.
The function at [the bottom of this page][3] can be used to determine the amount of free memory.

I have also seen code to measure the high water mark (memory that is never used at all), but none of them work for all Arduino boards and the code is not reliable.

  [1]: http://playground.arduino.cc/Main/InternalTemperatureSensor
  [2]: http://forum.arduino.cc/index.php?topic=8140.0
  [3]: http://playground.arduino.cc/code/AvailableMemory


message:
error 404 in HTTP GET request with Arduino Uno and ESP8266 using AT commands

when I try to send http get request I get error 404

    AT+CIPMTX=1

    OK
    AT+CIPSTART=4,"TCP","alirezaabrhshami.ir",80
    4,CONNECT
    OK
    AT⸮⸮R5U9⸮⸮b⸮⸮j
    OK
    >
    Recv 47 qytes
    SEND OK
    +IPD,4,223;HTTP/1.1 404 Not Found
    Cache-Contsol: public, max-age=0:a1n CeK⸮
this is my code:

    #include <SoftwareSerial.h>

    const byte rxPin = 2;
    const byte txPin = 3;
    SoftwareSerial ESP8266 (rxPin, txPin);

    unsigned long lastTimeMillis = 0;

    void setup() {
      Serial.begin(9600);
      ESP8266.begin(115200);
      delay(2000);
    }

    void printResponse() {
      while (ESP8266.available()) {
        Serial.println(ESP8266.readStringUntil('\n'));
      }
    }

    void loop() {

      if (millis() - lastTimeMillis > 30000) {
        lastTimeMillis = millis();

        ESP8266.println("AT+CIPMUX=1");
    delay(1000);
    printResponse();

    ESP8266.println("AT+CIPSTART=4,\"TCP\",\"alirezaabrishami.ir\",80");
    delay(1000);
    printResponse();

    String cmd = "GET /greencare/login.php?product_id=123456 ";
    ESP8266.println("AT+CIPSEND=4," + String(cmd.length() + 4));
    delay(1000);

    ESP8266.println(cmd);
    delay(1000);
    ESP8266.println("");
      }

      if (ESP8266.available()) {
        Serial.write(ESP8266.read());
      }

    }

body:
your HTTP request is incomplete. it should be

    String cmd = "GET /greencare/login.php?product_id=123456 HTTP/1.1\r\nHost:alirezaabrishami.ir\r\n\r\n"

if the wen server host has more hostnames for the same IP address, the Host header is used on HTTP server to direct the request to the right web application


message:
Access is denied. Error compiling for board Arduino/Genuino Uno

Having this  error-
Arduino: 1.8.8 Hourly Build 2018/11/30 12:33 (Windows 10), Board: "Arduino/Genuino Uno"

open sketch\LCD.ino.cpp: Access is denied.
Error compiling for board Arduino/Genuino Uno.

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

body:
High likely one of the intermediate/binary files is in use. For example:

- When you have it already opened in a debug session
- Having it opened in multiple instances of your IDE
- Having it opened in another application
- Having closed an application that locked the intermediate/binary file(s).

What you can do:

- Close the debug session
- Close all applications related to the project
- Restart your computer


message:
addt instruction of Nextion Display

I'm new to Nextion display. I'm doing a model of oscilloscope with the display and an Arduino Uno. I used the waveform component. I went through the instruction set and found two instructions to send data to the waveform component. The instruction "add" is clear to me. Tried and got the output. But the instruction "addt" is not clear to me. I sent the instruction

    addt 1,0,30\xFF\xFF\xFF

I got something on the display which I'm not able to understand. Please someone explain what the instruction "addt" does....... I also came across the term "data pass through mode" under this instruction in the documentation. Please explain that too.....

Thanks in Advance.....

body:
`addt` is the *volume* variant of `add`.

Instead of using something like:

    add 1, 0, 19
    add 1, 0, 39
    add 1, 0, 85
    add 1, 0, 98

you can group them all together with an `addt`:

    addt 1, 0, 4
    <5ms delay>
    \x13\x27\x55\x62

The third parameter of the `addt` command is the number of values you want to send. Then you have to leave at least 5ms after sending the command so the display is ready to receive (it will actually send a "go" signal to you of `\xFE\xFF\xFF\xFF`.  You send the data as raw binary values (shown as C string escape sequences above), and after it has received the specified number it responds with an "ok" signal of `\xFD\xFF\xFF\xFF`.

The maximum number of values you can send in one batch is 128.


message:
problem data I2C to sensor GY955/BNO055 (China)

I want to ask, I have a problem when running the Arduino sensor, I can't output data, but it's detecting that the sensor address has been paired.
Like I2C has a problem or locks it.

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

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

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

This is code in the bread board

    /****************************************************************************

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

       (C) All rights reserved by ROBERT BOSCH GMBH

       Copyright (C) 2014 Bosch Sensortec GmbH

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

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

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

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

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

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

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

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

    unsigned long lastTime = 0;

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

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

      //Configuration to NDoF mode
      bno055_set_operation_mode(OPERATION_MODE_NDOF);

      delay(1);

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

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

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

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

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

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

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

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

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

    Adafruit_BNO055 bno = Adafruit_BNO055(55,0x29);


message:
Arduino Program Memory Ran Out

I have a Arduino sketch I made and I have run out of dynamic memory on my Arduino  Nano. How could I possibly reduce the amount of memory the program takes? (I'm not that good at this stuff)

P.S: The code is here:
<!-- language-all: lang-cpp -->

    #include <SPI.h>
    #include <SD.h>
    #include <Wire.h>
    #include <Adafruit_GFX.h>
    #include <Adafruit_SSD1306.h>

    const int chipSelect = 4;

    #define OLED_RESET 5
    Adafruit_SSD1306 display(OLED_RESET);

    #if (SSD1306_LCDHEIGHT != 64)
    #error("Fix Height");
    #endif

    /********************************************/

    #define CHARWIDTH           5
    #define CHARHEIGHT          8
    #define AXISWIDTH           (2 + 1)
    #define VISIBLEVALUEPIXELS  (128 - AXISWIDTH)
    #define NUMVALUES           (2 * VISIBLEVALUEPIXELS)

    #define TRIGGER_ENABLE_PIN       2
    #define SCREEN_UPDATE_ENABLE_PIN 3

    byte values[NUMVALUES];
    int pos = 0;
    int count = 0;
    unsigned long readStartTime = 0;
    int sampleRate = 1;

    void displayln(const char* format, ...)
    {
      char buffer[32];

      va_list args;
      va_start(args, format);
      vsprintf(buffer, format, args);
      va_end(args);

      int len = strlen(buffer);
      for (uint8_t i = 0; i < len; i++) {
        display.write(buffer[i]);
      }
    }

    // Draws the graph ticks for the vertical axis
    void drawAxis()
    {
      // graph ticks
      for (int x = 0; x < 2; x++) {
        display.drawPixel(x,  0, WHITE);
        display.drawPixel(x, 13, WHITE);
        display.drawPixel(x, 26, WHITE);
        display.drawPixel(x, 38, WHITE);
        display.drawPixel(x, 50, WHITE);
        display.drawPixel(x, 63, WHITE);
      }
    }

    // Draws the sampled values
    void drawValues()
    {
      int start = 0;

      if ( digitalRead(TRIGGER_ENABLE_PIN) ) {
        // Find the first occurence of zero
        for (int i = 0; i < NUMVALUES; i++) {
          if ( values[i] == 0 ) {
            // Now find the next value that is not zero
            for (; i < NUMVALUES; i++) {
              if ( values[i] != 0 ) {
                start = i;
                break;
              }
            }
            break;
          }
        }
        // If the trigger point is not within half of our values, we will
        // not have enough sample points to show the wave correctly
        if ( start >= VISIBLEVALUEPIXELS )
          return;
      }

      for (int i = 0; i < VISIBLEVALUEPIXELS; i++) {
        display.drawPixel(i + AXISWIDTH, 63 - (values[i + start]), WHITE);
      }
    }

    // Shows the time taken to sample the values shown on screen
    void drawFrameTime(unsigned long us)
    {
      display.setCursor(9 * CHARWIDTH, 7 * CHARHEIGHT - 2); // almost at bottom, approximately centered
      displayln("%ld us", us);
    }

    /********************************************/

    void setup() {

      // Set up the display
      display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // Initialize with the I2C addr 0x3D (for the 128x64)
      display.setTextColor(WHITE);

      pinMode(TRIGGER_ENABLE_PIN, INPUT);
      pinMode(SCREEN_UPDATE_ENABLE_PIN, INPUT);
        // Open serial communications and wait for port to open:
      Serial.begin(9600);
      while (!Serial) {
        ; // wait for serial port to connect. Needed for native USB port only
      }

      Serial.print("init start");

      if (!SD.begin(chipSelect)) {
        Serial.println("fail");
        // don't do anything more:
        while (1);
      }
      Serial.println("init ok");
    }

    /********************************************/

    void loop() {

      // If a sampling run is about to start, record the start time
      if ( pos == 0 )
        readStartTime = micros();

      // If this iteration is one we want a sample for, take the sample
      if ( (++count) % sampleRate == 0 )
        values[pos++] = analogRead(0) >> 4; // shifting right by 4 efficiently maps 0-1023 range to 0-63

      // If we have filled the sample buffer, display the results on screen
      if ( pos >= NUMVALUES ) {
        // Measure how long the run took
        unsigned long totalSampleTime = (micros() - readStartTime) / 2;     // Divide by 2 because we are taking twice as many samples as are shown on the screen

        if ( !digitalRead(SCREEN_UPDATE_ENABLE_PIN) ) {
          // Display the data on screen
          display.clearDisplay();
          drawAxis();
          drawValues();
          drawFrameTime(totalSampleTime);
          display.display();
        }

        // Reset values for the next sampling run
        pos = 0;
        count = 0;
      }
      String dataString = "";

      // read three sensors and append to the string:
      for (int analogPin = 0; analogPin < 3; analogPin++) {
        int sensor = analogRead(analogPin);
        dataString += String(sensor);
          dataString += ",";
      }

      // open the file. note that only one file can be open at a time,
      // so you have to close this one before opening another.
      File dataFile = SD.open("datalog.txt", FILE_WRITE);

      // if the file is available, write to it:
      if (dataFile) {
        dataFile.println(dataString);
        dataFile.close();
        // print to the serial port too:
        Serial.println(dataString);
      }
      // if the file isn't open, pop up an error:
      else {
        Serial.println("error opening datalog.txt");
      }
    }

body:
## Few things to consider :

- Each variable in your program take memory, try to use the smallest datatype ( don't use a float if you need an int for example).
- Eliminate strings
- Reduce the usage of array
- Reduce your code size by using function for redudant task
- Avoid using digital and analog red/write. Use port manipulation instead (link [here]
[1])
- Modify library to remove unused code inside
- Use ICSP programmer instead of serial bootloader
- Simplify your code for reducing its size.

## Or simply ...

Use another board such as STM32 ou bigger ATmega chip with more RAM and bigger ROM size ...

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


message:
IR module sensor query for Line Follwer Robot

![enter image description here](https://i.stack.imgur.com/Pgokk.png)

Are the IR sensors used in Line following Robot and Obstacle avoidance Robot with Arduino UNO different ? If yes , where do we buy these parts online ? I used the following sensor in my Line Follower and am not getting result as it’s detecting obstacle instead of black line .

body:
The sensor you have used is fine. There is a [potentiometer][1] on the sensor PCB that is used for the range. For the line following robot you would want the range small, between 1-4cm. However, for the obstacle avoidance robot you would want to set this for a much larger range, say 10-45cm.

To make an effective line following robot you need at least 2-3 sensors.

Here is one using 2 LEDs either side of the line:
[![2 sensor robot][2]][2]

And here is a 3 sensor robot:
[![3 sensor robot][3]][3]
Notice that one LED stays on the line.

And finally a 5 sensor robot:
[![5 sensor robot][4]][4]

The following websites have good step by step guides where they explain the various techniques:

- https://www.learnrobotics.org/blog/how-to-build-a-mobile-robot-using-arduino-part-4/
- https://circuitdigest.com/microcontroller-projects/line-follower-robot-using-arduino
- http://www.robotc.net/wikiarchive/Tutorials/Arduino_Projects/Mobile_Robotics/VEX/Using_the_line_tracker_to_follow_a_line

When I made my line following robot I used 2 of the following sensor:
[![IR sensor][5]][5]

These sensors were great as they pointed in towards each other, making a focal point. You can do this to your sensor by bending the LEDs slightly towards each other.

  [1]: https://en.wikipedia.org/wiki/Potentiometer
  [2]: https://i.stack.imgur.com/qk9aU.jpg
  [3]: https://i.stack.imgur.com/2Uybs.jpg
  [4]: https://i.stack.imgur.com/LJBCi.jpg
  [5]: https://i.stack.imgur.com/csvNJ.jpg


body:
For obstacle detection you would usually use a different IR sensor, yes. The IR sensors usually used for line following only work at a very short range (typically <1cm). For a robot detecting obstacles you want a sensor that detects an obstacle further away, say at a 30-60 cm distance, so the robot can evade the obstacle before it runs into it.

Common IR sensors for obstacle detection look like this:
[![Infrared distance sensor][1]][1]

The IR sensor you showed probably send a 0V or 5V, true or false value to a digital input of your arduino. The IR distance sensor shown above sends an analogue value (range 0-5v) to an analogue input of an arduino. They come in different ranges. Ranges go from ± 10 cm to ±5m (rough indication).

But personally I prefer to use the common HC-SR04 ultrasonic distance sensor instead of infrared ones. They have a larger usable range, a less noisy signal and detect more different types of objects. That's my personal experience from side-by-side comparison.
[![HC-SR04][2]][2]

  [1]: https://i.stack.imgur.com/0XgKS.jpg
  [2]: https://i.stack.imgur.com/9lvYf.jpg

I'm reluctant to mention online shops on where to buy them. They're very common sensors.


message:
Servo starts rotating whenever it is plugged

I am making a fish feeder using an Arduino Mega 2560, a servo motor SG90 and an RTC DS3231. I want to make it rotate twice a day, i.e. morning and 9 o'clock evening.

Whenever I plug my Arduino board to my laptop for the first time it rotates correctly during specified time 9 o'clock and I change the time to 9 o'clock 10 mins to check again and it rotates after I plug it to my laptop for 180 degrees and then rotates during the specified time.

What should I do to avoid that initial rotation?

Here is my code:

```c++
#include<Wire.h>
#include<LiquidCrystal.h>
#include "RTClib.h"
#include <Servo.h>

Servo myservo;

int pos = 0;
RTC_DS3231 rtc;
DateTime now;
const int OnHour = 9;
const int OnMin = 15;

void setup() {
  Serial.begin(9600);
  rtc.begin();
  myservo.attach(9);
  rtc.adjust(__DATE__,__TIME__));
}

void loop() {
  now = rtc.now();
  Serial.print(now.hour);
  Serial.print(" hour(s), ");
  Serial.print(now.min);
  Serial.print(" minute(s)");
  Serial.println(" ");
  delay(1000);
  if (now.hour == OnHour && now.min == OnMin) {
    Serial.println("feeder ON");
    myservo.write(90);
    delay(1000);
    myservo.write(180);
  } else {
    Serial.println("feeder OFF");
    delay(10);
  }
}
```

body:
I'm not fully understanding the problem, but I assume you want it on for 9:00 / 9AM and 21:00 / 9 PM on for 15 minutes.

    const int onTime1 =  9 * 60 +  0; // 9:00 AM
    const int onTime2 = 21 * 60 + 30; // 9:30 PM
    const int onMinutes   = 15; // Minutes

    void loop()
    {
      now = rtc.now();
      int nowTime = now.hour * 60 + now.min; // Minutes from current day

      if (((onTime1 <= nowTime) && (nowTime < onTime1 + onMinutes)) ||
          ((onTime2 <= nowTime) && (nowTime < onTime2 + onMinutes)))
      {
         myservo.write(90); // On
      }
      else
      {
         myservo.write(180); // Off
      }
      delay(1000); // 1 s delay
    }

You can make the above if statement easier by:

      mysesrvo.write(180 - 90 * (int) (
       ((onTime1 <= nowTime) && (nowTime < onTime1 + onMinutes)) ||
       ((onTime2 <= nowTime) && (nowTime < onTime2 + onMinutes))));


message:
Why my serial message won't show on another when I try use 2 Arduino communication

I am trying to make a simple chatting program with my 2 arduino uno and 2 PC. But when I tried write a message using PC1 serial monitor the message won't show up on PC2 serial monitor. I can't see the problem or maybe I miss something on the program.

Here is my code:
PC1:

<!-- language: c -->

    #include <SoftwareSerial.h>

    SoftwareSerial Serial1(10,11);

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

    void loop()
    {
        if ( Serial.available()) // Check to see if at least one character is available
        {
            char ch1 = Serial.read();
            Serial1.print(ch1);
        }

        delay(200);
    }

PC2:

<!-- language: c -->

    #include <SoftwareSerial.h>

    SoftwareSerial Serial1(10,11);

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

    void loop()
    {
        if (Serial1.available())
        {
            char ch = Serial1.read();
            Serial.print(ch);
        }
    }

body: I haven't tested this in a while but it has been my experience that even though you can have multiple IDE windows open, you can only have one Serial Monitor at a time. The way I got around this is to use a Terminal Emulator program for the second Arduino.


message:
Accessing multiplexed I2C and UART pins of STM32F103 in arduino IDE

I want to access both of the multiplexed I2C and UART pins in the same program. I am programming in Arduino IDE.Can anyone please tell me how to access same pins for different functionalities?

body:
In order to use two different peripherals on the same pins, you have to initialize I2C and de-intialize UART when using I2C and doing the opposite when using UART.

It’s **not** possible to initialize two different peripherlas on the same pins, concurrently.


body:
You can't. (Well, you can, but you mustn't).

I2C and UART are electrically incompatible bus systems.  UART is a Push-Pull system, whereas I2C is an Open-Drain system.  The Push-Pull connections will interfere with the Open-Drain outputs and I2C will not function.

If you want to have both you will need to include extra hardware (and the necessary control pins) to physically isolate the different devices from their respective bus when not in use.


message:
esp8266 esp-01 printing garbage values on serial monitor

I am trying to up an esp8266 esp-01. While monitoring the serial monitor it's printing garbage values. I am using arduino-mega to write the code to the esp8266. The sample code i'm trying to write is

    #include <ESP8266WiFi.h>
    const char* ssid     = "SSID";
    const char* password = "PASSWORD";

    void setup() {
      Serial.begin(9600);// tried other rates as well
      delay(10);
      Serial.println('\n');

      WiFi.begin(ssid, password);
      Serial.print("Connecting to ");
      Serial.print(ssid); Serial.println(" ...");

      int i = 0;
      while (WiFi.status() != WL_CONNECTED) {
        delay(1000);
        Serial.print(++i); Serial.print(' ');
      }

      Serial.println('\n');
      Serial.println("Connection established!");
      Serial.print("IP address:\t");
      Serial.println(WiFi.localIP());
    }

    void loop() { }

Before this I tried to test the esp with a blink program, and it seems working. The connections between esp and arduino are as below

    Arduino | ESP
    ------------------------------------------------------------
    3.3V    | VCC(through a button)
    3.3V    |CH_PD
    TX      | TX
    RX      | RX (connected through a voltage divider to arduino)
    GPIO 0  | GND (through a push button to GND)
    GPIO 2  | 3.3V (through a 1K resistor to 3.3V)

Arduino's the RESET and GND are shorted. What I'm trying to achieve to make the wifi module to act as message que, sending and receiving data to and from a device which is connected to it via internet.

body:
The "garbage values" are most likely messages from the bootloader, output at 74880bps. Try watching its serial out at that speed. You'll probably see messages that look something like:

    ets Jan  8 2013,rst cause:2, boot mode:(3,7)
    load 0x4010f000, len 1384, room 16
    tail 8
    chksum 0x2d
    csum 0x2d

The `rst cause` number will give you an indication of why the chip rebooted.

The [most common reset causes][1] are

 0. power on
 1. hardware watchdog timer
 2. fatal exception (most likely error in your code or power issue)
 3. software watchdog timer
 4. software reset
 5. deep sleep
 6. hardware reset

If it's a "fatal exception", you should see another line that looks like this:

    Fatal exception (28):
    epc1=0x4025bfa6, epc2=0x00000000, epc3=0x00000000, excvaddr=0x0000000f,
    depc=0x00000000

[Look up the exception number][2]; if it's not obvious what it means, google it to learn about the causes.

  [1]: https://www.espressif.com/sites/default/files/documentation/esp8266_reset_causes_and_common_fatal_exception_causes_en.pdf
  [2]: https://links2004.github.io/Arduino/dc/deb/md_esp8266_doc_exception_causes.html


message:
to measure the time between the ON signal and OFF signal

int pin_state = LOW;
    struct Channel {
        byte pin;
        byte state;
        byte count;
        unsigned long fell, rose;
    };

    const int CHANNEL_COUNT = 3;
    Channel channels[CHANNEL_COUNT] = {
        { 2, LOW, 0, 0 },
        { 3, LOW, 0, 0 },
        //{ 4, LOW, 0, 0 },
        //{ 5, LOW, 0, 0 },
        //{ 6, LOW, 0, 0 }
    };

    void setup()
    {
        for (int i = 2; i <= CHANNEL_COUNT; ++i) {
            pinMode(channels[i].pin, INPUT);
        }
        Serial.begin(9600);
        //Serial.println("pin,fell,rose,low time");
        Serial.println("Minutes, Seconds, Count");
    }

    void loop()
    {
        for (int i = 0; i < CHANNEL_COUNT; ++i)
        {
            Channel &c = channels[i];
            byte new_state = digitalRead(c.pin);
            if (c.state == LOW && new_state == HIGH)
            {
                c.rose = millis();
                c.count = c.count + 1;
            }
            else if (c.state == HIGH && new_state == LOW)
            {
                c.fell = millis();
                display_channel(c);
            }
            c.state = new_state;
        }
    }

    void display_channel(const Channel &c)
    {
      int minutes, seconds;
      unsigned long difference;
      difference = c.fell - c.rose;
      seconds = int(difference/1000);
      if (seconds >= 60)
      {
           minutes = seconds / 60;
           seconds = seconds % 60;
      }
        //Serial.print(difference/1000);
        //Serial.print(",");
        Serial.print(minutes);
        Serial.print(",");
        Serial.print(seconds/1000);
        Serial.print(",");
        Serial.println(c.count-1);
        //Serial.print(",");
      }

When I try to run the program, I don't get any output.
Is there anything wrong with the code, that must be solved before any output can get displayed?

body:
Here's the catalog of errors I see at first glance:

    const int CHANNEL_COUNT = 3;
    Channel channels[CHANNEL_COUNT] = {
        { 2, LOW, 0, 0 },
        { 3, LOW, 0, 0 },
        //{ 4, LOW, 0, 0 },
        //{ 5, LOW, 0, 0 },
        //{ 6, LOW, 0, 0 }
    };

You set up space for 3 entries but only fill 2.  Also, the Channel structure has 5 entries, not 4. You don't initialize the 5th (`rose`) entry (although it will be initialized to 0 for you - best to be explicit though).

----

    for (int i = 2; i <= CHANNEL_COUNT; ++i) {
        pinMode(channels[i].pin, INPUT);
    }

You start from entry number 2 (the third entry) and iterate to the 4th (non-existent) entry to set the pin mode of either undefined or invalid pins.

----

    for (int i = 0; i < CHANNEL_COUNT; ++i)

You have only filled in 2 of the three entries. Yet you use the third as if it were filled in.

----

    Serial.print(minutes);

If `seconds` is less than 60 then `minutes` is undefined here.

----

I would suggest changing your code so that `Channel` is a class and embed the code to manage that class within it.

----

* Bonus Time

Here's your program re-written using a class. As an added bonus I have added automatic allocation of a channel number to each object as it's created.  To add more channels just add the pin number into the initialization list.

    class Channel {
     private:
      uint8_t _pin;
      uint8_t _state;
      uint32_t _rise;
      uint32_t _fall;
      uint8_t _count;
      uint8_t _channel;

      static uint8_t channelCount;

      void display() {
       uint32_t diff = (_fall - _rise) / 1000;
       uint32_t secs = diff % 60;
       uint32_t mins = diff / 60;
       Serial.print(_channel);
       Serial.print(",");
       Serial.print(mins);
       Serial.print(",");
       Serial.print(secs);
       Serial.print(",");
       Serial.println(_count);
      }

     public:
      Channel(int pin) : _pin(pin), _count(0) {
       _pin = pin;
       _count = 0;
       _channel = channelCount;
       channelCount++;
      }
      void process() {
       int s = digitalRead(_pin);
       if (s != _state) {
        _state = s;
        if (s == LOW) { // Fell
         _fall = millis();
         _count++;
         display();
        } else {
         _rise = millis();
        }
       }
      }
      void begin() {
       pinMode(_pin, INPUT);
      }
    };

    uint8_t Channel::channelCount = 0;

    Channel channels[] = { 2, 3 };
    #define NUM_CHANNELS (sizeof(channels) / sizeof(channels[0]))

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

     Serial.println("Channel,Minutes,Seconds,Count");

     for (unsigned int i = 0; i < NUM_CHANNELS; i++) {
      channels[i].begin();
     }
    }

    void loop() {
     for (unsigned int i = 0; i < NUM_CHANNELS; i++) {
      channels[i].process();
     }
    }


message:
Management issues through Blynk

I wrote a sketch for controlling the stepper motor under the controls of the Blynk application, the sketch was compiled but there was a problem in that no control was taking place. Receipts and controls occur on virtual pins V1, V2, V3. (The problem is that nothing is controlled), please help solve the problem.
[![enter image description here][1]][1]
[![enter image description here][2]][2]
[![enter image description here][3]][3]
[![enter image description here][4]][4]

    //#include <Stepper.h>
    //#define BLYNK_WRITE
    //#include <ESP8266WiFi.h>
    //#include <BlynkSimpleEsp8266.h>

    const int stepsPerRevolution = 200;  // change this to fit the number of steps per revolution
    // for your motor
    Stepper myStepper(stepsPerRevolution, 1, 2, 3, 4);

    // You should get Auth Token in the Blynk App.
    // Go to the Project Settings (nut icon).
    char auth[] = "[private]";

    // Your WiFi credentials.
    // Set password to "" for open networks.
    char ssid[] = "S30mini";
    char pass[] = "12345678";

    int pinData;
    int pinData1;
    int pinData2;
    BLYNK_WRITE(V3) //Button Widget is writing to pin V1
    {
      int pinData = param.asInt();
     }
    BLYNK_WRITE(V2) //Button Widget is writing to pin V1
    {
      int pinData1 = param.asInt();
     }
    BLYNK_WRITE(V1) //Button Widget is writing to pin V1
    {
      int pinData2 = param.asInt();
     }

    void setup()
    {
      // Debug console
      Serial.begin(115200);
      Blynk.begin(auth, ssid, pass);
    }

    void loop()
    {
        Blynk.run();

      // map it to a range from 0 to 100:
      int motorSpeed = map(pinData, 0, 1023, 0, 100);
      // set the motor speed:
      if (motorSpeed > 0) {
        myStepper.setSpeed(motorSpeed);
        // step 1/100 of a revolution:
        myStepper.step(stepsPerRevolution / 100);
      }

       if (pinData1 == 1){
          myStepper.step(stepsPerRevolution);
       }

       if (pinData2 == 1){
         myStepper.step(-stepsPerRevolution);
        }

    }

  [1]: https://i.stack.imgur.com/YRVUG.jpg
  [2]: https://i.stack.imgur.com/Cq6OP.jpg
  [3]: https://i.stack.imgur.com/ogVlP.jpg
  [4]: https://i.stack.imgur.com/cEUoO.jpg

body:
By prefixing your `pinData` variables with `int`, you are declaring local variables in your `BLYNK_WRITE()` functions, whose scope is only in that function. The local version is written to, instead of the global.

To fix this, do not declare a new variable in `BLYNK_WRITE()`:

    BLYNK_WRITE(V3) //Button Widget is writing to pin V1
    {
      pinData = param.asInt();
    }
    BLYNK_WRITE(V2) //Button Widget is writing to pin V1
    {
      pinData1 = param.asInt();
    }
    BLYNK_WRITE(V1) //Button Widget is writing to pin V1
    {
      pinData2 = param.asInt();
    }


message:
Help to delimit and read specific contents of incoming HTTP string

I am sending strings to an Esp8266 via web browser.

The below code returns the following in serial monitor if I send in browser:

Send from browser to esp8266 - http://192.168.1.220/s1s2s3s4s5d1
Receive in Arduino Serial monitor - GET /s1s2s3s4s5d2 HTTP/1.1

How do i read only the contents s1s2s3s4s5d1  ? This content can vary in length, numbers could be double digits but alphabets will remain in between.

Please note I am still a novice.
<!-- language-all: lang-cpp -->

    // Read the first line of the request
    String request = client.readStringUntil('\r');
    Serial.println(request);
    client.flush();

body:
I have this

    if (client.connected()) {
      if (client.available() && client.find(' ')) { // GET /fn HTTP/1.1
        char fn[20];
        int l = client.readBytesUntil(' ', fn, sizeof(fn));
        fn[l] = 0;
        while (client.read() != -1);
        Serial.println(fn);
        client.stop();
      }
    }


body:
you can try something like this

    int first_space = request.indexOf(' '); // location of the first space
    int second_space = request.indexOf(' ', first_space); // the next space after first

    String query_arg = request.substring(first_space,second_space);


message:
ESP8266 SoftwareSerial not receiving any character

I want to use a ESP8266 (ESP12) to receive data from a counter at 9600 baud via SotwareSerial. But my program does not receive any data. I broke it down to the code i attach here. I tried it using different libraries (Arduino SoftwareSerial and also espsoftwareserial) i found. I connected and tested RX and TX in different combinations of the available pins 4/5/12/13/14. But no combination is receiving data at all. I only can send data - checked by oscilloscope. Running my test program attached i connected the RX and TX pin together so i should loop back the data from tx.

I hopefully find somebody in the community who can give me a helpful hint. Thank you in advance!

    #include <SoftwareSerial.h>
    SoftwareSerial mySerial1(14, 12, false, 256);  // RX, TX

    void setup() {
    mySerial1.begin(9600);   //  Kommunikation mit Zähler
    mySerial1.setTimeout(5000);
    mySerial1.listen();
    //delay(100);
    //mySerial1.listen();

    Serial.begin(9600);
    delay(1000);
    Serial.print(__DATE__);Serial.print(" ");Serial.println(__TIME__);

    char ch;
    while(1){
      wdt_reset();
      Serial.println("\nSoftware serial test started");
      Serial.print("Data sent: ");
      for (byte i = 32; i < 128; i++) { mySerial1.write(i);
      Serial.print(char(i)); }
      Serial.println();
      mySerial1.println();
      ESP.wdtFeed();
      delay(100);
      Serial.print("Data recv: ");
      if(mySerial1.available()) {
        while(mySerial1.available()){
          ch = mySerial1.read();
          Serial.print(ch);
        }
        Serial.println("_");
      }
      delay(400);
    }
    }

    void loop() {}

body:
If the ESP8266's software serial is anything like the Arduino's software serial, it cannot receive data while it's transmitting. It's strictly half-duplex.

To test your system you will need to test the transmission and reception completely separately, and that means having some external device sending data for you to attempt to receive.


message:
Nan values in Egg Incubator

I've recently built my Arduino Incubator, which consists of a DHT22 sensor, an LCD Keypad Shield, some fans, resistors, e.t.c.

I uploaded the sketch, and everything seemed fine. However, when I try to select the temperature and humidity I want, it won't let me change anything, and it says "Temperature: NanC, Humidity: Nan%".

What am I doing wrong? I didn't write the code myself. I copied it from a guy who made his incubator and wrote his code himself. He has the incubator project on [github][1].

As you can see in the pictures he posted, everything appears to be working fine. What would be the problem? I don't have a lot of Arduino knowledge, although I am OK with reading and tinkering with code.

The display below, shows NaN when I try to select my own temperature/humidity. When I see the current temperature/humidity, it works fine. The sensor works with no problems at all, though I didn't connect a pullup resistor. I am going to try adding one. However, to me it seems like the problem isn't that. I get NaN errors when trying to select my own value. The buzzer beeps, the servo turns and the fan works fine. As said above, DHT sensor works and sends the values.

[![The error I get when trying to set the temperature.][2]][2]
[![Same error in humidity selection.][3]][3]

Useful Links:

[The code (Github)][4]

[The schematic (Github)][5]

[The whole incubator project (Github)][1]

***Update - 7/1/2019***
Thanks to [Jot][8], everything works fine now! He corrected my code, and he adviced me to reset the values in the EEPROM. I would have given up the project, unless he had helped me. I have now fully finished the build, even though I plan to add some features in the future.

**I want to add:**

 - A backup power source (lead acid battery)
 - Bigger ventilation holes
 - Design improvements
 - The ability to control everything using the serial monitor, so I can connect to the Arduino via Internet (Using an MFP Storage Server which I have)
 - A larger box for more eggs
 - A system which turns the eggs automatically
 - A pump which pumps water to the sponge automatically as well

However, nothing could be done without Jot's help. Again, thanks a lot to Jot for his help, and the efforts he put in order to help me. I really appreciate that, since I have not any kind of Arduino knowledge (I'm 14 years old), and I found his advices and comments very very useful.

I have now put 5 eggs inside the incubator, and it is right now working. I am counting backwards from today, and in about 21 days I am going to have chickens!

**Here are some pictures of the machine for those who are interested (or just curious!):**

The incubator working, with the screen turned on:
![[9]][9]

The "egg hatching" room:
(Inside, there is a wet sponge, all the devices and of course, 5 eggs!)
[![enter image description here][11]][11]

  [1]: https://github.com/quantenschaum/egg-incubator/
  [2]: https://i.stack.imgur.com/agXyy.jpg
  [3]: https://i.stack.imgur.com/olpzd.jpg
  [4]: https://github.com/quantenschaum/egg-incubator/blob/master/incubator.ino
  [5]: https://github.com/quantenschaum/egg-incubator/blob/master/incubator_schematic.png
  [8]: https://arduino.stackexchange.com/users/30198/jot
  [9]: https://i.stack.imgur.com/fc9YZ.jpg
  [11]: https://i.stack.imgur.com/A5eXd.jpg

body:
Hi Lefteris the builder,
StackExchange is about questions and answers.
Arduino is about learning and fast prototyping.

For guidance with your project, the forum at http://forum.arduino.cc/ is more appropriate.

I suppose that a number of us have read the code that you use. We really do read code.
That code is not bad, but there are a few weak spots in that code:

 - Not enough comments to explain what is going on.
 - Many conditions with flags. That is okay,
   but the flags are sometimes a boolean and
   sometimes a byte, and there is no explanation what the flag is
   used for.
 - Many checks for isnan(). Does that indicate that
   a floating point "nan" problem might pop up
   at any time in the sketch?
 - Most of the code is in the loop(). I don't mind that, but
   others prefer to put large blocks of code in functions.

It seems that your hardware is working okay.

It is hard to confirm that the code for the Holt-Winters algoritme is working.

All this together is too confusing for us at the moment.

----------

I have changed my answer, the hardware seems to be working.

----------

Below is the changed sketch to test it without extra hardware.
I use the serial monitor. The sadw keys (followed by enter) are the cursor keys and the space bar (followed by enter) is select.

    #include <avr/wdt.h>
    // #include <Servo.h>
    // #include <LiquidCrystal.h>
    // #include <DHT.h>
    #include <EEPROM.h>

    // stty -F /dev/ttyACM0 115200 cs8 cread clocal -hupcl time 30 && tee incubator.log </dev/ttyACM0

    #define WDT_TIMEOUT WDTO_8S // if defined, enable hardware watchdog
    #define DHTPIN 3 // data pin of the DHT T/H sensor
    #define T_OFFSET 0.9 // temperature sensor offset
    #define FAN_PIN 2 // fan tacho signal pin
    #define FAN_THRES 500 // fan alarm threshold
    #define BEEPER A2 // pin where beeper is attached
    #define BRIGHTNESS 10 // display brightness pin
    #define HEATER A1 // heater MOSFET pin
    #define DELAY 2000 // loop delay in ms
    #define TS_ADDR 0 // temperature set point EEPROM address
    #define HS_ADDR 4 // humidity set point EEPROM address
    #define HC_ADDR 8 // humiditiy control mode EEPROM address
    #define TI_RESET 1 // integral reset threshold, set integral to 0 when T error greater than this
    #define HI_RESET 5 // integral reset threshold, set integral to 0 when H error greater than this
    #define ALARM_T 2 // temperature alarm threshold, alert if T error greater than this
    #define ALARM_H 8 // humidity alarm threshold, alert if H error greater than this
    #define H_AUTO_THRES 3 // disable vent control in auto mode if H error < this
    #define H_AUTO_COUNT 200 // disable for n cycles
    #define HWAT 0.25 // holt winters parameters for temperature smoothing
    #define HWBT 0.2
    #define HWAH 0.7 // holt winters parameters for humidity smoothing
    #define HWBH 0.5
    #define A 0.005 // long average parameter
    #define VENTCLOSED 80 // consider vent closed if under this angle
    #define VENTOPENMS  480000L // open vent if closed longer
    #define VENTRESETMS 600000L // reset vent after this time (>VENTOPENMS!)

    // Servo vent;
    // DHT dht(DHTPIN, DHT22);
    // LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

    #define RIGHT 16
    #define UP 8
    #define DOWN 4
    #define LEFT 2
    #define SELECT 1
    #define NO_KEY 0

    // added define to show messages on serial monitor.
    #define lcd Serial

    byte getKey() {
    //  int key = analogRead(0);
    //  if (key < 50) {
    //    return RIGHT;
    //  } else if (key < 150) {
    //    return UP;
    //  } else if (key < 300) {
    //    return DOWN;
    //  } else if (key < 500) {
    //    return LEFT;
    //  } else if (key < 800) {
    //    return SELECT;
    //  } else {
    //    return NO_KEY;
    //  }
      if (Serial.available() > 0) {
        int inChar = Serial.read();
        switch (inChar)
        {
          case 'w': return UP;
          case 'a': return LEFT;
          case 's': return DOWN;
          case 'd': return RIGHT;
          case ' ': return SELECT;
        }
      } else {
        return NO_KEY;
      }
    }

    void eeread(int address, int length, void* p) {
      byte* b = (byte*)p;
      for (int i = 0; i < length; i++) {
        *b++ = EEPROM.read(address + i);
      }
    }

    void eewrite(int address, int length, void* p) {
      byte* b = (byte*)p;
      for (int i = 0; i < length; i++) {
        EEPROM.write(address + i, *b++);
      }
    }

    void write_byte(int address, byte &value) {
      eewrite(address, sizeof(value), &value);
    }

    byte read_byte(int address) {
      byte value;
      eeread(address, sizeof(value), &value);
      return value;
    }

    void write_int(int address, int &value) {
      eewrite(address, sizeof(value), &value);
    }

    int read_int(int address) {
      int value;
      eeread(address, sizeof(value), &value);
      return value;
    }

    void write_float(int address, float &value) {
      eewrite(address, sizeof(value), &value);
    }

    float read_float(int address) {
      float value;
      eeread(address, sizeof(value), &value);
      return value;
    }

    void heater(boolean on) {
    //  digitalWrite(HEATER, !on ? LOW : HIGH);
    }

    boolean heater() {
    //  return digitalRead(HEATER) == HIGH;
      return true;
    }

    volatile int fancount;

    void count() {
      ++fancount;
    }

    void beep(unsigned long f, unsigned long l) {
    //  pinMode(BEEPER, OUTPUT);
      byte v = 0;
      f = 500000 / f;
      l = (1000 * l) / f;
      for (int i = 0; i < l; ++i) {
    //    digitalWrite(BEEPER, v = !v);
    //    delayMicroseconds(f);
      }
    //  pinMode(BEEPER, INPUT);
    }

    float Ts, Hs; // set points
    byte Hcontrol; // H control mode
    byte Ts_changed, Hs_changed; // setpoint changed flags
    float ET, dETdt, IETdt; // prop/diff/integ terms for T
    float EH, dEHdt, IEHdt; // prop/diff/integ terms for H
    float T, Tavg = NAN, Tvar, Tstd;
    float H, Havg = NAN, Hvar, Hstd;
    float Hpower, Hduty; // heater current power, average duty cycle
    unsigned long t0, Hon, talarm, tventclosed;
    byte displayMode;
    byte key, bri = 255, alarm;
    boolean ventclosed;
    int fanrpm;

    void setup() {
    #if defined(WDT_TIMEOUT)
    //  wdt_enable(WDT_TIMEOUT);
    #endif
      Serial.begin(9600);
      Serial.println("Egg Incubator");
      Serial.println("Use wsad and space is select");

    //  pinMode(HEATER, OUTPUT);
    //  heater(0);
    //  pinMode(BRIGHTNESS, OUTPUT);
    //  analogWrite(BRIGHTNESS, bri = 255);
    //  lcd.begin(16, 2);
    //  lcd.noCursor();
      lcd.print("Incubator 0.7");
    //  lcd.setCursor(0, 1);
      Serial.println();
      lcd.print(__DATE__);
    //  dht.begin();
    //  vent.setMinimumPulse(800);
    //  vent.setMaximumPulse(2600);
    //  vent.attach(11);
      //  write_float(TS_ADDR, Ts=37.8);  write_float(HS_ADDR, Hs=55);
      Ts = read_float(TS_ADDR);
      Hs = read_float(HS_ADDR);
      Hcontrol = read_byte(HC_ADDR);
    //  pinMode(FAN_PIN, INPUT_PULLUP);
    //  attachInterrupt(0, count, FALLING);
    //  sei();
    //  beep(800, 100);
    //  beep(1000, 100);
    //  beep(1200, 100);
    //  beep(1600, 100);
    }

    void loop() {
      unsigned long t1 = millis();
      int dt = t1 - t0;

      if (!key) {
        key = getKey();
      }

      if (key) {
    //    analogWrite(BRIGHTNESS, bri = 255);
      }

      if (t1 - Hon > Hpower * DELAY) {
    //    heater(0);
      }

      if (Hcontrol && Hcontrol < H_AUTO_COUNT) {
    //    vent.refresh();
      }

      if (alarm && !(alarm & 8)) {
    //    beep(1000, 50);
    //    beep(1414, 50);
      }

      if (dt > DELAY || key) {

        if (!key) {
          //    beep(2000, 50);
    //      T = dht.readTemperature() + T_OFFSET;
          T = 30.0 + T_OFFSET;             // set to fixed value !
    //      H = dht.readHumidity();
          H = 60.0;                        // set to fixed value !

          if ((isnan(T) || T < 10 || T > 60) || (Hcontrol && (isnan(H) || H < 5 || H > 95))) {
    //        heater(0);
    //        lcd.clear();
            lcd.print("SENSOR ERROR!");
    //        lcd.setCursor(0, 1);
            Serial.println();
            lcd.print("T=");
            lcd.print(T);
            lcd.print("C H=");
            lcd.print(H, 1);
            lcd.print("%");
            beep(2000, 1000);
            return;
          }

          float dts = dt * 1e-3;

          if (dt > DELAY) {
            fanrpm = fancount * 60 / dts;
            fancount = 0;
          }

          if (fanrpm < FAN_THRES) {
            alarm |= 4;
          } else {
            alarm &= ~4;
          }

          // temperature Holt-Winters smoothing
          float E0 = ET;
          ET = HWAT * (T - Ts) + (1 - HWAT) * (ET + dETdt * dts); // smoothed T error (deviation from set point)
          dETdt = HWBT * (ET - E0) / dts + (1 - HWBT) * dETdt; // smoothed derivative
          IETdt += ET * dts; // integral of error
          if (abs(ET) > TI_RESET) // reset integral on big deviation
            IETdt = 0;
          float pidT = 1.1765 * (ET + 0.010526 * IETdt + 23.75 * dETdt); // PID value, adjust coefficients to tune
          Hpower = fanrpm > FAN_THRES ? max(0, min(1, -pidT)) : 0;
          heater(Hpower > 0.1);
          Hon = millis();

          if (abs(ET) > ALARM_T) {
            alarm |= 1;
    //        vent.write(ET < 0 ? 0 : 180);
            if (Hcontrol > 1) {
              Hcontrol = 2;
            }
          } else {
            alarm &= ~1;
          }

          // humidity Holt-Winters smoothing
          E0 = EH;
          EH = HWAH * (H - Hs) + (1 - HWAH) * (EH + dEHdt * dts); // smoothed H error (deviation from set point)
          dEHdt = HWBH * (EH - E0) / dts + (1 - HWBH) * dEHdt; // smoothed derivative
          IEHdt += EH * dts; // integral of error
          if (abs(EH) > HI_RESET) // reset integral on big deviation
            IEHdt = 0;
          float pidH = 0.1176 * (EH + 0.09091 * IEHdt + 2.75 * dEHdt); // PID value, adjust coefficients to tune
    //      vent.write(pidH * 180);

          if (Hcontrol && abs(EH) > ALARM_H) {
            alarm |= 2;
          } else {
            alarm &= ~2;
          }

          boolean ventclosed0 = ventclosed;
    //      ventclosed = vent.read() < VENTCLOSED;
          ventclosed = VENTCLOSED;

          if (ventclosed && ventclosed != ventclosed0) {
            tventclosed = millis();
          }

          boolean openvent = ventclosed && millis() - tventclosed > VENTOPENMS;
          if (openvent) {
    //        vent.write(180);
            if (millis() - tventclosed > VENTRESETMS) {
              tventclosed = millis();
            }
          }

          if (Hcontrol > 1) {
            if (abs(EH) > H_AUTO_THRES || openvent) {
              Hcontrol = 2;
            } else {
              if (Hcontrol < H_AUTO_COUNT) {
                ++Hcontrol;
              } else {
                IEHdt = 0;
              }
            }
          }

          // long term averages
          Tavg = A * T + (1 - A) * (isnan(Tavg) ? T : Tavg);
          Tvar = A * pow(T - Tavg, 2) + (1 - A) * (isnan(Tvar) ? 0 : Tvar);
          Tstd = sqrt(Tvar);

          Havg = A * H + (1 - A) * (isnan(Havg) ? H : Havg);
          Hvar = A * pow(H - Havg, 2) + (1 - A) * (isnan(Hvar) ? 0 : Hvar);
          Hstd = sqrt(Hvar);

          Hduty = A * Hpower + (1 - A) * Hduty;

          if (Ts_changed) {
            if (Ts_changed-- == 1)
              write_float(TS_ADDR, Ts);
          }

          if (Hs_changed) {
            if (Hs_changed-- == 1)
              write_float(HS_ADDR, Hs);
          }
        }

        if (key & SELECT) {
          displayMode = ++displayMode % 8;
        }

    //    lcd.clear();
        Serial.println();
        lcd.print("T=");
        lcd.print(Ts + ET);
        lcd.print("C H=");
        lcd.print(Hs + EH, 1);
        lcd.print("%");

    //    lcd.setCursor(0, 1);
        Serial.println();

        float uptime;
        char unit;
        switch (displayMode) {
          case 0: // raw values
            lcd.print("T=");
            lcd.print(T);
            lcd.print("C H=");
            lcd.print(H, 1);
            lcd.print("%");
            break;
          case 1: // temperature setpoint
            if (key & (UP | DOWN | LEFT | RIGHT)) {
              Ts = max(20, min(50, Ts + (key & (UP | RIGHT) ? +1 : -1) * (key & (UP | DOWN) ? 0.1 : 1)));
              Ts_changed = 10;
            }
            lcd.print("Ts=");
            lcd.print(Ts);
            lcd.print("C");
            break;
          case 2: // humidity setpoint
            if (key & (UP | DOWN)) {
              Hs = max(10, min(90, Hs + (key & UP ? +1 : -1)));
              Hs_changed = 10;
            }
            if (key & RIGHT) {
              if (Hcontrol < 2) {
                Hcontrol = ++Hcontrol;
              } else {
                Hcontrol = 0;
              }
              IEHdt = 0;
              write_byte(HC_ADDR, Hcontrol);
            }
            lcd.print("Hs=");
            lcd.print(Hs);
            lcd.print("% ");
            lcd.print(Hcontrol == 1 ? "on" : (Hcontrol > 1 ? "auto" : "off"));
            break;
          case 3: // average temperatur
            lcd.print("Ta=");
            lcd.print(Tavg);
            lcd.print("C (");
            lcd.print(Tstd);
            lcd.print(")");
            break;
          case 4: // average humidity
            lcd.print("Ha=");
            lcd.print(Havg);
            lcd.print("% (");
            lcd.print(Hstd);
            lcd.print(")");
            break;
          case 5: // heater duty cycle
            lcd.print("Hd=");
            lcd.print(Hduty);
            lcd.print(" Hp=");
            lcd.print(Hpower);
            break;
          case 6: // air vent
            lcd.print("V=");
    //        lcd.print(vent.read() / 180.0);
            lcd.print(" F=");
            lcd.print(fanrpm);
            break;
          case 7: // average humidity
            uptime = t1 * 1e-3;
            unit = 's';
            if (uptime > 60) {
              uptime /= 60;
              unit = 'm';
              if (uptime > 60) {
                uptime /= 60;
                unit = 'h';
                if (uptime > 24) {
                  uptime /= 24;
                  unit = 'd';
                }
              }
            }
            lcd.print("Up=");
            lcd.print(uptime, 1);
            lcd.print(unit);
            break;
          default:;
        }

        Serial.println();

        if (alarm & 7) {
          if (!talarm) {
            talarm = millis();
          }
          // sound on persistent alarm and fan failure
          if (millis() - talarm > 300000L || alarm & 4) {
            alarm &= ~8;
          }
    //      analogWrite(BRIGHTNESS, bri = 255);
    //      lcd.setCursor(0, 0);
          if (alarm & 1)
            lcd.print("T ");
          if (alarm & 2)
            lcd.print("H ");
          if (alarm & 4)
            lcd.print("F ");
          lcd.print("ALARM!          ");
          if (!(alarm & 8) && key) {
            alarm |= 8; // alarm acknowledged
            talarm = millis();
          }
          if (!(alarm & 8)) {
    //        lcd.setCursor(0, 1);
            Serial.println();

            lcd.print("T=");
            lcd.print(T);
            lcd.print("C H=");
            lcd.print(H, 1);
            lcd.print("%");
          }
        } else {
          alarm = 0;
          talarm = 0;
        }

        if (key) {
          delay((key & SELECT) ? 500 : 200);
        }

        if (bri) {
    //      analogWrite(BRIGHTNESS, --bri);
        }
        key = 0;
        t0 = t1;
      }

    #if defined(WDT_TIMEOUT)
      wdt_reset();
    #endif
    }

@Lefteristhebuilder, you have selected that sketch, but the sketch might not handle problems very well.

Anyone can write code for Arduino and put it online.
At least at Github it is possible that others can write an issue (as you did). The project at Github has 9 stars and the creator showed the project at the Arduino "Project Hub". That is all good, but I'm not very happy with the code itself.