message:
Do you actually NEED external resistors for switch connecting IO pin to ground?

Years ago, I encountered a fairly long debate at AVRfreaks.net about whether or not it's OK to directly connect AVR pins that are configured as inputs with internal pullup enabled directly to ground through a button or switch.

From what I recall, the consensus at the time was that it's not (at least, for switches likely to be *closed* and *conducting* at reset), because at least *some* AVR MCUs weren't absolutely *guaranteed* to have their pins in high-impedance state at reset (at least, not if the chip reset while in brownout state, or something like that).

Thinking back, I'm not sure whether the warnings even applied to the chips **I** was introduced to at the time (ATtiny2313, ATtiny13, and ATmega162)... I just remember that the others on the site were pretty adamant that I was courting disaster, and I took their word for it.

Fast forward ~15 years.

The **current** datasheet for the ATmega2560 (at https://ww1.microchip.com/downloads/en/DeviceDoc/ATmega640-1280-1281-2560-2561-Datasheet-DS40002211A.pdf ) **does** seem to guarantee (on pages 7-9) that the pins used by ports A through L **are** tri-state high-impedance input pins at reset under all conditions, including when the clock is halted (obviously, any pin Arduino's bootloader subsequently makes use of could behave differently if I tried to hijack it for double-duty reading a button/switch... but the Mega2560 has so many pins, there really isn't any *reason* to reuse pins Arduino uses for its own purposes).

Offhand, I can think of three potential remaining concerns:

* If I screw up and accidentally execute code that configures a pin connected directly to ground through a closed switch as a high output, the pin (and probably the whole chip) is likely to go up in smoke. I can deal with this risk.

* If I were powering it with batteries, I might care about the constant power drain wasting battery life. I'm not, and I don't.

* I'm not quite sure whether "OK to connect directly to ground through a *momentary* pushbutton" necessarily equates to "OK to connect directly to ground through a *switch* that might conceivably be closed and continuously conducting current for the life of the circuit.

So... have I missed anything? And **is** #3 a legitimate concern, or is it something that's not worth caring about if you're talking about something like 8 pins connected through a DIP switch?

Illustrative circuit:

`Ground <-- [switch] --> IO pin (configured for input, internal pullup enabled)`

body:
> If I screw up and accidentally execute code that configures a pin connected directly to ground through a closed switch as a high output, the pin (and probably the whole chip) is likely to go up in smoke. I can deal with this risk.

In addition to “there is an obvious bug”, there could also be a bug that is only triggered in very rare conditions, or a “cosmic ray” event which causes the processor to mis-execute instructions.

Or, maybe a metal tool or piece of debris fell across two of the processor pins and the other pin _is_ an output that's currently high. (This is impossible to protect against in all cases, of course.)

In any of these cases, the hazard is that you're **turning a situation where the device misbehaves temporarily into a situation where the device is permanently damaged.**

Will this happen? Likely not. Is it worth protecting against? Depends on your application, on hard-to-quantify risk probabilities, and how much of a bother it would be to replace the processor.


sender: user

sender: assistant

body: It is usually better to use a resistor when connecting to either +5V or ground. This protects the uP against software bugs, particularly during a hectic debug effort. Even moving on to the next project while forgetting the existing wiring can be a source of trouble.


message:
Proteus potentiometer value always highest

[![proteus schematic][1]][1]

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

    #include <Servo.h>

    #define potpin A0
    int savebutton=2;
    int button1=3;
    int button2=4;
    int button3=5;

    Servo servo1;
    Servo servo2;
    Servo servo3;

    int servo1ipos=90;
    int servo2ipos=90;
    int servo3ipos=90;

    int val=0;

    void setup() {
      // put your setup code here, to run once:
      Serial.begin(9600);
      pinMode(savebutton,INPUT);
      pinMode(button1,INPUT);
      pinMode(button2,INPUT);
      pinMode(button3,INPUT);

      servo1.attach(6);
      servo2.attach(7);
      servo3.attach(8);
      servo1.write(servo1ipos);
      servo2.write(servo2ipos);
      servo3.write(servo3ipos);

    }

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

    }

    int servocontrol(){
      if(digitalRead(button1)==LOW){
        potvalue();
        Serial.println(val);
        servo1.write(val);
        delay(200);
      }
    }
    int potvalue(){
        val=analogRead(potpin);
    }

Basicly I only read 1023 value instead of potentiometer value I couldnt figure it out need help.

Update:
I came up solution by connecting 5V into Arduino's VCC pin.


message:
"Simple" code...but what have I done wrong?

This code  compiles without problem, but doesn't work at all... The switch does not set the LED low and the while loop doesn't work, plus the serial print doesn't print....
Until I put the while loop in pressing either button would change the LED state. I wanted to make the sequence "button one, LED change, THEN button two"
I'm certain to have missed something...
```
const int buttonPin1 = 2;     // the number of the pushbutton 1 pin 2
const int buttonPin2 = 7;     // the number of the pushbutton 2 pin 7
const int ledPin = 13;      // the number of the LED pin

// variables will change:
int buttonState1 = 0;         // variable for reading the pushbutton status
int buttonState2 = 0;
int i = 0;

void setup() {
// initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);
// initialize the pushbutton pin 1 as an input:
  pinMode(buttonPin1, INPUT);
// initialize the pushbutton pin 2 as an input:
  pinMode(buttonPin2, INPUT);
  Serial.begin(9600);
}

void loop() {

  digitalWrite(ledPin, HIGH);

// read the state of the pushbutton value:
  buttonState1 = digitalRead(buttonPin1);

// check whether a  pushbutton is pressed.
// if it is, the buttonState is HIGH:

  if (buttonState1 == HIGH) {
// turn LED off:   //
    digitalWrite(ledPin, LOW);
    while (1) {
      (buttonState1 == LOW);
      if (buttonState1 == LOW) {
        Serial.println("1");
      }
      {
        break;
      }
    }

    delay[1000];

    digitalWrite(ledPin, HIGH);

// read the state of the pushbutton 2 value:
    buttonState2 = digitalRead(buttonPin2);
    if (buttonState2 == HIGH) {
// turn LED off:
      while (1) {
        if (buttonState2 == LOW) {
          break;
        }
      }
      digitalWrite(ledPin, LOW);

      delay(10000);
      digitalWrite(ledPin, HIGH);

    }
  }
}

```
[![enter image description here][1]][1]

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

body:
I think there’s a misunderstanding of how variables work.

Your code is only reading the real state of *buttonPin1* once (before the first `if ()` statement) and copies the value read from the I/O port *as it is at that moment* to the variable *buttonState1*, by executing `buttonState1 = digitalRead(buttonPin1);`.

After you’ve copied the value read from the *buttonPin1* port to the *buttonState1* variable, this variable will no longer change or reflect the actual button status. I.e. the value of the variable *buttonState1* will not automagically change when you push or release button 1. *buttonState1* is a normal program variable and not coupled to the I/O port.

If you want to continue to check the current button status, you have to continuously read the I/O port, by using `digitalRead()` statements where appropriate.

The same goes for *buttonPin2* and *buttonState2*.


message:
get data from arduino using python

I am trying to **read potential meter data from Arduino using python**, with the program on Arduino as follows :
```
#include <cvzone.h>

SerialData serialData;
int sendVals[2];

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

void loop() {
  int potVal = analogRead(A0);
  sendVals[0]= potVal;
  serialData.Send(sendVals);
}
```
the program on the arduino side is running fine

and program in python as follows
```
from cvzone.SerialModule import SerialObject

arduino = SerialObject("COM7")

while True:
   data = arduino.getData()
   print(data[0])
```
but I get this error:
```none
Traceback (most recent call last):
    data = arduino.getData()
  File "C:...\site-packages\cvzone\SerialModule.py", line 68, in getData
    data = data.decode("utf-8")
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xf7 in position 0: invalid start byte
```
How to solve it?

body:
I would embed the call to `.getData()` into a `try` block and handle this specific exception with `except UnicodeDecodeError`. There can always be a transmission error, especially when the script is started.

However, I would do it differently:

    void loop() {
      Serial.println(analogRead(A0));
    }

...and on the python side use `serial.readline()` from pyserial instead.
But I don't know cvzone and you might have a reason to use this instead of the commonly used pyserial.


body:
There seems that there *may* be an issue with the implementation of `getData()` in [`SerialModule.py`][1].

From [line 62][2]

```python
    def getData(self):
        """
        :param numOfVals: number of vals to retrieve
        :return: list of data received
        """
        data = self.ser.readline()
        data = data.decode("utf-8")
        data = data.split('#')
        dataList = []
        [dataList.append(d) for d in data]
        return dataList[:-1]
```

The block of code containing the `readLine()` should probably be with in a `try...except` block, like so:

```python
    def getData(self):
        """
        :param numOfVals: number of vals to retrieve
        :return: list of data received
        """
        try:
            data = self.ser.readline()
            data = data.decode("utf-8")
            data = data.split('#')
            dataList = []
            [dataList.append(d) for d in data]
            return dataList[:-1]
        except Exception as e:
            print(e)
            self.ser.close
```

An issue has been raised on Github: [SerialModule.py - readLine() should be within try block. #49][3]

  [1]: https://github.com/cvzone/cvzone/blob/master/cvzone/SerialModule.py
  [2]: https://github.com/cvzone/cvzone/blob/master/cvzone/SerialModule.py#L67
  [3]: https://github.com/cvzone/cvzone/issues/49


message:
I have been having a lot of trouble adding a countdown to a piece of code

This is the code. The /// are where I added the countdown. Unfortunately the countdown only goes down 9 seconds. What I want it to do is go down the full 24 hours. I have been trying to fix this error for months with no luck.

```
int beeper_pin      = 2; //Naming buzzer pin
int resetGarden_pin = 3; //Naming the warning led pin
int pump_pin        = 6; //Naming the pump pin

#include <LiquidCrystal_I2C.h> // Driver Library for the LCD Module

LiquidCrystal_I2C lcd(0x27, A4, A5);

void clearLCDLine(int line)
{
  lcd.setCursor(0, line);
  for (int n = 0; n < 20; n++) // 20 indicates symbols in line. For 2x16 LCD write - 16
  {
    lcd.print(" ");
  }
}

void beepWarning() {            //Makes beeping a subroutine

  lcd.setCursor(0, 0);
  lcd.print("WARNING");
  delay(100);
  lcd.setCursor(0, 1);
  for (int x = 0; x < 3; x++) {

    lcd.setCursor(0, 1);
    lcd.print("WATER PUMP ACTIVE");
    delay(100);
    clearLCDLine(1);
    lcd.setCursor(0, 1);
    lcd.print("WATER PUMP ACTIVE.");
    delay(100);
    clearLCDLine(1);
    lcd.setCursor(0, 1);
    lcd.print("WATER PUMP ACTIVE..");
    delay(100);
    clearLCDLine(1);
    lcd.setCursor(0, 1);
    lcd.print("WATER PUMP ACTIVE...");
    delay(100);
    clearLCDLine(1);
  }

  lcd.setCursor(0, 1);
  lcd.print("WATER PUMP ACTIVE...");

  for (int x = 0; x < 3; x++) {   //Repeats 3 times

    digitalWrite(beeper_pin, HIGH); //Turn on buzzer
    delay(100);                     //Delay of 400 milliseconds
    digitalWrite(beeper_pin, LOW);  //Turns off buzzer
    delay(100);                     //Delay of 400 milliseconds

  }
}

void SOSWarning() {            //Makes SOS a subroutine

  clearLCDLine(1);
  lcd.setCursor(0, 0);
  lcd.print("WPA Reset Aerogarden");

  for (int x = 0; x < 3; x++) {   //Repeats 3 times

    for (int d = 0; d < 3; d++) {   //Repeats 3 times
      digitalWrite(beeper_pin, HIGH); //Turn on buzzer
      delay(200);                     //Delay of 400 milliseconds
      digitalWrite(beeper_pin, LOW);  //Turns off buzzer
      delay(200);                     //Delay of 400 milliseconds
    }

    for (int a = 0; a < 3; a++) {   //Repeats 3 times
      digitalWrite(beeper_pin, HIGH); //Turn on buzzer
      delay(400);                     //Delay of 400 milliseconds
      digitalWrite(beeper_pin, LOW);  //Turns off buzzer
      delay(400);                     //Delay of 400 milliseconds
    }

    for (int d = 0; d < 3; d++) {   //Repeats 3 times
      digitalWrite(beeper_pin, HIGH); //Turn on buzzer
      delay(200);                     //Delay of 400 milliseconds
      digitalWrite(beeper_pin, LOW);  //Turns off buzzer
      delay(200);                     //Delay of 400 milliseconds
    }

    delay(500);                     //Delay of 500 milliseconds
  }
}

void weekDelay() { //Makes waiting for a week a subroutine
  clearLCDLine(1);
  lcd.setCursor(0, 0);
  lcd.print("Waiting One Week");

long hour = 23, minute = 59, second = 59;//second //////////////////////////
long countdown_time = (hour * 3600) + (minute * 60) + second; ///////////////////////////////////////////////////////////////////////////

  long countdowntime_seconds = countdown_time - (millis() / 1000); /////////

  if (countdowntime_seconds >= 0) {   ///////////////////////////////////////////////
    long countdown_hour = countdowntime_seconds / 3600;
    long countdown_minute = ((countdowntime_seconds / 60) % 60);
    long countdown_sec = countdowntime_seconds % 60;
    lcd.setCursor(4, 1);
    if (countdown_hour < 10) {
      lcd.print("0");
    }
    lcd.print(countdown_hour);
    lcd.print(":");
    if (countdown_minute < 10) {
      lcd.print("0");
    }
    lcd.print(countdown_minute);
    lcd.print(":");
    if (countdown_sec < 10) {
      lcd.print("0");
    }
    lcd.print(countdown_sec);
  }
  delay(500);///////////////////////////////////////////////////////////////

  delay(500);

  delay(86400000);
  clearLCDLine(0);
  lcd.setCursor(0, 0);
  lcd.print("Waiting Six Days");
  delay(86400000);
  clearLCDLine(0);
  lcd.setCursor(0, 0);
  lcd.print("Waiting Five Days");
}

void pumpOn() {               //Makes turning on the pump a subroutine
  clearLCDLine(1);
  lcd.setCursor(0, 1);
  lcd.print("PUMPING");
  delay(100);
  digitalWrite(pump_pin, HIGH); //Turning on the pump
}

void pumpOff() {              //Makes turning off the pump a subroutine
  digitalWrite(pump_pin, LOW);  //Turning off the pump
  clearLCDLine(1);
  lcd.setCursor(0, 1);
  lcd.print("WATER PUMP OFF");
  delay(100);
}

void setup() {
  //run once:
  lcd.backlight();
  lcd.init();

  lcd.setCursor(4, 0);//////////////////////////////////////////////////////
  lcd.print("HH:MM:SS"); //////////////////////////////////////////////////

  lcd.clear(); // Clear the screen
  lcd.setCursor(0, 0);
  lcd.print("Aero_Pump V3");
  delay(1000);
  lcd.setCursor(0, 1);
  lcd.print("By Alex");
  delay(1000);
  pinMode (beeper_pin,      OUTPUT); //Setting outputs
  pinMode (resetGarden_pin, OUTPUT); //Setting outputs
  pinMode (pump_pin,       OUTPUT); //Setting outputs
  lcd.clear(); // Clear the screen

  digitalWrite(resetGarden_pin, LOW); //Turning off the reset garden light

  beepWarning(); //Beeps a warning
  pumpOn();      //Turns on the pump
  delay(3000);  //Adds a delay of 24000 milliseconds
  pumpOff();     //Turns off the pump
  weekDelay();   //Waits a week

  beepWarning(); //Beeps a warning
  pumpOn();      //Turns on the pump
  delay(135000);  //Adds a delay of 48000 milliseconds
  pumpOff();     //Turns off the pump
  weekDelay();   //Waits a week
}

void loop() {

  SOSWarning(); //Beeps an SOS warning
  pumpOn();      //Turns on the pump
  delay(48000);  //Adds a delay of 48000 milliseconds
  pumpOff();     //Turns off the pump

  for (int x = 0; x < 3024000; x++) {
    lcd.backlight(); // turn on backlight.
    delay(100);
    lcd.noBacklight(); // turn off backlight
    delay(100);
  }
  lcd.backlight(); // turn on backlight.
}
```

This is more specifically what needs to be fixed:

```
long hour = 23, minute = 59, second = 49;//second //////////////////////////
long countdown_time = (hour * 3600) + (minute * 60) + second; ///////////////////////////////////////////////////////////////////////////

  long countdowntime_seconds = countdown_time - (millis() / 1000); /////////

  if (countdowntime_seconds >= 0) {
    long countdown_hour = countdowntime_seconds / 3600;
    long countdown_minute = ((countdowntime_seconds / 60) % 60);
    long countdown_sec = countdowntime_seconds % 60;
    lcd.setCursor(4, 1);
    if (countdown_hour < 10) {
      lcd.print("0");
    }
    lcd.print(countdown_hour);
    lcd.print(":");
    if (countdown_minute < 10) {
      lcd.print("0");
    }
    lcd.print(countdown_minute);
    lcd.print(":");
    if (countdown_sec < 10) {
      lcd.print("0");
    }
    lcd.print(countdown_sec);
  }
```

This is some edited code that I have tried but might have made a mistake on because it does 0 days instead of 7 and (Hours/Min/Sec) 04:09:36.
```
void weekDelay() { //Makes waiting for a week a subroutine
  clearLCDLine(1);
  clearLCDLine(0);
  lcd.setCursor(0, 0);
  lcd.print("Waiting One Week");

  unsigned long start = millis();
  unsigned long week_secs = 7 * 24 * 3600;
  unsigned long countdowntime_seconds;

  while (countdowntime_seconds = week_secs - (millis() - start)/1000){
     char buff[80];
     unsigned long countdown_day = countdowntime_seconds / 3600 / 24;
     int countdown_hour = (countdowntime_seconds / 3600) % 24;
     int countdown_minute = ((countdowntime_seconds / 60) % 60);
     int countdown_sec = countdowntime_seconds % 60;
     sprintf(buff," days, d:d:d",
            (int) countdown_day,
            countdown_hour,
            countdown_minute,
            countdown_sec
            );
     Serial.print(buff);
     clearLCDLine(1);
     lcd.setCursor(2, 1);
     lcd.print(buff);
     delay(1000);
     }
}
```

body:
I'd try something with a `while(){}` loop and a `sprintf()`, like:

    void weekDelay() { //Makes waiting for a week a subroutine
      unsigned long start = millis();
      unsigned long week_secs = 7 * 24 * 3600;
      unsigned long countdowntime_seconds;

      while (countdowntime_seconds = week_secs - (millis() - start)/1000){
         char buff[80];
         unsigned long countdown_day = countdowntime_seconds / 3600 / 24;
         // or maybe
         //int  countdown_day = (int)(countdowntime_seconds / 3600UL / 24UL);

         int countdown_hour = (countdowntime_seconds / 3600) % 24;
         int countdown_minute = ((countdowntime_seconds / 60) % 60);
         int countdown_sec = countdowntime_seconds % 60;
         sprintf(buff," days, d:d:d",
                (int) countdown_day,
                countdown_hour,
                countdown_minute,
                countdown_sec
                );
         clearLCDLine(1);
         lcd.setCursor(0, 0);
         lcd.print(buff);
         delay(1000);
         }
    }

Or make it more general and start it off like:

    void coundownDelay(unsigned long seconds) { //Makes waiting for a week a subroutine
      unsigned long start = millis();
      unsigned long countdowntime_seconds;

      while (countdowntime_seconds = seconds - (millis() - start)/1000){

         ...

    }

and call like:

      ...
      countdownDelay(7 * 24 * 3600);   //Waits a week
      ...


message:
Arduino Nano: Send a few bytes over Serial with as little delay as possible

My scenario is the following:

I have a few buttons connected to an Arduino Nano, which is connected to my PC over Serial. Now I want to send a few bytes whenever a button is pressed, to be interpreted by my Computer. However, I noticed a significant, unregular delay (feels like something between almost instantaneous transmission up to a delay of easily ~300 milliseconds), until the message is received by my computer, and I want to get rid of that.

I understand that Arduinos make use of a Serial Buffer, and only send over data once the buffer is full (or some sort of timeout probably), and I think that is the culprit - however I don't see a way of forcing the Arduino to send the data ASAP. I tried just sending over exactly 64 bytes (which, according to what I read, should be the buffer size), but that doesn't help as well (can I however decrease the buffer size or is there a way to send bytes exactly until the buffer is full?)

I don't think baudrate changes anything either, as I'm experiencing problems with the "ping" rather than with the bandwidth (and I also tried anything from 9600 to 115200).

Maybe I'm also completely wrong and the delay happens on the side of my computer, but I don't know if there is anything to change that - I'm looking at the Serial Monitor or at a small `pyserial` script, both of which have the delay:
```
arduino = serial.Serial(serial_port}, 115200, timeout=.1)
while True:
    data = arduino.readline().decode("UTF-8").strip()
    if data:
        print(data)
```

The code on the Arduino-side boils down to:

```
#include <digitalWriteFast.h>

#define button1_pin 2

int button1_state = 0;
int last_button1_state = 0;

void setup() {
  Serial.begin(115200);
  pinMode(button1_pin, INPUT_PULLUP);
  while (!Serial) { delay(50); }
  Serial.println("Started");
}

void loop() {
  button1_state = digitalReadFast(button1_pin);

  if (button1_state != last_button1_state) {
    if (button1_state == LOW) {
      Serial.write("d\n");
    } else {
      Serial.write("u\n");
    }
    last_button1_state = button1_state;
    delay(20);
  }
}
```

Then there's also the weirdest thing which I noticed but am not sure about if it's at all plausible:
When the window of the Serial Monitor (the one that ships with the Arduino IDE) is not completely full (meaning there are only some 1-20 rows and the window doesn't need to scroll), I notice the aforementioned delay, but if the Serial Monitor is full (so new content will be on the last line and the window automatically scrolls a bit), I don't. As soon as I clear the output of the window, it's there again. I don't know what to make of this observation, because I definitely don't have any reasonable clue why that may be the case, so maybe it's also just my imagination :shrug:. Using the python-code there is no such behaviour, and the transimission always seems to have a ping of at least 200-300ms.

I hope my problem is understandable, and like I said I am really unsure what even is the culprit (and I see that it's also highly likely that it's on the side of my computer), but does anybody have any idea how I can decrease this delay? Thanks a lot!

body:
>"Slowing down to speed up". _-   a Chinese proverb_

The problem is with your python code. Not sure what your computer's operating system is, but if you are using Mac or Linux, if you run `top` on command line, you will see you have a high CPU utilization causing by your python script. This is because your your python `while True` loop constantly looping without giving the chances for other processes on your computer to use the CPU, bear in mind that Linux, MacOS or Windows are not designed as a real-time operating system.

So how to solve the problem? put your `while True` loop to sleep for a short period of time, this allows other processes on your computer to have chance to run and you will see the CPU utilization go down significantly and everything will running smoothly.

```
import time
arduino = serial.Serial(serial_port}, 115200, timeout=.1)
while True:
    data = arduino.readline().decode("UTF-8").strip()
    if data:
        print(data)
    time.sleep(0.01)
```

With this slight delay, I've seen some CPU utilisation drop from 90% to 3.5%. This is quite a common mistake that many python programmers made, including some quite experienced programmers who are not familiar with network programming.

Try it out and let me know.


body:
Answering my own question in case anybody experiences the same problem eventually: @hcheung's answer was almost correct after all - see the comments to that question.

Important take-away however:
**don't trust the Serial Monitor or Python's `print` to check how quickly the arduino and your computer communicate**!

When ponging back to the Arduino to let it trigger an LED, I noticed that the actual transmission is definitely faster than my eye, far from the 200ms delay I mentioned in the question.
So the problems for me were

a) the *other* code I used to test the connection but didn't post here was faulty
b) The delay I saw in the Serial Monitor/python's `print` is **not the delay of the serial communication** but apparently somewhere later in the printing of the respective content.

Serial communication is definitely faster than the human eye :)


message:
Can arduino show the power drawn from its output pin on serial monitor? If yes, what code should I use?

I want to know is it possible that arduino can show how much power my prototype is drawing from arduino and if it can what would be the code for that.

body:
No, it cannot do power measurement. With an Arduino (and most other microcontrollers) you only have voltage measurement (on the analog input pins).

Though this is half of the power measurement, since power is voltage multiplied by current. Measure the voltage on that pin with an analog pin. Then you need a way to measure the current. For that you need extra hardware. There are current sensors made for Arduino, which measure the current flowing through its pins and giving out a corresponding analog voltage, which you can then measure on an analog pin. Make sure that the current sensor is rated for the correct current range to not overload it or loose resolution (by having a way bigger range in the sensor than with the actual current). For a digital output pin of an Arduino Uno/Nano the max. current should be 20mA.

You can also google for something like "Arduino current sensor". A short search gave me some promising results.

Then when you have measured the voltage and current you can multiply them to get the power.


body:
You cannot directly measure the power, no. But it's simple enough to arrange using a very small amount of extra hardware.

Depending on what the device is you want to monitor there are two ways of creating the circuit that you need. Both require just a single small resistor, and either one or two analog pins.

The simplest arrangement is the "low-side current shunt" and is simply a small resistor between the ground of your device and the ground of the Arduino. This causes a small voltage drop which raises the ground potential of your device slightly, so could have an effect on communication if you're not careful (see the alternative below). Then a connection from the "top" of that resistor to an analog input will allow you to monitor the voltage drop across that resistor. From that, using Ohm's Law, you can calculate the current. That then can give you the power.

Here's a schematic:

<!-- Begin schematic: In order to preserve an editable schematic, please
     don't edit this section directly.
     Click the "edit" link below the image in the preview instead. -->

![schematic](https://i.stack.imgur.com/MJRlq.png)

<!-- End schematic -->

This arrangement does have the benefit that it will work for any power supply voltage, not just the 5V supply pin (for example powering from the VIN pin or 3.3V pin).

If you are powering your device from no more than 5V you can place the resistor in the 5V feed and avoid the offset to the ground voltage. The idea is just the same: use an analog input to monitor the voltage drop across the resistor to calculate the current and hence the power:

<!-- Begin schematic: In order to preserve an editable schematic, please
     don't edit this section directly.
     Click the "edit" link below the image in the preview instead. -->

![schematic](https://i.stack.imgur.com/rnHkf.png)

<!-- End schematic -->

If you want to measure the current being drawn out of a GPIO pin, though, there is an extra step you need to consider. The GPIO has a MOSFET within it which imposes a small resistance of its own on the output. This resistance will of course cause a variation in the output voltage depending on the current drawn from the output pin. So it is important to know what the actual output voltage is rather than assuming that it would be 5V.  For that a second analog input is needed:

<!-- Begin schematic: In order to preserve an editable schematic, please
     don't edit this section directly.
     Click the "edit" link below the image in the preview instead. -->

![schematic](https://i.stack.imgur.com/45PkP.png)

<!-- End schematic -->

Now the voltage drop is calculated as the difference between the voltages measured by A0 and A1. Then all the other calculations are the same.


message:
Add library to CLion project

I have a new project created with PlatformIO in CLion.  I've copied the _Servo-1.1.8_ library into the `include` directory.

```cpp
#include <Arduino.h>
#include "Servo-1.1.8/src/Servo.h"

Servo servo;

void setup() {
}

void loop() {
}
```

I'm getting a compilation error though:

```none
====================[ Build | Production | uno ]================================
C:\Users\USER_NAME\AppData\Local\JetBrains\Toolbox\apps\CLion\ch-0\213.5744.254\bin\cmake\win\bin\cmake.exe --build C:\Users\USER_NAME\Documents\Arduino\MultiServoCallibration\cmake-build-uno --target Production
[1/1] cmd.exe /C "cd /D C:\Users\USER_NAME\Documents\Arduino\MultiServoCallibration && platformio -c clion run -euno"
FAILED: CMakeFiles/Production C:/Users/USER_NAME/Documents/Arduino/MultiServoCallibration/cmake-build-uno/CMakeFiles/Production
cmd.exe /C "cd /D C:\Users\USER_NAME\Documents\Arduino\MultiServoCallibration && platformio -c clion run -euno"
Processing uno (platform: atmelavr; board: uno; framework: arduino)
--------------------------------------------------------------------------------
Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/atmelavr/uno.html
PLATFORM: Atmel AVR (3.4.0) > Arduino Uno
HARDWARE: ATMEGA328P 16MHz, 2KB RAM, 31.50KB Flash
DEBUG: Current (avr-stub) On-board (avr-stub, simavr)
PACKAGES:
 - framework-arduino-avr 5.1.0
 - toolchain-atmelavr 1.70300.191015 (7.3.0)
LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 5 compatible libraries
Scanning dependencies...
No dependencies
Building in release mode
Compiling .pio\build\uno\src\main.cpp.o
Linking .pio\build\uno\firmware.elf
C:\Users\USER_NAME\AppData\Local\Temp\ccmN7v6f.ltrans0.ltrans.o: In function `_GLOBAL__sub_I_servo':
<artificial>:(.text.startup+0x98): undefined reference to `Servo::Servo()'
collect2.exe: error: ld returned 1 exit status
*** [.pio\build\uno\firmware.elf] Error 1
========================== [FAILED] Took 1.18 seconds ==========================
ninja: build stopped: subcommand failed.
```

I've never used CMake before, so it might well be something super simple like adding a line to some config to include that library.

body:
For what it's worth, I asked a [similar question][1] on StackOverflow, on the chance that the slightly different crowd might include someone who uses CLion + PlatformIO for non-Arduino embedded work and has a more authoritative opinion on the topic.

I have no idea whether it's actually safe or a good idea, but for what it's worth, I was able to add an Arduino library to **my** project by doing the following:

1. Install PlatformIO with bundled VS Code, install CLion, then configure CLion to use PlatformIO.
2. Using CLion, create a new PlatformIO Arduino sketch. Let CLion spin its wheels, do some things that might or might not have ultimately made a difference, and make sure it's in a state where it can build and deploy successfully using CLion. I personally just called Serial.start(9600) and Serial.println("something") to output to serial, then verified it actually worked.
3. Exit CLion, and launch VS Code. Add the folder containing the sketch created in step 2 to its workspace.
4. Use VS Code to add the library. Wait for it to finish downloading, and exit VS Code.
5. Relaunch CLion, and try to use the new library.

Be warned, I have absolutely *no idea* yet whether or not this is actually kosher. I'm under the impression that when you're using PlatformIO with CLion, 100% of everything is actually managed by PlatformIO, and all CLion itself does is stub through the call to launch CMake. Assuming VS Code is the same way, this should theoretically be OK... but until someone intimately familiar with PlatformIO and the way it integrates with both CLion and VS Code reassures me that it is, I'm a little bit nervous about it.

That said... if it actually *is* safe to do, it's probably the best way to add an Arduino library to a CLion-PlatformIO project since (AFAIK) CLion itself has absolutely no comparable functionality (via the PlatformIO plugin or otherwise), and I've encountered a few libraries for SSD1306 OLED use that are a major *pain* to copy into a project by hand from their Github repo (because the OLED library has dependencies on somebody else's graphics library, which itself has dependencies on somebody else's math library and menu library, the menu library has dependencies on one or two more libraries... well, you get the idea. Pain. The exact reason things like Gradle and Maven exist for Android & Java, and CMake theoretically now exists for C(++), even though it still seems to be pretty useless in Arduino-land. ;-)

  [1]: https://stackoverflow.com/questions/70387357/how-to-add-arduino-library-to-clion-platformio-project


message:
Arduino controlled 25A 12V DC relay

I have an air compressor that I often give difficult tasks, where the compressor needs to run longer than it was designed for.  So it gets close to overheating, which requires periodically giving the compressor some "cool down" time, turned off.

Rather than walk into my garage every couple of minutes to turn the compressor on or off, I'd like to automate the process with a little arduino board.

The problem is the compressor is run by a 25A 12V DC line.  Most relays I can find that are Arduino compatible (3.3v DC control) max out at 10A.

I'm curious if there is a smart way to do this efficiently.  Two solutions that come to mind are:

 1) Control 3 or 4 10A relays with the Arduino, and parallelize the current heading to the compressor across multiple relays.

 2) Use one relay controlled by the Arduino, and use that relay to control a secondary big relay, that could control the 25A line.

Neither seems like a very efficient approach to the problem.  I don't know for certain but I worry that perhaps with (1), one relay might be a better conductor than the others, so perhaps one might eventually see a cascade of overheating relays.

Perhaps someone here that's more familiar with circuit design could suggest a better approach.

edit: After a little digging it looks like option (2) is the standard route most often traveled.

[![enter image description here][1]][1]

This is an OMRON relay that is powered by a 12VDC supply (0.167A), and can switch a 28VDC 30A line.   So I will double relay it, using an Adafruit featherwing to switch the 12VDC supply, which will then switch this big OMRON relay.   In my pile of old AC/DC converters I found a 1A 12V supply that's sufficient to run the OMRON relay.  Provided I haven't overlooked anything this is likely a decent solution.

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

body:
Do not double relay it (at least not parallel aka Option 1).  Relays have a tendancy to bounce or take time.  This exposes you to a potential for only one relay to be connected for a time.  Worse, if someone decides to use the relays as high, low instead of closed, open it will short high to low for a time.

The series relay solution is sound but not efficient.  Relays are almost never the efficient approach (there are cases where infrequent switching occurs where a relay simply holding a position without power for long durations can be efficient).  A relay module is essentially a mosfet and a relay.  Mosfet controls the coil, and if you will have one of those, might as well go for a 12V mosfet of appropriate amperage.  I used to have some arduino compatible 3D printer heat bed mosfets that went up to 25A (on paper) so I can't imagine they're impossible to obtain.

You also mention digging power supplies for your relay.  If you are going so far as to need a 12V power supply, is there one providing for the compressor itself?  If so, could you just control the wall outlet AC that powers the supply?  Amperage would be a lot lower and AC can allow use of some rather nifty "Solid State Relay" devices (as well as relay modules, smart outlets, etc).


message:
Serial connection between arduino and processing doesn't work; Port busy

I'm trying to connect arduino and processing via serial. Whenever I run the processing sketch I get the following error in Processing:

```
RuntimeException: Error opening serial port COM26: Port busy
Could not run the sketch (Target VM failed to initialize).
```

Below is the arduino sketch and processing code, which I "borrowed" from [here](https://startingelectronics.org/software/processing/find-arduino-port/), to try to programmatically find the correct serial port to connect to.

Arduino:

```lang-cpp
int var;

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

void loop() {
  if (Serial.available()) {
    var = Serial.read();
  }
  Serial.println(var);
  delay(100);
}
```
Processing:

```lang-java
import processing.serial.*;

Serial ser_port;                // for serial port
PFont fnt;                      // for font
int num_ports;
boolean device_detected = false;
String[] port_list;
String detected_port = "";

void setup() {
  size(400, 200);                         // size of application window
  background(0);                          // black background
  fnt = createFont("Arial", 16, true);    // font displayed in window

  println(Serial.list());

  // get the number of detected serial ports
  num_ports = Serial.list().length;
  // save the current list of serial ports
  port_list = new String[num_ports];
  for (int i = 0; i < num_ports; i++) {
    port_list[i] = Serial.list()[i];
  }
}

void draw()
{
  background(0);
  // display instructions to user
  textFont(fnt, 14);
  text("1. Arduino or serial device must be unplugged.", 20, 30);
  text("   (unplug device and restart this application if not)", 20, 50);
  text("2. Plug the Arduino or serial device into a USB port.", 20, 80);

  // see if Arduino or serial device was plugged in
  if ((Serial.list().length > num_ports) && !device_detected) {
    device_detected = true;
    // determine which port the device was plugged into
    boolean str_match = false;
    if (num_ports == 0) {
      detected_port = Serial.list()[0];
    } else {
      // go through the current port list
      for (int i = 0; i < Serial.list().length; i++) {
        // go through the saved port list
        for (int j = 0; j < num_ports; j++) {
          if (Serial.list()[i].equals(port_list[j])) {
            break;
          }
          if (j == (num_ports - 1)) {
            str_match = true;
            detected_port = Serial.list()[i];
          }
        }
      }
    }
  }
  // calculate and display serial port name
  if (device_detected) {
    text("Device detected:", 20, 110);
    textFont(fnt, 18);
    text(detected_port, 20, 150);
    ser_port = new Serial(this, detected_port, 9600);
  }
}
```
I am a newbie at this, so not sure what I'm doing wrong. Would appreciate any help :)

body:
I tried your Processing sketch, and it does detect and try to connect to the serial port, but fails for some reason.

Processing "code" can include a `try catch` block to help you diagnose the issue. Using this modified sketch, you can print the errors to the console window.

```java
import processing.serial.*;

Serial ser_port;                // for serial port
PFont fnt;                      // for font
int num_ports;
boolean device_detected = false;
String[] port_list;
String detected_port = "";

void setup() {
  size(400, 200);                         // size of application window
  background(0);                          // black background
  fnt = createFont("Arial", 16, true);    // font displayed in window

  println(Serial.list());

  // get the number of detected serial ports
  num_ports = Serial.list().length;
  // save the current list of serial ports
  port_list = new String[num_ports];
  for (int i = 0; i < num_ports; i++) {
    port_list[i] = Serial.list()[i];
  }
}

void draw()
{
  background(0);
  // display instructions to user
  textFont(fnt, 14);
  text("1. Arduino or serial device must be unplugged.", 20, 30);
  text("   (unplug device and restart this application if not)", 20, 50);
  text("2. Plug the Arduino or serial device into a USB port.", 20, 80);

  // see if Arduino or serial device was plugged in
  if ((Serial.list().length > num_ports) && !device_detected) {
    device_detected = true;
    // determine which port the device was plugged into
    boolean str_match = false;
    if (num_ports == 0) {
      detected_port = Serial.list()[0];
    } else {
      // go through the current port list
      for (int i = 0; i < Serial.list().length; i++) {
        // go through the saved port list
        for (int j = 0; j < num_ports; j++) {
          if (Serial.list()[i].equals(port_list[j])) {
            break;
          }
          if (j == (num_ports - 1)) {
            str_match = true;
            detected_port = Serial.list()[i];
          }
        }
      }
    }
  }
  else{
    text("else", 20, 110);
  }
  // calculate and display serial port name
  if (device_detected) {
    text("Device detected:", 20, 110);
    textFont(fnt, 18);
    text(detected_port, 20, 150);
    try{
      ser_port = new Serial(this, detected_port, 9600);
    }
    catch(Exception e){
      // Print detailed error information to the console.
      System.err.println(e);
      e.printStackTrace();
    }
  }
  else{
    text("Device NOT detected:", 20, 140);
  }
}
```

These are the errors I get on my computer using a Arduino Uno.

```
 at processing.serial.Serial.<init>(Unknown Source)
 at processing.serial.Serial.<init>(Unknown Source)
 at sketch_211210a.draw(sketch_211210a.java:85)
 at processing.core.PApplet.handleDraw(PApplet.java:2475)
 at processing.awt.PSurfaceAWT$12.callDraw(PSurfaceAWT.java:1547)
 at processing.core.PSurfaceNone$AnimationThread.run(PSurfaceNone.java:313)
java.lang.RuntimeException: Error opening serial port /dev/tty.wchusbserial620: Port busy
java.lang.RuntimeException: Error opening serial port /dev/tty.wchusbserial620: Port busy
```

Another issue is with this part of the code: `if (device_detected)`. The `draw()` function is like the Arduino `loop()` function in that it keeps looping through the code. It is repeatedly trying to make a new serial connection to the same port, which MAY explain why the `Port busy` error message is repeated in the console error messages.

Using Processing IDE 3.5.3, there is a errors tab at the bottom of the console window. I am getting 2 errors there which don't seem to be involved with the port connection issue.

If you install the `controlP5` library in the Processing IDE, you can use this port testing sketch to see the Port ID change every time you create a new connection with it. I suspect your sketch may connect to the Arduino the first time through the `draw()` function, then it keeps trying to connect to the same port which is busy.

```java
// Serial port(s) connection tester. Processing version 3.5.3.
// For a list of all the ScrollableList Controller methods available,
// use: "ControlP5.printPublicMethodsFor(ScrollableList.class);"
// to print the entire list of the 165 functions to the console.
import controlP5.*;
import java.util.*;
import processing.serial.*;

ControlP5 cp5;
Serial myPort;
Textlabel outputWindowLine1, outputWindowLine2;
String portName;

void setup(){

  size(500, 431);

  // Use a font larger than the default "6px".
  ControlFont font = new ControlFont(createFont("Verdana", 14));

  // ALL CAPS is the default font for the control. Why?
  Label.setUpperCaseDefault(false);

  // Configure a controlP5 ScrollableList.
  cp5 = new ControlP5(this);
  cp5.addScrollableList("dropdown")
    .setPosition(0, 50)
    .setSize(500, 400)
    .setBarHeight(50)
    .setItemHeight(30)
    .setFont(font)
    .addItems(GetSerialPortList())
    .setType(ScrollableList.LIST)
    .setLabel("--- Click on a port name to try and connect to it ---")
    ;

  outputWindowLine1 = cp5.addTextlabel("outputWindowLine1Label")
    .setText("The list of port names is \"scrollable\".")
    .setPosition(0, 0)
    .setColorValue(0)
    .setFont(font)
    ;

  outputWindowLine2 = cp5.addTextlabel("outputWindowLine2Label")
    .setText("Press any character on the keyboard to reload the list.")
    .setPosition(0, 25)
    .setColorValue(0)
    .setFont(font)
    ;
}

void draw(){
  background(255);
}

// User selects a drop down item. Works like a JavaScript onChange()
// event, except you can click on the same item multiple times, this
// code will execute again on each mouse "click" of the same item.
void dropdown(int n){

  // Create a serial connection and send some
  // chars to the "USB to Serial Converter".
  try{

    // Get the port name.
    portName = Serial.list()[n];

    // If you don't do this, you can't re-connect to the same port again.
    // Re-connecting to the same port gives you a new "myPort ID" and may
    // take a few seconds.
    if(myPort != null){
      myPort.clear();
      myPort.stop();
    }

    // Create a Serial Port connection.
    myPort = new Serial(this, portName, 9600);

    // User message.
    outputWindowLine1.setText("Connected to portName: " + portName);
    outputWindowLine2.setText("myPort = " + myPort);

  }
  catch(Exception e){

    // User message.
    outputWindowLine1.setText("Error connecting to portName: " + portName);
    outputWindowLine2.setText("");

    // Print detailed error information to the console.
    System.err.println(e);
    e.printStackTrace();
  }
}

// Refresh the dropdown list of serial port names.
void keyPressed(){
  cp5.get(ScrollableList.class, "dropdown").setItems(GetSerialPortList());
  outputWindowLine1.setText("Serial port list refreshed!");
  outputWindowLine2.setText("");
}

// Get a List of the serial port names.
List GetSerialPortList(){
  List serialPortList = Arrays.asList(Serial.list());
  return serialPortList;
}

```


message:
Code to display binary value from 1 hall sensor A3144 connected with shift register 74HC165 when magnet is brought near to it or taken away?

[![enter image description here][1]][1]

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

I have checked my connections and when I bring a magnet close to the hall sensors the voltage on them which is apprx. 4.5V becomes 0V and when I remove the magnet the sensor turns back to 4.5V. This means that all the hall sensors are responding to the magnets which makes my connections alright. I want to get 0 when magnet is brought closer to the sensor and 1 when taken away.

The below code shows 11111111 continuously and does not get affected even if magnet is brought close or taken away. I expected the code to show 00000000 until magnet is brought closer to any sensor. If magnet is brought closer to 1st sensor, it should have shown 10000000 and so forth.

    int load = 7;
    int clockEnablePin = 4;
    int dataIn = 5;
    int clockIn = 6;

    void setup() {
    Serial.begin(9600);
    pinMode(load, OUTPUT);
    pinMode(clockEnablePin, OUTPUT);
    pinMode(clockIn, OUTPUT);
    pinMode(dataIn, INPUT);
    digitalWrite(clockEnablePin, LOW);
    digitalWrite(clockIn, LOW);
    }

    void loop() {

    //Write pulse to load pin
    digitalWrite(load, LOW);
    digitalWrite(load, HIGH);

    //Get data from 74HC165
    byte incoming = shiftIn(dataIn, clockIn, LSBFIRST);

    // Print to serial monitor
    Serial.print("Pin States: \r\n");
    Serial.println(incoming, BIN);
    delay(200);
    }

    uint8_t shiftIn(uint8_t dataIn, uint8_t clockIn, uint8_t bitOrder) {
    uint8_t value = 0;
    uint8_t i;
    for (i = 0; i < 8; ++i)
    {
     digitalWrite(clockIn, HIGH);
     if (bitOrder == LSBFIRST)
     {
      value |= digitalRead(dataIn) << i;
     }
     else
     {
      value |= digitalRead(dataIn) << (7 - i);
     }
     digitalWrite(clockIn, LOW);
    }
    return value;
    }

---

The code as well as the schematic is correct. The problem was with shift register. Thank you everyone for your suggestions.

body: Preset your clockIn and clockEnablePin pins to LOW in the setup function. Do not manipulate them in the loop function. You do not need to use the delayMicroseconds() functions because the 74HC165 is a great deal faster than Arduino read/write functions.


body:
The connections are correct in the above diagram. I have had a terrible experience with non working shift register. Some 74HC165 don't work properly(might be duplicate). So, try buying from a verified store.

Use this code to get HIGH or LOW value as output. You can change them to 1 or 0 as per your requirement.

I used this code and it works perfect with 8 Hall switches connected to one shift register 74HC165. Don't forget to connect your pins with your Arduino Uno as depicted in the code or you can update your code as per your connections of shift register with Arduino Uno. You can increase the number of inputs by adding more shift register 74HC165 to the circuit & also you just need to update the value of number of shift chips in the below code.

    /* How many shift register chips are daisy-chained.
    */
    #define NUMBER_OF_SHIFT_CHIPS   1

    /* Width of data (how many ext lines).
    */
    #define DATA_WIDTH   NUMBER_OF_SHIFT_CHIPS * 8

    /* Width of pulse to trigger the shift register to read and latch.
    */
    #define PULSE_WIDTH_USEC   5

    /* Optional delay between shift register reads.
    */
    #define POLL_DELAY_MSEC   1

    /* You will need to change the "int" to "long" If the
     * NUMBER_OF_SHIFT_CHIPS is higher than 2.
    */
    #define BYTES_VAL_T unsigned int

    int ploadPin        = 7;  // Connects to Parallel load pin the 165
    int clockEnablePin  = 4;  // Connects to Clock Enable pin the 165
    int dataPin         = 5; // Connects to the Q7 pin the 165
    int clockPin        = 6; // Connects to the Clock pin the 165

    BYTES_VAL_T pinValues;
    BYTES_VAL_T oldPinValues;

    /* This function is essentially a "shift-in" routine reading the
     * serial Data from the shift register chips and representing
     * the state of those pins in an unsigned integer (or long).
    */
    BYTES_VAL_T read_shift_regs()
    {
        long bitVal;
        BYTES_VAL_T bytesVal = 0;

        /* Trigger a parallel Load to latch the state of the data lines,
        */
        digitalWrite(clockEnablePin, HIGH);
        digitalWrite(ploadPin, LOW);
        delayMicroseconds(PULSE_WIDTH_USEC);
        digitalWrite(ploadPin, HIGH);
        digitalWrite(clockEnablePin, LOW);

        /* Loop to read each bit value from the serial out line
         * of the SN74HC165N.
        */
        for(int i = 0; i < DATA_WIDTH; i++)
        {
            bitVal = digitalRead(dataPin);

            /* Set the corresponding bit in bytesVal.
            */
            bytesVal |= (bitVal << ((DATA_WIDTH-1) - i));

            /* Pulse the Clock (rising edge shifts the next bit).
            */
            digitalWrite(clockPin, HIGH);
            delayMicroseconds(PULSE_WIDTH_USEC);
            digitalWrite(clockPin, LOW);
        }

        return(bytesVal);
    }

    /* Dump the list of zones along with their current status.
    */
    void display_pin_values()
    {
        Serial.print("Pin States:\r\n");

        for(int i = 0; i < DATA_WIDTH; i++)
        {
            Serial.print("  Pin-");
            Serial.print(i);
            Serial.print(": ");

            if((pinValues >> i) & 1)
                Serial.print("HIGH");
            else
                Serial.print("LOW");

            Serial.print("\r\n");
        }

        Serial.print("\r\n");
    }

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

        /* Initialize our digital pins...
        */
        pinMode(ploadPin, OUTPUT);
        pinMode(clockEnablePin, OUTPUT);
        pinMode(clockPin, OUTPUT);
        pinMode(dataPin, INPUT);

        digitalWrite(clockPin, LOW);
        digitalWrite(ploadPin, HIGH);

        /* Read in and display the pin states at startup.
        */
        pinValues = read_shift_regs();
        display_pin_values();
        oldPinValues = pinValues;
    }

    void loop()
    {
        /* Read the state of all zones.
        */
        pinValues = read_shift_regs();

        /* If there was a chage in state, display which ones changed.
        */
        if(pinValues != oldPinValues)
        {
            Serial.print("*Pin value change detected*\r\n");
            display_pin_values();
            oldPinValues = pinValues;
        }

        delay(POLL_DELAY_MSEC);
    }


message:
Serial communication with 2 Arduinos and one optocoupler

[![enter image description here][1]][1]I just started working with Arduinos on Tinkercad in a school assignment and have non preexisting electrical knowledge. Tried to read up on the subject and I think I've gotten some of the facts straight but i still can't get them to communicate when using the optocoupler. It works fine with the code if i connect them to each other directly with the tx/rx pins.
```
//Sender code
char string[5] = {'h', 'e', 'l', 'l', 'o'};
void setup()
{
  Serial.begin(9600);
}
void loop()
{
  Serial.write(string,5);
  delay(1000);
}
```
```
//Reciving arduino code

char text[10];

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

void loop()
{
  Serial.readBytes(text,5);
  Serial.println(text);
  delay(1000);
}
```
My guess is I've done something wrong connecting the receiving Arduino but i can't find whats wrong. Any feedback is immensely appreciated!

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

body:
Here is a diagram that I would suggest you to to try it out. The transmitting Arduino pin will turn the internal infrared LED on or off depend on the whether the pin is at LOW or HIGH. When the infrared LED is on, it will turn on the phototransistor, and produce a LOW at the receiving arduino pin.

The LED is optional but it gives you a visual clue on whether you are receiving the data or not.

<!-- Begin schematic: In order to preserve an editable schematic, please
     don't edit this section directly.
     Click the "edit" link below the image in the preview instead. -->

![schematic](https://i.stack.imgur.com/WxIkN.png)

<!-- End schematic -->


body:
EDIT: Even though the OP may be long gone, I wanted to finish what I started with my response.
[![enter image description here][1]][1]

This circuit works fine for me using two UNOs (and one UNO and a serial board for a PC). It is, essentially, the same as in the first response by @hcheung. I used 4.7K and 10K for R2/R4 and they worked fine. I tested it using this program running on both UNOs.

        #include <SoftwareSerial.h>

    SoftwareSerial SSerial(4,5); // RX, TX

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

    }

    void loop() {
      // display whatever comes in through software serial on the Arduino monitor
      if(SSerial.available()) {
        Serial.write(SSerial.read());
      }
      // send whatever comes in on serial to software serial
      if(Serial.available()) {
        SSerial.write(Serial.read());
      }
    }

Note that the programs use software serial and both Tx and Rx are isolated.

If you use this for the hardware serial port on two UNOs, take care. First, don't hang things on 0/1 until after the program loads and how much you can get away with is unclear to me.

Second, if you use a simple program like this, on both UNOs, you will quickly see that the first bytes sent will ping-pong and causes problems.

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

    void loop() {
      if(Serial.available()){
        Serial.write(Serial.read());
      }
    }

I note that the OP was only using one end.

Personally, I found several junk box 4N25s that would not work - that took me a bit of time to figure out. Finally, I don't see the point of optically isolating two UNOs as I did for example, but that is another story.

______ older msg is below _______________________________

A typical way of doing this is illustrated here .
[![enter image description here][2]][2]

// *** I am leaving my original text below, but I want to back off of this a bit. I spent a few hours on this today and I am not happy with the results or my understanding. If I come to any worthwhile conclusions, I will post them. I do like getting to the bottom of things, but I was premature. It is simply not working the way I would expect when I get into 9600 speed and I need to investigate further. Yes, I am accounting for the UNO 0&1 involvement with USB.

// ***

The advantage is that you will not be inverting the line on the receiving end. The choice of R1 and R2 is important. I used R1=330 and R2=1K and transmission was fine at 9600 using a junk box 4N25. My testing was with a single UNO and after uploading a simple program.

See https://github.com/pepaslabs/Electronics/wiki/Designing-a-TTL-Serial-Opto-isolator for a good discussion on exactly this topic.

PS: As mentioned you should have submitted a schematic and you could have used a meter to see what voltages you were getting - those are good steps to understanding things.

  [1]: https://i.stack.imgur.com/vjQ5K.jpg
  [2]: https://i.stack.imgur.com/62BiQ.jpg


message:
Question about ElapsedMillis() library and state machines

I'm making a sort of state machine with 3 states, and I'm actually doing some tests by configuring at the start of my code state=3. I've wired on each pin 2 leds, for a total of 12 leds. I'm using elapsedMillis library (https://github.com/pfeerick/elapsedMillis)  to make things a bit more easy and I'm stuck at 3rd state. At the 3rd state I would like that each couple of leds will stay on for 90ms, than goes of for 1ms. elapsedMillis library allows one to do something like that:

elapsedMillis timeElapsed; //declare global if you don't want it reset every time loop runs

    #include "elapsedMillis.h"

    const int pin0 = 12;
    const int pin1 = 11;
    const int pin2 = 10;
    const int pin3 = 9;
    const int pin4 = 8;
    const int pin5 = 7;

    unsigned long t1 = 500;
    unsigned long waiting = 1000;
    unsigned long t2 = 100;
    unsigned long t3 = 50;
    unsigned long t4 = 1;
    unsigned long t5 = 90;
    unsigned long startTime = 0;

    int ledArray[] = {pin0, pin1, pin2, pin3, pin4, pin5};
    int j, k, a, c = 0;
    int state = 3;

    elapsedMillis elapsedTime;
    elapsedMillis timer1;
    elapsedMillis timer2;
    elapsedMillis timer3;
    elapsedMillis timer4;
    elapsedMillis timer5;

    void setup() {
      pinMode(pin0, OUTPUT);
      pinMode(pin1, OUTPUT);
      pinMode(pin2, OUTPUT);
      pinMode(pin3, OUTPUT);
      pinMode(pin4, OUTPUT);
      pinMode(pin5, OUTPUT);
      Serial.begin(9600);

    }

    void loop() {

      switch (state) {

        case 0:
          // led accesi in modo scalare allo stato 0
          while (k <= 5)
          {

            if (timer1 >= t1)
            {
              if (j <= 5)
              {
                digitalWrite(ledArray[j], HIGH);
                j++;
                timer1 = 0;

              }
              k++;
              elapsedTime = 0;
            }

          }
          // attendo 1s poi vado allo stato 1

          if (elapsedTime >= waiting) {
            state = 1;
            elapsedTime = 0;
          }

          break;

        case 1:

          // led spenti rapidamente in modo scalare

          while (k >= 0) {
            if (timer2 >= t2)
            {
              if (j >= 0)
              {
                digitalWrite(ledArray[j], LOW);
                j--;
                timer2 = 0;
              }
              k--;
              elapsedTime = 0;
            }
          }
          // attendo 0.1s
          if (elapsedTime >= t2) {
            state = 2;

          }
          break;

        case 2:

          // led fade per 3 volte
          if (c <= 3)
          {
            while (a <= 255)
            {
              if (timer3 >= t3) {
                analogWrite(ledArray[3], a);
                timer3 = 0;
                a += 10;

              }

            }
            while (a >= 0)
            {
              if (timer3 >= t3) {
                analogWrite(ledArray[3], a);
                timer3 = 0;
                a -= 10;
              }
            }
            c++;
          }
          else {
            state = 3;
          }

          break;

        case 3:

          if (timer4 >= t5) {
            if (j <= 5) {
              digitalWrite(ledArray[j], HIGH);
              j++;
              timer4 = 0;
              if (timer5 >= t4) {
                  digitalWrite(ledArray[j], LOW);
                  timer5 = 0;
                }
              }
            }
          break;
      }
    }

---

    case 3:

      for (int ii = 0; ii <= 5; ii++)
      {
        digitalWrite(ledArray[ii], ( (ii == j) && (timer4 < 90)));
      }

      if (timer4 > 91) {
        j += backwardScan ? -1 : 1 ;
        if (j > 5) {
          backwardScan = 1;
          j = 5;
        }
        if (j < 0) {
          backwardScan = 0;
          j = 0;
        }
        timer4 = 0;
      }
      break;

For the state3 I would like an effect like the "KITT" knight rider car in 80s TV show. Each couple of 2 leds should move back and forth... in shortly: first 2 leds stays on 90ms and 1ms off, then second 2 leds on 90ms and 1ms off.. etc...

It seems like the leds in the array goes on all together.

body:
You need to maintain more state information to have 'case 3' work like a KITT-style back and forth LED scanner. I think you can do it with three state variables, `j` for which pair of LEDs is active, `backwardsScan` to say which way to go, and `timer4` to remember where in the 91ms cycle we are with the active pair of LEDs.

Try something like this:

    ...
    int backwardsScan = 0;
    ...

    case 3: // KITT-like scanning back and forth 90us/1us
      // j remembers which LED pair is active
      // backwardsScan remembers which direction to scan
      // timer4 handles the 90ms/1ms on-off cycle.
      //
      // reset output leds appropriately for (j,timer4):
      for(int ii=0;ii<=5;ii++){
        digitalWrite(ledArray[ii],( (ii==j) && (timer4 <90)));
      }
      // update KITT state based on (j,backwardsScan,timer4)
      if(timer4 > 91){
         j += backwardsScan? -1 : 1 ;
         if (j > 5){
            backwardsScan = 1;
            j = 5;
            }
         if (j < 0) {
            backwardsScan = 0;
            j = 0;
            }
         timer4 = 0;
         }

      break;

The main trick with state machines is being able to fully determine the complete state from what you are keeping track of--It should be memoryless, in that the state variable(s) fully specify the state, and you don't need to remember the prior state.  If you find you need to know more than one thing, you might need a vector or set of state variables.  One could map the whole led-backwardsScan-timer4 state vector into a single state variable (timer4, modulo 182ms for example,) but that would be unnecessarily complicated. Recognizing all the variables required to fully specify the state is important.


message:
Serial connection between Processing and Arduino doesn't work

I'm trying to connect an Arduino Nano Every and Processing via serial. I'm getting no errors on either side, and the arduino serial functionality works otherwise on the arduino IDE.

I'm connecting on the right port, and the port is busy while the processing code is running (as you would expect), however, the variable inside the arduino is not updating. In fact, the whole if serial.available statement is not executing.

Arduino:

```lang-cpp
int var;

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

void loop() {
  if (Serial.available()) {
    var = Serial.read();
  }
  Serial.println(var);
  delay(100);
}
```
Processing:

```lang-java
import processing.serial.*;

// The serial port
Serial myPort;

void setup() {
  // List all the available serial ports:
  printArray(Serial.list());
  // open port
  myPort = new Serial(this, Serial.list()[2], 9600);
}

void draw() {
  try {
    myPort.write(1);
  }
  catch(Exception e) {
    // Print detailed error information to the console.
    System.err.println(e);
    e.printStackTrace();
  }
  delay(50);
}
```

PS. Asked moderator to close previous post on topic.

body:
Most Arduinos (and the Nano Every is one of them) will reset when the serial connection is reopened (You close it by closing the processing sketch and open it again with the Serial Monitor). Variables are stored in RAM, which gets wiped and reinitialized after a reset or power loss.

So this basically happens: You send the data from processing over serial to the Arduino. The Arduino puts the received value into the variable in its RAM. Then you close the processing sketch, effectively closing the serial connection. Then you open the Serial Monitor, which opens the serial connection again. This triggers the reset of the Arduino and wipes the previous variable value from the RAM. You will only ever see the initial variable value (zero) this way.

You can prevent a reset over serial if you connect a capacitor between the Reset pin and ground.

Though I would say this is probably not what you really should do. Instead just read the data from serial inside your processing sketch. After you have read it you can print it.

---

As a side note: The reset-on-serial-reconnect functionality is used for programming the Arduino over serial (through the USB cable). The new program is written into the program memory (flash) by the bootloader. The bootloader runs directly after a reset/power-on. So to upload a new program to the Arduino the Arduino IDE has to first reset the Arduino to talk to the bootloader.


body:
If you open your Processing sketch and send the data to the Arduino without opening the serial monitor in the Arduino IDE, the data gets through. Here is your Arduino sketch which is slightly modified. Disclaimer - tested on an Uno.

There are other options for serial monitors which may work (varies by OS), as well as other options to interface between Processing and Arduino, such as [Firmata][1]

```c++
int var;

void setup() {
  Serial.begin(9600);
  pinMode(2, OUTPUT);
  digitalWrite(2, LOW);
}

void loop() {
  if (Serial.available()) {
    var = Serial.read();
    digitalWrite(2, HIGH);
    delay(50);
    digitalWrite(2, LOW);
  }
  Serial.println(var);
  delay(100);
}
```

**EDIT**

Arduino IDE version 1.0.6.2 with `Processing` 2.2-ish would let you open the serial monitor in the Arduino IDE and "monitor" the data. Since you can't do this anymore, what about making your `Processing` app open 2 windows. One window could be a home brewed serial monitor, and the other the sketch you are working on. Using `Processing` version 3.5.3, it is only [15 lines of code][2] to open up 2 windows. I'm sure the actual implementation of such a system would be a good challenge.

  [1]: https://www.arduino.cc/en/reference/firmata
  [2]: https://stackoverflow.com/a/32992545/10292145


message:
Stepper motor with microstep driver

In my project I have to control a stepper motor using arduino and microstep driver, can I control the motor so that it can move 90 degrees then stop for like a second and then move again and repeat that sequence.
Can I do that please help I'm stuck in the code and I couldn't figure it out.

body:
Of course you can! There are some excellent libraries to control steppers, e.g. [Stepper](https://www.arduino.cc/en/Reference/Stepper) or [AccelStepper](http://www.airspayce.com/mikem/arduino/AccelStepper/).

What you describe sounds like basic task that is covered in examples of these libraries. For example, this one: https://github.com/arduino-libraries/Stepper/blob/master/examples/stepper_oneRevolution/stepper_oneRevolution.ino. You only need to set correct pins and tweak delays and rotation angles (if your stepper has 200 steps per revolution, then 90 degrees is 50 steps).


message:
ESP32: spi_master: check_trans_valid(801) when using SPI

I use the following code to communicate with a display:

    void Display_HandleDC(spi_transaction_t* p_Transaction)
    {
        gpio_set_level((gpio_num_t)LCD_DC, (uint32_t)p_Transaction->user);
    }

    static void Display_SendCommand(const uint8_t Command)
    {
        spi_transaction_t t;

        memset(&t, 0, sizeof(t));

        t.length = 8;
        t.tx_buffer = &Command;
        t.user=(void*)0;

        assert(spi_device_polling_transmit(_SPI, &t) == ESP_OK);
    }

    static void Display_SendData(const uint8_t* p_Data, uint32_t Length)
    {
        spi_transaction_t t;

        if(Length == 0)
        {
            return;
        }

        memset(&t, 0, sizeof(t));

        t.length = Length * 8;
        t.tx_buffer = p_Data;
        t.user=(void*)1;

        assert(spi_device_polling_transmit(_SPI, &t) == ESP_OK);
    }

    static uint32_t Display_ReadID(void)
    {
        spi_transaction_t t;

        Display_SendCommand(0x04);

        memset(&t, 0, sizeof(t));
        t.length = 4 * 8;
        t.flags = SPI_TRANS_USE_RXDATA;
        t.user = (void*)1;

        assert(spi_device_polling_transmit(_SPI, &t) == ESP_OK);

        return *(uint32_t*)t.rx_data;
    }

    static void Display_Write(int ypos, uint16_t *linedata)
    {
        static spi_transaction_t trans[6];

        for(uint8_t x=0; x<6; x++)
        {
            memset(&trans[x], 0, sizeof(spi_transaction_t));
            if ((x&1)==0) {
                //Even transfers are commands
                trans[x].length=8;
                trans[x].user=(void*)0;
            } else {
                //Odd transfers are data
                trans[x].length=8*4;
                trans[x].user=(void*)1;
            }

            trans[x].flags = SPI_TRANS_USE_TXDATA;
        }

        trans[0].tx_data[0] = 0x2A;
        trans[1].tx_data[0] = 0;
        trans[1].tx_data[1] = 0;
        trans[1].tx_data[2] = 320 >> 8;
        trans[1].tx_data[3] = 320 & 0xFF;

        trans[2].tx_data[0] = 0x2B;
        trans[3].tx_data[0] = ypos >> 8;
        trans[3].tx_data[1] = ypos & 0xFF;
        trans[3].tx_data[2] = (ypos + 1) >> 8;
        trans[3].tx_data[3] = (ypos + 1) & 0xFF;

        // Write the data to memory
        trans[4].tx_data[0] = 0x2C;
        trans[5].tx_buffer = linedata;
        trans[5].length = 320 * sizeof(uint16_t) * 8;
        trans[5].flags = 0x00;

        for(uint8_t x = 0; x<6; x++)
        {
            assert(spi_device_queue_trans(_SPI, &trans[x], portMAX_DELAY) == ESP_OK);
        }
    }

    static void Display_Busy(void)
    {
        spi_transaction_t* rtrans;
        for(uint8_t x=0; x<6; x++)
        {
            assert(spi_device_get_trans_result(_SPI, &rtrans, portMAX_DELAY) == ESP_OK);
        }
    }

    esp_err_t Display_Init(void)
    {
        static uint16_t* Line;

        gpio_set_direction((gpio_num_t)LCD_DC, GPIO_MODE_OUTPUT);
        gpio_set_direction((gpio_num_t)LDC_RESET, GPIO_MODE_OUTPUT);
        gpio_set_direction((gpio_num_t)LCD_BACKLIGHT, GPIO_MODE_OUTPUT);

        if((spi_bus_initialize(HSPI_HOST, &_BusCfg, 0) != ESP_OK) || (spi_bus_add_device(HSPI_HOST, &_DevDcfg, &_SPI) != ESP_OK))
        {
            return ESP_FAIL;
        }

        Display_Reset();
        ESP_LOGI(TAG, "ID: X", Display_ReadID());

        uint32_t Commands = sizeof(_Init_Cmd_List) / sizeof(_Init_Cmd_List[0]);
        ESP_LOGI(TAG, "Loading initialization commands: %u", Commands);

        for(uint32_t i = 0x00; i < Commands; i++)
        {
            ESP_LOGI(TAG, "     Command %u / %u", i + 1, Commands);
            Display_SendCommand(_Init_Cmd_List[i].Command);
            Display_SendData(_Init_Cmd_List[i].Data, _Init_Cmd_List[i].Length & 0x1F);
            if(_Init_Cmd_List[i].Length & 0x80)
            {
                vTaskDelay(100 / portTICK_RATE_MS);
            }
        }

        Line = (uint16_t*)heap_caps_malloc(320 * sizeof(uint16_t), MALLOC_CAP_DMA);
        if(Line == NULL)
        {
            return ESP_FAIL;
        }

        for(uint32_t i = 0x00; i < 320; i++)
        {
            Line[i] = 0xF8;
        }

        Display_Write(0, Line);
        Display_Busy();
        free(Line);

        return ESP_OK;
    }

And this code results in the following error message:

    E (1833) spi_master: check_trans_valid(801): txdata transfer > host maximum
    assertion "spi_device_queue_trans(_SPI, &trans[x], portMAX_DELAY) == ESP_OK" failed: file "src/Peripherals/Display/display.cpp", line 225, function: void Display_Write(int, uint16_t*)
    abort() was called at PC 0x400e47a4 on core 1

    ELF file SHA256: bc86d952445723b2

    Backtrace: 0x4008e8c0:0x3ffb4b30 0x4008ecb9:0x3ffb4b50 0x400e47a4:0x3ffb4b70 0x400d170d:0x3ffb4ba0 0x400d1873:0x3ffb4bc0 0x400d13ea:0x3ffb4bf0 0x400d194b:0x3ffb4c20 0x40088601:0x3ffb4c40
      #0  0x4008e8c0:0x3ffb4b30 in invoke_abort at .platformio\packages\framework-espidf@3.40001.200521\components\esp32/panic.c:155
      #1  0x4008ecb9:0x3ffb4b50 in abort at .platformio\packages\framework-espidf@3.40001.200521\components\esp32/panic.c:172
      #2  0x400e47a4:0x3ffb4b70 in __assert_func at /builds/idf/crosstool-NG/.build/HOST-i686-w64-mingw32/xtensa-esp32-elf/src/newlib/newlib/libc/stdlib/assert.c:62 (discriminator 8)
      #3  0x400d170d:0x3ffb4ba0 in Display_Write(int, unsigned short*) at src/Peripherals/Display/display.cpp:225 (discriminator 1)
      #4  0x400d1873:0x3ffb4bc0 in Display_Init() at src/Peripherals/Display/display.cpp:288
      #5  0x400d13ea:0x3ffb4bf0 in setup() at src/Application/application.cpp:21
      #6  0x400d194b:0x3ffb4c20 in applicationTask(void*) at src/main.cpp:41
      #7  0x40088601:0x3ffb4c40 in vPortTaskWrapper at .platformio\packages\framework-espidf@3.40001.200521\components\freertos/port.c:143

But the error doesn´t occur when I change the DMA channel from `0` to `1`:

    if((spi_bus_initialize(HSPI_HOST, &_BusCfg, 1) != ESP_OK) || (spi_bus_add_device(HSPI_HOST, &_DevDcfg, &_SPI) != ESP_OK))
    {
        return ESP_FAIL;
    }

What´s the difference between both channels and why is only channel `1` working?

body:
Your code initializes the SPI bus by calling the `spi_bus_initialize(HSPI_HOST, &_BusCfg, 0)` function. The last argument of this function (`int dma_chan`) defines the DMA channel to use, which can be 0, 1 or 2.

Selecting DMA channel "0" will actually not select a DMA channel at all ([which is explained in the Espressif documentation](https://docs.espressif.com/projects/esp-idf/en/release-v3.0/api-reference/peripherals/spi_master.html#_CPPv418spi_bus_initialize17spi_host_device_tPK16spi_bus_config_ti)):

* **dma_chan**: Either channel 1 or 2, *or 0 in the case when no DMA is required*. Selecting a DMA channel for a SPI bus allows transfers on the bus to have sizes only limited by the amount of internal memory. *Selecting no DMA channel (by passing the value 0) limits the amount of bytes transfered to a maximum of 32.*

The reason you get an error when your ESP32 tries to do an SPI transfer when no DMA channel is selected (option 0), is that the transfer apparently is larger than 32 bytes.

The error produced is "*E (1833) spi_master: check_trans_valid(801): txdata transfer > host maximum*", which reflects that.

The reason DMA channel 1 works correctly, is because that is an actual DMA channel and it has no limit on the amount of bytes transferred (only limited by the amount of internal memory).


message:
I am trying to add a countdown to my Arduino code but it does 0 days, 04:09:36 instead of starting at 7 days

The code I use probably has a math problem since an Arduino can only count a 16 bit integer. This problem is with the WeekDelay() function.
The project is for an Aerogarden. It pumps water into the garden every week from information based on my collected data. It writes on the LCD information like if it is pumping, waiting (it should have the timer here and display on the LCD), and it can show when it is going to pump with a beep warning. After beeping, pumping, and waiting for a few times I run out of information and do a loop and show a warning message, blinking the LCD and pumping a set amount.
More specifically WeekDelay() should be a delay for a week. It clears the LCD, Sets the cursor to 0,0 and prints "Waiting one week". It should then have a countdown of 24 hours on the screen and then just how many days it is waiting. It does that through clearing the LCD, Setting the cursor, printing days and waiting.

Because of the glitch it does not display any days even though it should show 7. It displays 04:09:36. Somebody was helping me out and said this:

*Ah, it is the integer math interacting with the size of days. 04:09:36 = 4*3600+9*60+36 = 14976 which happens to be equal to 7*24*3600 % 32768. See gammon.com.au/forum/?id=12146 and https://wiki.sei.cmu.edu/confluence/display/c/INT35-C.+Use+correct+integer+precisions for what's happening.*

This is some cut-down version of my code:
```
int beeper_pin      = 2; //Naming buzzer pin
int resetGarden_pin = 3; //Naming the warning led pin
int pump_pin        = 6; //Naming the pump pin

#include <LiquidCrystal_I2C.h> // Driver Library for the LCD Module

LiquidCrystal_I2C lcd(0x27, A4, A5);

void clearLCDLine(int line)
{
  lcd.setCursor(0, line);
  for (int n = 0; n < 20; n++) // 20 indicates symbols in line. For 2x16 LCD write - 16
  {
    lcd.print(" ");
  }
}

void beepWarning() {            //Makes beeping a subroutine

  lcd.setCursor(0, 0);
  lcd.print("WARNING");
  delay(100);
  lcd.setCursor(0, 1);
  for (int x = 0; x < 3; x++) {

    lcd.setCursor(0, 1);
    lcd.print("WATER PUMP ACTIVE");
    delay(100);
    clearLCDLine(1);
    lcd.setCursor(0, 1);
    lcd.print("WATER PUMP ACTIVE.");
    delay(100);
    clearLCDLine(1);
    lcd.setCursor(0, 1);
    lcd.print("WATER PUMP ACTIVE..");
    delay(100);
    clearLCDLine(1);
    lcd.setCursor(0, 1);
    lcd.print("WATER PUMP ACTIVE...");
    delay(100);
    clearLCDLine(1);
  }

  lcd.setCursor(0, 1);
  lcd.print("WATER PUMP ACTIVE...");

  for (int x = 0; x < 3; x++) {   //Repeats 3 times

    digitalWrite(beeper_pin, HIGH); //Turn on buzzer
    delay(100);                     //Delay of 400 milliseconds
    digitalWrite(beeper_pin, LOW);  //Turns off buzzer
    delay(100);                     //Delay of 400 milliseconds

  }
}

void SOSWarning() {            //Makes SOS a subroutine

  clearLCDLine(1);
  lcd.setCursor(0, 0);
  lcd.print("WPA Reset Aerogarden");

  for (int x = 0; x < 3; x++) {   //Repeats 3 times

    for (int d = 0; d < 3; d++) {   //Repeats 3 times
      digitalWrite(beeper_pin, HIGH); //Turn on buzzer
      delay(200);                     //Delay of 400 milliseconds
      digitalWrite(beeper_pin, LOW);  //Turns off buzzer
      delay(200);                     //Delay of 400 milliseconds
    }

    for (int a = 0; a < 3; a++) {   //Repeats 3 times
      digitalWrite(beeper_pin, HIGH); //Turn on buzzer
      delay(400);                     //Delay of 400 milliseconds
      digitalWrite(beeper_pin, LOW);  //Turns off buzzer
      delay(400);                     //Delay of 400 milliseconds
    }

    for (int d = 0; d < 3; d++) {   //Repeats 3 times
      digitalWrite(beeper_pin, HIGH); //Turn on buzzer
      delay(200);                     //Delay of 400 milliseconds
      digitalWrite(beeper_pin, LOW);  //Turns off buzzer
      delay(200);                     //Delay of 400 milliseconds
    }

    delay(500);                     //Delay of 500 milliseconds
  }
}

void weekDelay() { //Makes waiting for a week a subroutine
  clearLCDLine(1);
  clearLCDLine(0);
  lcd.setCursor(0, 0);
  lcd.print("Waiting One Week");

  unsigned long start = millis();
  unsigned long week_secs = 7 * 24 * 3600;
  unsigned long countdowntime_seconds;

  while (countdowntime_seconds = week_secs - (millis() - start)/1000){
     char buff[80];
     int countdown_day = countdowntime_seconds / 3600 / 24;
     int countdown_hour = (countdowntime_seconds / 3600) % 24;
     int countdown_minute = ((countdowntime_seconds / 60) % 60);
     int countdown_sec = countdowntime_seconds % 60;
     sprintf(buff," days, d:d:d",
            countdown_day,
            countdown_hour,
            countdown_minute,
            countdown_sec
            );
     Serial.print(buff);
     clearLCDLine(1);
     lcd.setCursor(2, 1);
     lcd.print(buff);
     delay(1000);
     }
}

void pumpOn() {               //Makes turning on the pump a subroutine
  clearLCDLine(1);
  lcd.setCursor(0, 1);
  lcd.print("PUMPING");
  delay(100);
  digitalWrite(pump_pin, HIGH); //Turning on the pump
}

void pumpOff() {              //Makes turning off the pump a subroutine
  digitalWrite(pump_pin, LOW);  //Turning off the pump
  clearLCDLine(1);
  lcd.setCursor(0, 1);
  lcd.print("WATER PUMP OFF");
  delay(1000);
}

void setup() {
  //run once:
  lcd.backlight();
  lcd.init();

  lcd.setCursor(4, 0);//////////////////////////////////////////////////////
  lcd.print("HH:MM:SS"); //////////////////////////////////////////////////

  lcd.clear(); // Clear the screen
  lcd.setCursor(0, 0);
  lcd.print("Aero_Pump V3");
  delay(1000);
  lcd.setCursor(0, 1);
  lcd.print("By Alex");
  delay(1000);
  pinMode (beeper_pin,      OUTPUT); //Setting outputs
  pinMode (resetGarden_pin, OUTPUT); //Setting outputs
  pinMode (pump_pin,       OUTPUT); //Setting outputs
  lcd.clear(); // Clear the screen

  digitalWrite(resetGarden_pin, LOW); //Turning off the reset garden light

  beepWarning(); //Beeps a warning
  pumpOn();      //Turns on the pump
  delay(3000);  //Adds a delay of 24000 milliseconds
  pumpOff();     //Turns off the pump
  weekDelay();   //Waits a week

  beepWarning(); //Beeps a warning
  pumpOn();      //Turns on the pump
  delay(12000);  //Adds a delay of 24000 milliseconds
  pumpOff();     //Turns off the pump
  weekDelay();   //Waits a week
}

void loop() {

  SOSWarning(); //Beeps an SOS warning
  pumpOn();      //Turns on the pump
  delay(48000);  //Adds a delay of 48000 milliseconds
  pumpOff();     //Turns off the pump

  for (int x = 0; x < 3024000; x++) {
    lcd.backlight(); // turn on backlight.
    delay(100);
    lcd.noBacklight(); // turn off backlight
    delay(100);
  }
  lcd.backlight(); // turn on backlight.
}
```

This is the function that needs to be fixed:

```
void weekDelay() { //Makes waiting for a week a subroutine
  clearLCDLine(1);
  clearLCDLine(0);
  lcd.setCursor(0, 0);
  lcd.print("Waiting One Week");

  unsigned long start = millis();
  unsigned long week_secs = 7 * 24 * 3600;
  unsigned long countdowntime_seconds;

  while (countdowntime_seconds = week_secs - (millis() - start)/1000){
     char buff[80];
     int countdown_day = countdowntime_seconds / 3600 / 24;
     int countdown_hour = (countdowntime_seconds / 3600) % 24;
     int countdown_minute = ((countdowntime_seconds / 60) % 60);
     int countdown_sec = countdowntime_seconds % 60;
     sprintf(buff," days, d:d:d",
            countdown_day,
            countdown_hour,
            countdown_minute,
            countdown_sec
            );
     Serial.print(buff);
     clearLCDLine(1);
     lcd.setCursor(2, 1);
     lcd.print(buff);
     delay(1000);
     }
}
```

body:
As the comment already tells, you are trying to calculate a constant with `int` literals that overflows:

`unsigned long week_secs = 7 * 24 * 3600;`

This is 604800 (0x93A80), but since `int`s are just signed 16 bits numbers (with your compiler system), only the lower 16 bits are taken into account. Fortunately these lower 16 bits are positive in two's complement, and so you get 14976 (hex 0x3A80).

The correct statement uses at least one `unsigned long` value, and the integer promotion rules make sure that all values are converted to that type, too.

`unsigned long week_secs = 7UL * 24 * 3600;`


message:
Random access to SD card using SD.h or another library (ESP32)

I'm trying to use a SD card with my ESP32 in order to save some variables in a txt file. Each variable uses 1 byte, so they can be represented by an 8 bit extended ASCII character.

The issue is it seems that the SD.h library has only 3 open modes (Read only, `FILE_WRITE`, `FILE_APPEND`), and I cannot figure out how to use random access for writing a specific byte of the file.

Imagine the situation: I have a file called `myFile.txt` which initially has a size of 5 bytes, and its content is:
```abcde```

The code I'm using is the following:

```c++
#include <SPI.h>
#include <SD.h>

#define SD_CS_PIN 5

File myFile;

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(115200);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  Serial.println("Initializing SD card...");

  if (!SD.begin(SD_CS_PIN)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");

  myFile = SD.open("/myFile.txt", FILE_WRITE);
  myFile.seek(3);
  myFile.write('a');
  myFile.close();

}

void loop() {}
```

But after running the code, the file has an unexpected behaviour, its size changes from 5 bytes to 4 bytes, and its content is:
```abca```
instead of the expected
```abcae```

I know it happens because when writing into the file I'm using the open mode `FILE_WRITE` which uses the `FILE_APPEND` mode internally, so when doing `myFile.seek(3);`, I'm truncating the file to 4 bytes since the `FILE_APPEND` mode needs to point to the end of the file.

So, my question is, how can I open a file in random access mode with SD.h, or another library?

Thanks in advance!

body:
**Solved!**

The solution was to migrate from the `SD` library to [`mySD`](https://github.com/nhatuan84/esp32-micro-sdcard), which seems to be a `SdFat` wrapper for ESP32.

You can see in the file [`mySD.h`](https://github.com/nhatuan84/esp32-micro-sdcard/blob/master/mySD.h#L30) that the `FILE_WRITE` mode is defined as:

```c++
#define FILE_WRITE (F_READ | F_WRITE | F_CREAT)
```

Which means that it allows random access to the file for writing (`F_WRITE` instead of `FILE_APPEND`).

**PS:** I want to remark @Juraj comment since the forum is mainly for Arduino board questions
> the SD library in ESP32 boards support package is different than the standard Arduino SD library


message:
HC-05 Bluetooth module; two serial ports, COM4 and COM5

I'm learning how to use the Arduino HC-05 Bluetooth module. After pairing to it with my laptop I saw that I was getting two serial links, COM4 and COM5, as can be seen from the picture below.

On COM4 everything is working fine, but on COM5 nothing is happening. Can somebody explain why this is so?

NOTE: I only have one Bluetooth device (the HC-05).

[![enter image description here][1]][1]

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

body:
I found [this answer in Microsoft Technet][1] helpful:

> - when connecting your terminal program to the first you are actually instructing Windows to attempt to establish the Bluetooth connection to the remote paired device, and if the connection is established the RFCOMM channel will be opened for the exchange of data
> - when connecting your terminal program to the second you are actually instructing Windows to load the SPP SDP record and to remain waiting for incoming connections from the remote paired device.

  [1]: https://social.technet.microsoft.com/Forums/en-US/58f690e5-1939-43c2-a2d3-245a527c678b/bluetooth-serial-port-settings-for-windows10-pc?forum=win10itprohardware


message:
When using the IRremote library- why does it say 64 bits when after converting the hex to binary it comes out to be less?

I get this code output on my Serial when the IR receiver gets a signal:

``` cpp
Protocol  : GREE
Code      : 0x01C02350000000E0 (64 Bits)
Mesg Desc.: Model: 1 (YAW1F), Power: Off, Mode: 1 (Cool), Temp: 16C, Fan: 0 (Auto), Turbo: Off, Econo: Off, IFeel: Off, WiFi: Off, XFan: Off, Light: On, Sleep: Off, Swing(V) Mode: Manual, Swing(V): 0 (Last), Swing(H): 0 (Off), Timer: 23:00, Display Temp: 0 (Off)
uint16_t rawData[279] = {...
````

When I convert `0x01C02350000000E0` to binary, however, it usually comes out to less than 64 bits. I'm assuming it has to do with the parameters of my IR receiver and not normal.

body:
You are confusing the data size and the value size.

Yes, your value can be represented using fewer than 64 bits, but the data size that is used to contain that value is 64 bits in size.

It's like saying that "4" is stored in a 6 digit storage space.  It only needs 1 storage slot, but the allocated space is 6 digits. So what is actually stored would be "000004".

As humans we tend to throw away the leading zeroes because they are meaningless. That's because we are able to use flexible storage sizes in our brains. The computer, though, works on fixed sizes - 8 bit, 16 bit, 32 bit, 64 bit, etc.

You can't store that value in a 32 bit variable, but you can in a 64 bit one. It may be wasteful for that specific value, but it's the smallest size that is available that is big enough.


message:
Digital Pins Question

I am new to the world of Arduino and need a little bit of help. I have an Arduino Uno and I am trying to supply 5V to an actuator using the digital pins. It is my understanding that the board I have is capable of doing that. But I can't seem to get 5V from my digital pins.

I would really prefer to not have to use the 5V power pin because I need to supply multiple sources with 5V in an alternating pattern, which I know I can do with the digital pins.

Could I use the analog pins to help with this? Could I supply more power using a battery? Etc.

Thank you in advance.

body:
The digital pins of the Arduino are rated to reliably deliver up to
20 mA. Their _absolute maximum rating_ is 40 mA. Anything
above that risks destroying the microcontroller.

If your device is supposed to pull from 0.24 to 0.38 A, that is too
much for your Arduino pins. With such a high current, you are seeing a
significant voltage drop caused by the internal resistance of the output
transistors. Or it could be that you already fried those transistors.


body:
The most common solution is to use the digital output to turn on a MOSFET that supplies separate power to a high-current device that needs more current than the 20 mA that an ATmega328 microcontroller can safely supply.

The MOSFET is chosen based on the desired current and with the need for a logic-level input.

A typical circuit:

<!-- Begin schematic: In order to preserve an editable schematic, please
     don't edit this section directly.
     Click the "edit" link below the image in the preview instead. -->

![schematic](https://i.stack.imgur.com/nhBoy.png)

<!-- End schematic -->

D1 is needed for an inductive load like a motor. It protects other components.

You might get away without using the resistors (connecting D1 directly to the MOSFET's gate) but the 10 K "pull-down" resistor R1 ensures that the load is off when the Arduino is powering up. Resistor R2 is probably mainly useful for noisy or high-frequency applications..


message:
Is an ESP32 HTTP web server limited to a certain number of Base64 images?

This sketch only displays about nine images (when there are more). Does this mean the ESP32 is limited amount of Base64 images able to be displayed?

    #include <WiFi.h>
    #include <WebServer.h>

    const char* ssid = "ESP32";
    const char* password = "12345678";

    IPAddress local_ip(192,168,1,1);
    IPAddress gateway(192,168,1,1);
    IPAddress subnet(255,255,255,0);

    WebServer server(80);

    // Used for determining the selected pattern and HTML to display:
    int pattern = 0;
    int selectedPattern = 0;

    String circleString = "<img src=\"data:image/png;base64,[encoded data, 6912 characters]\" alt=\"NAME\" style=\"width:100%\">\n";

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

      WiFi.softAP(ssid, password);
      WiFi.softAPConfig(local_ip, gateway, subnet);
      delay(100);

      server.on("/", handle_OnConnect);
      server.onNotFound(handle_NotFound);

      server.begin();
      Serial.println("HTTP server started");
    }
    void loop()
    {
      server.handleClient();

    }

    void handle_OnConnect() {

      server.send(200, "text/html", SendHTML(selectedPattern));
    }

    void handle_NotFound(){
      server.send(404, "text/plain", "Not found");
    }

    String SendHTML(int pattern)
    {
        String ptr = "<!DOCTYPE html> \n";
        // Instance of class String (not a pointer)

        ptr += "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
        // <meta> viewport element makes the web page responsive in any web browser
        // https://www.w3schools.com/css/css_rwd_viewport.asp

        ptr += "\n";

        ptr +="\n";
        ptr +="\n";

          /*  */
          ptr += "
\n"; // 1
            ptr += circleString;
          ptr += "
\n";

          ptr +="1\n";

          ptr += "
\n"; // 2
            ptr += circleString;
          ptr += "
\n";

          ptr +="2\n";

          ptr += "
\n"; // 3
            ptr += circleString;
          ptr += "
\n";

          ptr +="3\n";

          ptr += "
\n"; // 4
            ptr += circleString;
          ptr += "
\n";

          ptr +="4\n";

          ptr += "
\n"; // 5
            ptr += circleString;
          ptr += "
\n";

          ptr +="5\n";

          ptr += "
\n"; // 6
            ptr += circleString;
          ptr += "
\n";

          ptr +="6\n";

          ptr += "
\n"; // 7
            ptr += circleString;
          ptr += "
\n";

          ptr +="7\n";

          ptr += "
\n"; // 8
            ptr += circleString;
          ptr += "
\n";

          ptr +="8\n";

          ptr += "
\n"; // 9
            ptr += circleString;
          ptr += "
\n";

          ptr +="9\n";

          ptr += "
\n"; // 10
            ptr += circleString;
          ptr += "
\n";

          ptr += "
\n"; // 11
            ptr += circleString;
          ptr += "
\n";

          ptr += "
\n"; // 12
            ptr += circleString;
          ptr += "
\n";

          ptr += "
\n"; // 13
            ptr += circleString;
          ptr += "
\n";

        ptr +="\n";
        ptr +="\n";

        return ptr;

    }

>Sketch uses 726230 bytes (55%) of program storage space. Maximum is 1310720 bytes.
>Global variables use 39384 bytes (12%) of dynamic memory, leaving 288296 bytes for local variables. Maximum is 327680 bytes.

body:
You build up the HTML website by concatting strings together by hand in the code. I know this is done in many code throughout the internet, but this is only really practical, if you need to change the website content with every request. Normally it is better to use SPIFFS (or now LittleFS) to store the files and let a fitting webserver library serve them as static files. Additionally you are making Swiss cheese out of your heap memory when you concat `String` variables this often and you might run out of RAM.

I'm not used to LittleFS, so I will write this answer using SPIFFS. But I'm sure you can use LittleFS in a very similar way. I will leave it to you to determine how it fits in with code for SPIFFS.

Have a look at the [ESPAsyncWebServer][1] library and its simple server example. I've used this library for my projects. Try the examples, read the documentation and get an idea how this library is working.

Then have a look at the documentation where it says "Serving static files". I think you want to serve your static files from a directory. That way the library will look for requested files in that complete directory inside of the SPIFFS. Inside that directory you will have your HTML website (named as `index.html`) and all the images as binary data in a format, that a webbrowser can read (like jpg, png, ...). In your HTML website you reference the images with their path. Since in this scenario they all lie in the root directory the path is only the filename (+ the files extension).

When the webbrowser requests the `index.html` from the ESP, the library will serve it from SPIFFS. The webbrowser interprets the site and sees the references to the images. It than tries to load these images, meaning it sends requests to the ESP with the path of the images. The library will search for these files in SPIFFS, will find them and serve them to the webbrowser, who will then display them on the website.

Something like this:

    #include "ESPAsyncWebServer.h"
    #include "SPIFFS.h"

    AsyncWebServer server(80);

    void setup(){
      Serial.begin(115200);
      while(!SPIFFS.begin()){
        Serial.println("Could not mount SPIFFS");
        delay(500);
      }
      server.serveStatic("/", SPIFFS, "/").setDefaultFile("index.html");
      server.begin();
    }

    void loop(){
    }

Note:
- I've left out all Wifi related stuff. You need to add that yourself.
- I've not tested this code, just put it together from one of my working bigger programs.
- You still need to upload the actual files to the ESP SPIFFS. There are many tutorials on how to do that. Just place your files in the root directory of SPIFFS.

  [1]: https://github.com/me-no-dev/ESPAsyncWebServer