message:
Writing multiple inputs to serial port using a while loop

I am trying to get the serial monitor to prompt me to input two settings - the PWM level and the Resonance level. I am being prompted to input the PWM level, but before I can input the Resonance level it is set to zero and then I am asked again for the PWM level.

I am using Serial.flush(); inbetween the commands to clear the serial input, but I still cannot input the Resonance level before it is set to zero.

Here is my code:
```
int PWMPin = 10;       // Pin 10 connects to MOSFET gate on breadboard
int ResPin = 4;        // Pin for the resonator stage

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);   // Define baud rate for console to be 9600
  pinMode(PWMPin, OUTPUT);
  pinMode(ResPin, OUTPUT);

}

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

Serial.println("What PWM level do you want to test?");   // Testing only
 while (Serial.available() == 0) {
     // Wait for user input
  }
  int test_level_PWM = Serial.parseInt();
    analogWrite(PWMPin, test_level_PWM);
    Serial.print("PWM Level: ");
    Serial.println(test_level_PWM);

Serial.flush();

Serial.println("What Resonance level do you want to test?");
 while (Serial.available() == 0) {
     // Wait for user input
  }
  int test_level = Serial.parseInt();
    analogWrite(ResPin, test_level);
    Serial.print("Resonance Level: ");
    Serial.println(test_level);

   delay(1000);

```
Here is the serial monitor output. I was able to input the PWM level but the Resonance level was set to zero immediately after and then I was asked to input the PWM level again.

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

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

body:
Your line

`   Serial.flush();`

is probably intended to remove additional input after the expected numerical input. But that's not what it's doing. (See @jurai's comment)

Either avoid additional input like NewLine characters, or remove them using something like

`while (Serial.available()) {delay(1); Serial.read();}`

( The delay(1); takes care of slowly coming in serial data at 9600 Baud )


sender: user

message:
esp8266 analogRead of 5.5V soil moisture sensor input using voltage divider

On an ESP8266 I try to analogRead(A0) my soil moisture sensor using a voltage divider but I get unexpected low values.

The MT3608 increases the esp's output voltage from 3.3V to 5.5V which is the recommended voltage for my capacitive soil moisture sensor v1.2 (different to the picture below I use v1.2, not v1.0). When there is no voltage divider in the game and the sensor is dry, the sensor outputs ~4.5V (yellow wire). The output is around ~2.3V when the sensor is completely wet.

For my voltage divider I use a 150 Ohm (R1) and a 39 Ohm (R2) resistor. Given ~4.5V Vin on the yellow wire this should provide me with ~0.9V Vout on the green wire, because Vout=Vin*(R2/(R1+R2)). A voltage <=1V I could safely attach to the esp8266 A0 analog pin. However, using the voltage devider I measure only 8,3**mV** instead of the expected 0.9**V**! It drops to 7.7mV when Vin is 2.3V (wet sensor).

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

What am I doing wrong? Any advise is highly appreciated!

For testing I currently use a board which has a build-in internal voltage divider that allows for up to 3.3V input, however in the final design I need to run everything using an ESP12-E without such an internal divider.

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

sender: assistant

body:
When designing a voltage divider with 2 resistors, there are 2 things to consider:

 - The ratio between R1 and R2, which gives the output voltage: U(out) = U(in) * [R2 / (R1 + R2)]
 - The magnitude of each resistors: to get a 1/2 ratio, you need to have R1 = R2 no matter their value. But depending the value of your resistors (it can be 10Ω, 1kΩ, 100kΩ or 10MΩ for example), you will have a different current travelling through the bridge. The higher the resistors, the lower the current, and vice-versa.

When mesuring voltage inside the voltage divider, the ADC can be considered as a load to the circuit (as shown below). Some forums state that the input resistor of the ESP8266 ADC is around 20MΩ. If the resistors of the bridge are too low, the current will be high and will only travel through the bridge, leaving not enough current for the ADC to measure (electrons are lazy and always take the path of least resistance). On the other hand, if the resistors are too high, the current will be to low to be accurately detected as well.

[![Voltage divider with load][1]][1]

In most cases, voltage dividers are build with resistors between 10kΩ and 1MΩ. This allows enough current to travel through the ADC to give an accurate measure of the voltage.

As suggested by dandavis comment, choosing (R1 ; R2) = (15kΩ ; 3,9kΩ) or (150kΩ ; 39kΩ) should work in your circuit.

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


message:
Avoid using delay with the HR-S04 ultrasonic sensor

How can I measure the distance of an HR-S04 ultrasonic sensor with millis and micros?

body:
I have noticed that many people on the net have problems using millis with the sensor to take measurements etc. so I created this sketch to help anyone.

You are free to ask for any clarification about it!

    /*
     *  HC-SR04 sensor measuring
     *
     *  Non-blocking HC-SR04 sensor measuring
     *
     *  The circuit:
     *  - Echo pin connected to pin 2
     *  - Trigger pin connected to pin 3
     *  - VCC pin connected to VCC (5v)
     *  - GND gger pin connected to GND
     *
     *  created 3 Jul 2021
     *  by alessandromrc
     */

    #define trigPin 3
    #define echoPin 2

    unsigned long timerStart = 0;
    unsigned long StartTime = micros();
    bool timer = false;
    const unsigned long HIGH_TRIGGER = 10;
    const unsigned long LOW_TRIGGER = 2;

    float timeDuration, distance;

    enum SensorStatus {
      TRIG_LOW,
      TRIG_HIGH,
      ECHO_HIGH
    };

    SensorStatus sensorStatus = TRIG_LOW;

    bool isTimerReady(const unsigned long Sec) {
      return (micros() - timerStart) < Sec;
    }

    void setup(void) {
      Serial.begin(9600);
      pinMode(trigPin, OUTPUT);
      pinMode(echoPin, INPUT);
    }

    void loop(void) {
      switch (sensorStatus) {
      case TRIG_LOW: {
        digitalWrite(trigPin, LOW);
        timerStart = micros();
        if (isTimerReady(LOW_TRIGGER)) {
          sensorStatus = TRIG_HIGH;
        }
      }
      break;

      case TRIG_HIGH: {
        digitalWrite(trigPin, HIGH);
        timerStart = micros();
        if (isTimerReady(HIGH_TRIGGER)) {
          sensorStatus = ECHO_HIGH;
        }
      }
      break;

      case ECHO_HIGH: {
        if (!timer) {
          Serial.print("Microseconds Passed in initialization: ");
          Serial.println(micros() - StartTime);
          timer = !timer;
          Serial.println("Starting to Measure");
        }
        digitalWrite(trigPin, LOW);
        timeDuration = pulseIn(echoPin, HIGH);
        Serial.print("Measured: ");
        Serial.print(timeDuration * 0.034 / 2);
        Serial.println(" cm");
        sensorStatus = TRIG_LOW;
      }
      break;
      }
    }

[Github Repository][1]

  [1]: https://github.com/alessandromrc/HC-SR04-Ultrasonic-Sensor/blob/main/HC_SR04_Ultrasonic_Sensor.ino


body:
In response to @Majenko comment on the original question, here is some code that I use which uses the Timer1 input capture function to read an ultrasonic sensor.  It also uses the Timer1 PWM generator to create the trigger pulses.  The entire code is interrupt driven and nothing blocks the main program.

It's not built as an official style library with all the extra parts, but the .h and .cpp can be put into a folder in the libraries folder as in the manual installation process.  It's really just a personal library that I use on some of my robots, but I'm happy to share.

The code as written supports the ATMEGA1284P and ATMEGA328P chips.  There are a couple of lines to comment and un-comment to change between the two.

It exposes a singleton instance much like the Serial class, so there's nothing to instantiate.  The pins are all set by hardware, you can't change them.

Depending on how much total range you want, you can set the prescaler to a much lower value.  If you run with no prescaler then the resolution would be something on the order of nearly 100 times what you can get with micros (62.5ns vs 4us resolution).  But that would be shorter distances like 1.2m and less.

https://github.com/delta-G/PingTimer

    #include "PingTimer.h"

    int distance;

    void setup() {

      Serial.begin(9600);
      ping.begin();
      ping.sendPing();

    }

    void loop() {

      //  if the ping sensor has new data save it to distance and print it.
      if(ping.hasNewData()){
        distance = ping.getDistanceMM();
        Serial.print("Current Distance: ");
        Serial.println(distance);
        ping.sendPing();
      }

      //  Do other things not blocked by ping sensor

    }

PingTimer.h

    /*

    PingTimer  --  uses Timer1 Input Capture to read a HC-SR04
         Copyright (C) 2019  David C.

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

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

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

         */

    #ifndef PINGTIMER_H_
    #define PINGTIMER_H_

    #include "Arduino.h"

    // Ping pin on OC1A -- PB1 on 328P.  (UNO pin 9)
                        //-- PD5 on 1284P  (pin 13)
    #define PING_PIN_MASK (1 << 5)
    #define PING_PIN_PORT PORTD

    // Echo pin on ICP1 -- PB0 on 328P  (UNO pin 8)
                        //-- PD6 on 1284P  (pin 14)
    #define ECHO_PIN_MASK (1 << 6)
    #define ECHO_PIN_PORT PIND

    class PingTimer {
    private:
     volatile uint16_t timerVal;
     volatile boolean overflowed;
     volatile boolean newData;

     void initTimer();

     void startPulse();

    public:
     PingTimer();
     void begin();

     void sendPing();
     void echoHandler();
     void overflowHandler();

     boolean hasNewData();
     boolean hasOverflowed();
     uint16_t getTimerVal();

     int16_t getDistanceMM();

    };

    extern PingTimer ping;

    #endif /* PINGTIMER_H_ */

And the PingTimer.cpp

    /*

    PingTimer  --  uses Timer1 Input Capture to read a HC-SR04
         Copyright (C) 2019  David C.

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

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

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

         */

    #include "PingTimer.h"

    PingTimer ping;

    PingTimer::PingTimer(){
     newData = false;
     overflowed = false;
     timerVal = 0;
    }

    void PingTimer::begin() {
     initTimer();
     // ATMEGA328P
    // pinMode(8, INPUT);
    // pinMode(9, OUTPUT);
     // ATMEGA1284P
     pinMode(14, INPUT);
     pinMode(13, OUTPUT);
    }

    void PingTimer::initTimer(){
     cli();
     TCCR1A = 0;  // no PWM
     // Noise Cancel On, RISING Edge , No prescaler, 4ms range.
     TCCR1B |= ((1 << ICNC1) | (1 << ICES1) | (1 << CS11) | (0 << CS10));
     // make sure analog comparator isn't selected as capture input
     ACSR &= ~(1 << ACIC);
     //  Turn off Timer interrupts
     TIMSK1 = 0;
     // setup COMPA for 10us to time the trigger pulse
     // and COMPB for 12ms for out of range signal (a little over 4 meters)
     OCR1AH = 0;
     OCR1AL = 20;  // With prescaler at 8 each tick is 0.5 us.
     OCR1BH = 0xB5;
     OCR1BL = 0xB0; // 0xB5B0 is 46512.  That's a little over 4 meters with prescaler at 8.
     sei();
    }

    //  This is a public facing function to call the startPulse so it can stay private
    //  since it twiddles registers
    void PingTimer::sendPing() {
     startPulse();
    }

    void PingTimer::startPulse(){
     // set pin high and setup PWM unit to
     // turn the pin off 10us later
     cli();
     TCNT1H = 0x00;
     TCNT1L = 0x00;
     //Set up to get one pulse of PWM
     // Clear OC1A on compare match.  10bit fast PWM
     TCCR1A = ((1 << COM1A1) | (1 << WGM11) | (1 << WGM10));
     // Setup input capture interrupt to catch the rising
     // of the echo pin and start the timer
     // Noise Cancel On, RISING Edge ,prescaler at 8 gives a 32ms timer = 5.5 meter range
     TCCR1B = ((1 << ICNC1) | (1 << ICES1) | (1 << CS11) | (0 << CS10) | (1 << WGM12));
     //  Turn on interrupt Input Capture
     TIFR1 = ((1 << ICF1) | (1 << TOV1));
     TIMSK1 = ((1 << ICIE1));
     overflowed = false;
     newData = false;
     sei();
    }

    // Called from ISR
    void PingTimer::echoHandler() {
     if (ECHO_PIN_PORT & ECHO_PIN_MASK) {  //Rising Pin
      // Kill the OC1A PWM unit and return to normal mode
      TCCR1A = 0;
      // Noise Cancel On, FALLING Edge ,prescaler at 8 gives a 32ms timer = 5.5 meter range
      TCCR1B = (1 << ICNC1) | (0 << ICES1) | (1 << CS11) | (0 << CS10);
      // Reset Timer1
      TCNT1H = 0;
      TCNT1L = 0;
      //  Reset Input Capture and Timer Overflow Interrupts
      TIFR1 = (1 << ICF1) | (1 << TOV1);
      //  Turn on interrupts Input Capture and Timer Overflow
      TIMSK1 = (1 << ICIE1) | (1 << TOIE1);
     } else {  // Falling pin
      // Read the ICR1 Register
      uint8_t low = ICR1L;
      uint8_t high = ICR1H;
      timerVal = ((high << 8) | low) - 4; // Noise canceler adds 4 clock cycles

      //  turn off the timer interrupts
      TIMSK1 = 0;
      newData = true;
     }
    }

    // Called from ISR  Timer 1 OVF
    void PingTimer::overflowHandler(){
     //turn off timer interrupts
     TIMSK1 = 0;
     newData = true;
     overflowed = true;
    }

    boolean PingTimer::hasNewData(){
     cli();
     boolean retval = newData;
     newData = false;
     sei();

     return retval;
    }

    boolean PingTimer::hasOverflowed(){
     cli();
     boolean retval = overflowed;
     overflowed = false;
     sei();

     return retval;
    }

    uint16_t PingTimer::getTimerVal() {
     uint16_t retval = 0;
     cli();
     if (overflowed) {
      retval = -1;
     } else {
      uint16_t copy = timerVal;
      retval = copy;
     }
     sei();
     return retval;
    }

    int16_t PingTimer::getDistanceMM() {

     int16_t retval = 0;
     uint16_t copy = getTimerVal();
     if (copy == (uint16_t) -1) {
      retval = -1;
     } else {
      // 16Mhz is 62.5 ns/clock
      // We've got the prescaler dividing by 8
      uint32_t nanoSecs = copy * 62.5 * 8;
      //speed of sound in mm/ns
      uint16_t mm = nanoSecs * 0.000344;
      retval = mm / 2;  // half a round trip
     }
     return retval;
    }

    ISR(TIMER1_CAPT_vect){
     ping.echoHandler();
    }

    ISR(TIMER1_OVF_vect){
     ping.overflowHandler();
    }

    ISR(TIMER1_COMPB_vect){
     ping.overflowHandler();
    }


message:
DHT11 humidity and temperature sensor

**Hello. I've got a question about DHT11 sensor. Why should pullup resistor be connected as on the image below:**
[![enter image description here][1]][1]

**while as far as I know, pullup resistor should be placed between Arduino 5V pin and Vcc of sensor as shown here:**
[![enter image description here][2]][2]

  [1]: https://i.stack.imgur.com/7iDG3.png
  [2]: https://i.stack.imgur.com/RrSgf.png
**PS: I know that there is a wrong icon of DHT11, but I couldn't find a correct one.**

body:
You require a pullup resistor between the data wire and VCC because the DHT11 uses a bidirectional communication system on a single wire.  When neither end is communicating both ends of the link will be in "high impedance" mode - i.e., input mode. In that case the signal will be "floating" and needs the pullup to keep it in a known state.

When actively communicating the outputs switch to "open drain" mode to allow then to pull the signal low against the pull of the pullup resistor.

A resistor in series with the Arduino's 5V and the VCC of the DHT11 is *not* a pullup resistor. It is not an arrangement that you would ever want, since it would make the voltage to the DHT11 unstable.


message:
Pass Byte Array to Char and Send to a Separate Arduino

I am trying to send data between Arduino Nano and D1 Mini (ESP 8266 Module)

*My Code as below in Nano which will be the transmeting ,*

    #include <DES.h>
    #include <SoftwareSerial.h>
    SoftwareSerial link(2, 3); // Rx, Tx
    DES des;
    byte in[8];
    String  input;
    char text[20];
    char charVal[6];

    char buf[30];
    void setup() {
      link.begin(9600);
      Serial.begin(9600);
      Serial.println("Hello! Pleace Enter Your Data to Encrypt");

    }

    void tdesTest() {
      byte out[8];
      byte key[] = {
        0x3b, 0x38, 0x98, 0x37, 0x15, 0x20, 0xf7, 0x5e, // key A
        0x92, 0x2f, 0xb5, 0x10, 0xc7, 0x1f, 0x43, 0x6e, // key B
        0x3b, 0x38, 0x98, 0x37, 0x15, 0x20, 0xf7, 0x5e, // key C (in this case A)
      };

      Serial.println();
      Serial.println("====== Triple-DES test ======");

      //encrypt
      Serial.print("Encrypt...");
      unsigned long time = micros();
      des.tripleEncrypt(out, in, key);
      time = micros() - time;
      Serial.print("done. (");
      Serial.print(time);
      Serial.println(" micros)");
      printArray(out);
      /*
        //decrypt
        for (int i = 0; i < 8; i++)
        {
          in[i] = out[i];
        }
        Serial.print("Decrypt...");
        time = micros();
        des.tripleDecrypt(out, in, key);
        time = micros() - time;
        Serial.print("done. (");
        Serial.print(time);
        Serial.println(" micros)");
        printArray(out);
        delay(2000);
      */
    }

    //printing output
    void printArray(byte output[])
    {
      for (int i = 0; i < 8; i++)
      {
        if (output[i] < 0x10)
        {
          Serial.print("0");
        }
        Serial.print(output[i], HEX);
        Serial.print(" ");
        delay(100);

      }
      Serial.println();

    }

    void loop() {

      while (Serial.available() > 0) {

        String  input = Serial.readString(); // read the incoming data as string
        memset(in, 0, 9); // Erase the contents of in[]
        input.toCharArray((char *)in, 9); // Copy up to 8 bytes from the string
        tdesTest();

      }
    }

In `printArray(byte output[])`I am getting Output as `HEX` Byte as below

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

**I am trying to send the this encrypted data to from Arduino nano to D1 Mini,**

I have wrote a small Receiver  Application in D1 Mini and It works ,
*Receiver Code:*

    //Receiver code
    #include <SoftwareSerial.h>
    SoftwareSerial link(4, 0); // Rx, Tx

    byte greenLED = 13;
    char cString[2000];
    byte chPos = 0;
    byte ch = 0;
    char dataStr[6];

    void setup()
    {
      link.begin(9600); //setup software serial
      Serial.begin(9600);    //setup serial monitor
      pinMode(greenLED, OUTPUT);
    }

    void loop()
    {

      while (link.available())
      {
        ESP.wdtDisable();

        //read incoming char by char:
        ch = link.read();
        cString[chPos] = ch;
        chPos++;

        digitalWrite(greenLED, HIGH); //flash led to show data is arriving
        delay(20);
        digitalWrite(greenLED, LOW);

      }

      cString[chPos] = 0; //terminate cString
      chPos = 0;

      Serial.print(cString);
      ESP.wdtEnable(1);
      Serial.flush();

    }

**I want to pass this HEX data Generated to D1 Mini from Arduino Nano,**

I have wrote test code in Arduino Nano for *Transmitter*(Nano) and between *Receiver* (D1 Mini) it works,

    //Transmitter Code for Testing Connections
    #include <SoftwareSerial.h>
    SoftwareSerial link(2, 3); // Rx, Tx
    byte greenLED = 12;
    char text[20] ;
    char charVal[6];

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

    }

    void loop()
    {
      strcat(text, "Message"); //append to empty string
      Serial.println(text); //print to local screen for debug*
      link.println(text);

      delay(10000);
    }

Please help me to send this **`HEX`** data in single shot to D1 Mini.
[![enter image description here][2]][2]

  [1]: https://i.stack.imgur.com/1lefo.jpg
  [2]: https://i.stack.imgur.com/0YNWU.jpg

body:
You can change your `printArray` function to work on provided `Print` instance:
```
void printArray(byte output[], Print& serial)
{
  for (int i = 0; i < 8; i++)
  {
    if (output[i] < 0x10)
    {
      serial.print("0");
    }
    serial.print(output[i], HEX);
    serial.print(" ");
  }
  serial.println();

}
```

then you can use it as `printArray(out, Serial);` or `printArray(out, link);`.


message:
Artefacts on display when adding seemingly unrelated code

I have this simple program, where I am implementing a menu structure on an OLED display and a rotary encoder.

The code works functionally as intended, however when I add more menu items, then I get some artefacts on the display, in the lower right corner (see screenshots).
The code that I am referring to is inside the block comment in `initMenu()`.
When I uncomment that block, the artefacts start appearing, every other time I turn the knob on the encoder. Sometimes it temporarily disappears, or slightly changes its shape.

[![no artefacts when turning knob][1]][1]
[![artefacts after uncommenting and turning knob][2]][2]

As I said, other than that, the code behaves as expected.
Could anyone maybe shed some light on why this happens?
```
#define DEBUG 1

// Display
#include "Adafruit_GFX.h"
#include "Adafruit_SSD1306.h"
#define OLED_RESET -1
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display;

// Rotary encoder
#include "RotaryEncoder.h"
#include "YetAnotherPcInt.h"
#define RTRY_ENC_SW A1
#define RTRY_ENC_CLK A2
#define RTRY_ENC_DT A3
RotaryEncoder encoder(RTRY_ENC_CLK, RTRY_ENC_DT);
void onSwitch();
void onRotate();

typedef struct MenuItem {
  String name;
  byte id = 0;
  boolean active = false;
  MenuItem* prevSibling;
  MenuItem* nextSibling;
  MenuItem* currentChild;
};

MenuItem autoModes;
MenuItem manualModes;
MenuItem settings;
MenuItem peakAverage;
MenuItem peakToPeak;
MenuItem rms;

MenuItem* currentItem;
MenuItem* activeMode;

void setup() {
#ifdef DEBUG
  Serial.begin(115200);
#endif
  initEncoder();
  initMenu();
  initDisplay();
}

boolean hasInputs = false;
boolean switchPressed = false;

void loop() {
  if (hasInputs == true) {
    hasInputs = false;
    handleButtonInputs();
  }
}

void initEncoder() {
  pinMode(RTRY_ENC_SW, INPUT_PULLUP);
  PcInt::attachInterrupt(RTRY_ENC_SW, onSwitch, FALLING);
  PcInt::attachInterrupt(RTRY_ENC_CLK, onRotate, CHANGE);
  PcInt::attachInterrupt(RTRY_ENC_DT, onRotate, CHANGE);
}

void initMenu() {
  autoModes.name = "Auto";
  autoModes.id = 1;
  autoModes.active = true;
  autoModes.prevSibling = &settings;
  autoModes.nextSibling = &manualModes;
  autoModes.currentChild = &peakAverage;

  manualModes.name = "Manual";
  manualModes.id = 2;
  manualModes.prevSibling = &autoModes;
  manualModes.nextSibling = &settings;

  settings.name = "Config";
  settings.id = 3;
  settings.prevSibling = &manualModes;
  settings.nextSibling = &autoModes;
/*
  peakAverage.name = "PAvg";
  peakAverage.id = 4;
  peakAverage.active = true;
  peakAverage.prevSibling = &rms;
  peakAverage.nextSibling = &peakToPeak;

  peakToPeak.name = "P2P";
  peakToPeak.id = 5;
  peakToPeak.prevSibling = &peakAverage;
  peakToPeak.nextSibling = &rms;

  rms.name = "RMS";
  rms.id = 6;
  rms.prevSibling = &peakToPeak;
  rms.nextSibling = &peakAverage;

  activeMode = &peakAverage;
*/
  currentItem = &autoModes;
}

void initDisplay() {
  display = Adafruit_SSD1306(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  display.setCursor(36, 24);
  display.setTextSize(2);
  display.setTextColor(1);
  display.print("Hello");
  display.display();
}

void handleButtonInputs() {
  if (switchPressed) {
    switchPressed = false;
    if (currentItem->id <= 3) {
      currentItem = currentItem->currentChild;
      printMenu();
    } else if (4 <= currentItem->id && currentItem->id <= 6) {
      if (activeMode->id != currentItem->id) {
        activeMode->active = false;
        currentItem->active = true;
        activeMode = currentItem;
      }
      currentItem = &autoModes;
      printMenu();
    }
  }

  RotaryEncoder::Direction direction = encoder.getDirection();
  if (direction == RotaryEncoder::Direction::CLOCKWISE) {
#ifdef DEBUG
    Serial.println("clockwise");
#endif
    currentItem = currentItem->nextSibling;
    printMenu();
  } else if (direction == RotaryEncoder::Direction::COUNTERCLOCKWISE) {
#ifdef DEBUG
    Serial.println("counterclockwise");
#endif
    currentItem = currentItem->prevSibling;
    printMenu();
  } else if (direction == RotaryEncoder::Direction::NOROTATION ) {
#ifdef DEBUG
    Serial.println("no rotation");
#endif
    // ?
  }
}

void printMenu() {
#ifdef DEBUG
  Serial.println(currentItem->prevSibling->name);
#endif
  display.clearDisplay();
  display.setTextSize(2);
  Serial.println(currentItem->prevSibling->name);
  int x1 = 64 - currentItem->prevSibling->name.length() * 6;
  if (currentItem->prevSibling->active) {
    display.setTextColor(0, 1);
    display.fillRect(x1 - 2, 0, 2, 16, 1);
  } else {
    display.setTextColor(1, 0);
  }
  display.setCursor(x1, 0);
  display.print(currentItem->prevSibling->name);
#ifdef DEBUG
  Serial.println(currentItem->name);
#endif
  int x2 = 64 - currentItem->name.length() * 6;
  int width = currentItem->name.length() * 12 + 10;
  if (currentItem->active) {
    display.setTextColor(0, 1);
    display.fillRect(x2 - 6, 19, width, 24, 1);
  } else {
    display.setTextColor(1, 0);
    display.drawRect(x2 - 6, 19, width, 24, 1);
  }
  display.setCursor(x2, 23);
  display.print(currentItem->name);
#ifdef DEBUG
  Serial.println(currentItem->nextSibling->name);
#endif
  int x3 = 64 - currentItem->nextSibling->name.length() * 6;
  if (currentItem->nextSibling->active) {
    display.setTextColor(0, 1);
    display.fillRect(x3 - 2, 47, 2, 16, 1);
  } else {
    display.setTextColor(1, 0);
  }
  display.setCursor(x3, 47);
  display.print(currentItem->nextSibling->name);
  display.display();
}

void onSwitch() {
  hasInputs = true;
  switchPressed = true;
}

void onRotate() {
  hasInputs = true;
  encoder.tick();
}
```

This is the output of the compilation process regarding program size:
```
Sketch uses 18198 bytes (59%) of program storage space. Maximum is 30720 bytes.
Global variables use 827 bytes (40%) of dynamic memory, leaving 1221 bytes for local variables. Maximum is 2048 bytes.
```

  [1]: https://i.stack.imgur.com/9w2tGb.jpg
  [2]: https://i.stack.imgur.com/0X8Xrb.jpg

body:
Thanks for the comments about memory usage, I was able to solve this specific problem.

I have updated my program, and optimized it by splitting up the menu rendering, using smaller variable sizes where possible, and putting all Strings to PROGMEM using the `F()` macro.
I also had a look at this page https://learn.adafruit.com/memories-of-an-arduino/measuring-free-memory and copied `freeMemory()` from there:

```
#define DEBUG 1
#define DEBUG_MEMORY 1

// Display
#include "Adafruit_GFX.h"
#include "Adafruit_SSD1306.h"
#define OLED_RESET -1
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display;

// Rotary encoder
#include "RotaryEncoder.h"
#include "YetAnotherPcInt.h"
#define RTRY_ENC_SW A1
#define RTRY_ENC_CLK A2
#define RTRY_ENC_DT A3
RotaryEncoder encoder(RTRY_ENC_CLK, RTRY_ENC_DT);
void onSwitch();
void onRotate();

typedef struct MenuItem {
  String name;
  byte id = 0;
  boolean active = false;
  MenuItem* prevSibling;
  MenuItem* nextSibling;
  MenuItem* currentChild;
};

MenuItem autoModes;
MenuItem manualModes;
MenuItem settings;
MenuItem peakAverage;
MenuItem peakToPeak;
MenuItem rms;

MenuItem* currentItem;
MenuItem* activeMode;

#ifdef DEBUG_MEMORY
#ifdef __arm__
// should use uinstd.h to define sbrk but Due causes a conflict
extern "C" char* sbrk(int incr);
#else  // __ARM__
extern char *__brkval;
#endif  // __arm__

int freeMemory() {
  char top;
#ifdef __arm__
  return &top - reinterpret_cast<char*>(sbrk(0));
#elif defined(CORE_TEENSY) || (ARDUINO > 103 && ARDUINO != 151)
  return &top - __brkval;
#else  // __arm__
  return __brkval ? &top - __brkval : &top - __malloc_heap_start;
#endif  // __arm__
}
#endif

void setup() {
#ifdef DEBUG
  Serial.begin(115200);
#endif
  initEncoder();
  initMenu();
  initDisplay();
}

boolean hasInputs = false;
boolean switchPressed = false;

void loop() {
  if (hasInputs == true) {
    hasInputs = false;
    handleButtonInputs();
  }
}

void initEncoder() {
  pinMode(RTRY_ENC_SW, INPUT_PULLUP);
  PcInt::attachInterrupt(RTRY_ENC_SW, onSwitch, FALLING);
  PcInt::attachInterrupt(RTRY_ENC_CLK, onRotate, CHANGE);
  PcInt::attachInterrupt(RTRY_ENC_DT, onRotate, CHANGE);
}

void initMenu() {
  autoModes.name = F("Auto");
  autoModes.id = 1;
  autoModes.active = true;
  autoModes.prevSibling = &settings;
  autoModes.nextSibling = &manualModes;
  autoModes.currentChild = &peakAverage;

  manualModes.name = F("Manual");
  manualModes.id = 2;
  manualModes.prevSibling = &autoModes;
  manualModes.nextSibling = &settings;

  settings.name = F("Config");
  settings.id = 3;
  settings.prevSibling = &manualModes;
  settings.nextSibling = &autoModes;

  peakAverage.name = F("PAvg");
  peakAverage.id = 4;
  peakAverage.active = true;
  peakAverage.prevSibling = &rms;
  peakAverage.nextSibling = &peakToPeak;

  peakToPeak.name = F("P2P");
  peakToPeak.id = 5;
  peakToPeak.prevSibling = &peakAverage;
  peakToPeak.nextSibling = &rms;

  rms.name = F("RMS");
  rms.id = 6;
  rms.prevSibling = &peakToPeak;
  rms.nextSibling = &peakAverage;

  activeMode = &peakAverage;
  currentItem = &autoModes;
}

void initDisplay() {
  display = Adafruit_SSD1306(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  display.setCursor(36, 24);
  display.setTextSize(2);
  display.setTextColor(1);
  display.print(F("Hello"));
  display.display();
}

void handleButtonInputs() {
  if (switchPressed) {
    switchPressed = false;
    if (currentItem->id <= 3) {
      currentItem = currentItem->currentChild;
      renderMenu();
    } else if (4 <= currentItem->id && currentItem->id <= 6) {
      if (activeMode->id != currentItem->id) {
        activeMode->active = false;
        currentItem->active = true;
        activeMode = currentItem;
      }
      currentItem = &autoModes;
      renderMenu();
      #ifdef DEBUG_MEMORY
        Serial.println(freeMemory());
      #endif
    }
  }

  RotaryEncoder::Direction direction = encoder.getDirection();
  if (direction == RotaryEncoder::Direction::CLOCKWISE) {
#ifdef DEBUG
    Serial.println(F("cw"));
#endif
    currentItem = currentItem->nextSibling;
    renderMenu();
  } else if (direction == RotaryEncoder::Direction::COUNTERCLOCKWISE) {
#ifdef DEBUG
    Serial.println(F("ccw"));
#endif
    currentItem = currentItem->prevSibling;
    renderMenu();
  } else if (direction == RotaryEncoder::Direction::NOROTATION ) {
#ifdef DEBUG
    Serial.println(F("nr"));
#endif
    // ?
  }
}

void renderMenu() {
  display.clearDisplay();
  printPrevSibling();
  printCurrentItem();
  printNextSibling();
#ifdef DEBUG_MEMORY
  Serial.println(freeMemory());
#endif
  display.display();
}

void printPrevSibling() {
#ifdef DEBUG
  Serial.println(currentItem->prevSibling->name);
#endif
  display.setTextSize(2);
  Serial.println(currentItem->prevSibling->name);
  byte x1 = 64 - currentItem->prevSibling->name.length() * 6;
  if (currentItem->prevSibling->active) {
    display.setTextColor(0, 1);
    display.fillRect(x1 - 2, 0, 2, 16, 1);
  } else {
    display.setTextColor(1, 0);
  }
  display.setCursor(x1, 0);
  display.print(currentItem->prevSibling->name);
}

void printCurrentItem() {
#ifdef DEBUG
  Serial.println(currentItem->name);
#endif
  byte x2 = 64 - currentItem->name.length() * 6;
  byte width = currentItem->name.length() * 12 + 10;
  if (currentItem->active) {
    display.setTextColor(0, 1);
    display.fillRect(x2 - 6, 19, width, 24, 1);
  } else {
    display.setTextColor(1, 0);
    display.drawRect(x2 - 6, 19, width, 24, 1);
  }
  display.setCursor(x2, 23);
  display.print(currentItem->name);
}

void printNextSibling() {
#ifdef DEBUG
  Serial.println(currentItem->nextSibling->name);
#endif
  byte x3 = 64 - currentItem->nextSibling->name.length() * 6;
  if (currentItem->nextSibling->active) {
    display.setTextColor(0, 1);
    display.fillRect(x3 - 2, 47, 2, 16, 1);
  } else {
    display.setTextColor(1, 0);
  }
  display.setCursor(x3, 47);
  display.print(currentItem->nextSibling->name);
}

void onSwitch() {
  hasInputs = true;
  switchPressed = true;
}

void onRotate() {
  hasInputs = true;
  encoder.tick();
}
```
Now the size is like this:
```
Sketch uses 18588 bytes (60%) of program storage space. Maximum is 30720 bytes.
Global variables use 761 bytes (37%) of dynamic memory, leaving 1287 bytes for local variables. Maximum is 2048 bytes.
```
However the improvement is not that great, and I am still left wondering, when the next problem will arise. I am still thankful for further insights besides using a bigger controller, because I am not quite done yet on this one.

If anyone has more ways for me to improve this program without sacrificing performance, as I will be adding a radio, and a microphone, I will accept that as an answer over this one.


message:
Sending Data Between Arduino Nano and D1 Mini

I am sending data from Arduino Nano to D1 Mini,

*Transmitter is Arduino Nano*

**Transmitter Code:**

    #include <DES.h>
    #include <SoftwareSerial.h>
    SoftwareSerial link(2, 3); // Rx, Tx
    DES des;
    byte in[8];
    String  input;
    char text[20];
    char charVal[6];
    char buf[30];
    void setup() {
      link.begin(9600);
      Serial.begin(9600);
      Serial.println("Hello! Pleace Enter Your Data to Encrypt");
    }
    void tdesTest() {
      byte out[8];
      byte key[] = {
        0x3b, 0x38, 0x98, 0x37, 0x15, 0x20, 0xf7, 0x5e, // key A
        0x92, 0x2f, 0xb5, 0x10, 0xc7, 0x1f, 0x43, 0x6e, // key B
        0x3b, 0x38, 0x98, 0x37, 0x15, 0x20, 0xf7, 0x5e, // key C (in this case A)
      };
      Serial.println();
      Serial.println("====== Triple-DES test ======");
      //encrypt
      Serial.print("Encrypt...");
      unsigned long time = micros();
      des.tripleEncrypt(out, in, key);
      time = micros() - time;
      Serial.print("done. (");
      Serial.print(time);
      Serial.println(" micros)");
      delay(10000);
      printArray(out, link);
      link.write(out, 9);
      delay(2000);
      //decrypt
      for (int i = 0; i < 8; i++)
      {
        in[i] = out[i];
      }
      Serial.print("Decrypt...");
      time = micros();
      des.tripleDecrypt(out, in, key);
      time = micros() - time;
      Serial.print("done. (");
      Serial.print(time);
      Serial.println(" micros)");
      printArray(out);
      delay(2000);
    }
    //passing output and Print
    void printArray(byte output[], Print& serial)
    {
      for (int i = 0; i < 8; i++)
      {
        if (output[i] < 0x10)
        {
          Serial.print("0");
        }
        Serial.print(output[i], HEX);
        Serial.print(" ");
        delay(100);
      }

      Serial.println();
    }
    //printing output without link pass
    void printArray(byte output[])
    {
      for (int i = 0; i < 8; i++)
      {
        if (output[i] < 0x10)
        {
          Serial.print("0");
        }
        Serial.print(output[i], HEX);
        Serial.print(" ");
        delay(100);
      }
      Serial.println();
    }
    void userdata() {
      Serial.println("Sending User Data");
      byte user[] = {0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x30};
      printArray(user, link);
      link.write(user, 9);
      delay(100);
      tdesTest();

    }
    void loop() {
      while (Serial.available() > 0) {
        String  input = Serial.readString(); // read the incoming data as string
        memset(in, 0, 9); // Erase the contents of in[]
        input.toCharArray((char *)in, 9); // Copy up to 8 bytes from the string

        userdata();
      }
    }

And receiving same from *D1 Mini (ESP8266)*

**Receiver Code:**

    //Receiver code
    #include <SoftwareSerial.h>
    SoftwareSerial link(4, 0); // Rx, Tx

    byte greenLED = 13;
    byte cString[8];
    byte chPos;
    byte ch;
    byte out[8];
    String hexstring = "";

    void setup()
    {
      link.begin(9600); //setup software serial
      Serial.begin(9600);    //setup serial monitor
      pinMode(greenLED, OUTPUT);
    }

    void loop()
    {

      while (link.available() > 0)
      {
        ESP.wdtDisable(); // This helps th avoid not reciving data after second try

        //read incoming char by char:
        ch = link.read();
        cString[chPos] = ch;
        chPos++;

        digitalWrite(greenLED, HIGH); //flash led to show data is arriving
        delay(20);
        digitalWrite(greenLED, LOW);

      }
      if (ch != 0)
      {
        printArray(cString);
        ESP.wdtEnable(1);
        Serial.flush();
        cString[chPos] = 0; //terminate cString
        chPos = 0;
      }

    }

    //printing output
    void printArray(byte output[])
    {
      for (int i = 0; i < 8; i++)
      {
        if (output[i] < 0x10)
        {
          Serial.print("0");
        }
        Serial.print(output[i], HEX);
        hexstring += String(output[i], HEX);
        Serial.print(" ");
        delay(100);

      }
      Serial.println();
      Serial.println("Your String Sir:");
      Serial.print(hexstring);
      Serial.println();
      ch = 0; // Avoid printing 0s when no data is recived
      hexstring = ""; //Clear the memeory of hexstring
    }

**In Receiver I am receiving data as below:**

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

I want to get data in Single Stream to receiver *as Example: 31 30 30 30 30 30 30 30 7E B5 2D 4D 93 CB 08 BA* or in receiver join two streams in to a single stream,

**On Side Note:**
1st Part is Plain Data and 2nd Part will be Encrypted Data

Could anyone please help..

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

body:
Managed Get it Working:

Change the Transmitter Code to Cascade Two Char Streams Before Sending:

**Transmitter Code:**

    #include <DES.h>
    #include <SoftwareSerial.h>
    SoftwareSerial link(2, 3); // Rx, Tx
    DES des;
    byte in[8];
    String  input;

    void setup() {
      link.begin(9600);
      Serial.begin(9600);
      Serial.println("Hello! Pleace Enter Your Data to Encrypt");

    }

    //passing output and Print
    void printArray(byte output[], Print& serial)
    {
      for (int i = 0; i < 8; i++)
      {
        if (output[i] < 0x10)
        {
          Serial.print("0");

        }
        Serial.print(output[i], HEX);
        Serial.print(" ");
        delay(100);

      }

      Serial.println();

    }
    //printing output without link pass
    void printArray(byte output[])
    {
      for (int i = 0; i < 8; i++)
      {
        if (output[i] < 0x10)
        {
          Serial.print("0");

        }
        Serial.print(output[i], HEX);
        Serial.print(" ");
        delay(100);

      }
      Serial.println();
    }

    void userdata_and_Encrypt() {
      Serial.println("Sending User Data");
      byte username[] = {0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30};
      printArray(username, link);
      byte username_data = (username, 9);
      delay(100);

      byte out[8];
      byte key[] = {
        0x3b, 0x38, 0x98, 0x37, 0x15, 0x20, 0xf7, 0x5e, // key A
        0x92, 0x2f, 0xb5, 0x10, 0xc7, 0x1f, 0x43, 0x6e, // key B
        0x3b, 0x38, 0x98, 0x37, 0x15, 0x20, 0xf7, 0x5e, // key C (in this case A)
      };

      Serial.println();
      Serial.println("====== Triple-DES test ======");
      //encrypt
      Serial.print("Encrypt...");
      unsigned long time = micros();
      des.tripleEncrypt(out, in, key);
      time = micros() - time;
      Serial.print("done. (");
      Serial.print(time);
      Serial.println(" micros)");
      delay(100);
      printArray(out, link);
      byte password_data = (out, 9);
      delay(100);
      byte data_stream = username_data + password_data;
      printArray(data_stream, link);
      link.write(out, 17);

      //decrypt
      for (int i = 0; i < 8; i++)
      {
        in[i] = out[i];
      }
      Serial.print("Decrypt...");
      time = micros();
      des.tripleDecrypt(out, in, key);
      time = micros() - time;
      Serial.print("done. (");
      Serial.print(time);
      Serial.println(" micros)");
      printArray(out);
      delay(100);

    }

    void loop() {

      while (Serial.available() > 0) {

        String  input = Serial.readString(); // read the incoming data as string
        memset(in, 0, 9); // Erase the contents of in[]
        input.toCharArray((char *)in, 9); // Copy up to 8 bytes from the string

        userdata_and_Encrypt();

      }
    }

Receiver Code to Accept 16 Bytes

**Receiver Code:**

    //Receiver code
    #include <SoftwareSerial.h>
    SoftwareSerial link(4, 0); // Rx, Tx

    byte greenLED = 13;
    byte cString[8];
    byte chPos;
    byte ch;
    byte out[8];
    String hexstring = "";
    static String data = "";

    void setup()
    {
      link.begin(9600); //setup software serial
      Serial.begin(9600);    //setup serial monitor
      pinMode(greenLED, OUTPUT);
    }

    void loop()
    {

      while (link.available() > 0)
      {
        ESP.wdtDisable(); // This helps th avoid not reciving data after second try

        //read incoming char by char:
        ch = link.read();
        cString[chPos] = ch;
        chPos++;

        digitalWrite(greenLED, HIGH); //flash led to show data is arriving
        delay(20);
        digitalWrite(greenLED, LOW);

      }
      if (ch != 0)
      {
        printArray(cString);
        ESP.wdtEnable(1);
        Serial.flush();
        cString[chPos] = 0; //terminate cString
        chPos = 0;
      }

    }

    //printing output
    void printArray(byte output[])
    {
      for (int i = 0; i < 16; i++)
      {
        if (output[i] < 0x10)
        {
          Serial.print("0");
        }
        Serial.print(output[i], HEX);
        hexstring += String(output[i], HEX);
        Serial.print(" ");
        delay(100);

      }
      Serial.println();

      Serial.println("Your String Sir:");
      Serial.println(hexstring);

      Serial.println();
      ch = 0; // Avoid printing 0s when no data is recived
      hexstring = ""; //Clear the memeory of hexstring
    }

**Working Output:**

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

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


message:
How to run a sketch for a period (e.g. 1min) and then attiny85 goes to sleepmode automaticaly?

Another beginner to arduino device.
My knowledge for programming is so weak.
As i mention to the title i would like your help.
I just want to run this simple sketch into attiny85 for lets say 1 min and then chip goes to sleepmode by its own.
My code is below but i cannot manage to achive what i want.
Any help?
Many thanks.

```c++
void setup() {

  pinMode(0, OUTPUT);
  pinMode(1, OUTPUT);
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);

}

void loop() {

                              // put your main code here, to run repeatedly:
  pinMode(0, OUTPUT);
  pinMode(1, OUTPUT);
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);

  digitalWrite(0, HIGH);
  digitalWrite(1, LOW);  // 1
  digitalWrite(2, LOW);
  digitalWrite(3, LOW);
  digitalWrite(4, LOW);
  delay(180);
  digitalWrite(0, LOW);
  digitalWrite(1, HIGH);   // 2
  digitalWrite(2, LOW);
  digitalWrite(3, LOW);
  digitalWrite(4, LOW);
  delay(180);
  digitalWrite(0, LOW);
  digitalWrite(1, LOW);      //3
  digitalWrite(2, HIGH);
  digitalWrite(3, LOW);
  digitalWrite(4, LOW);
  delay(180);
  digitalWrite(0, LOW);
  digitalWrite(1, LOW);   //4
  digitalWrite(2, INPUT);
  digitalWrite(3, HIGH);
  digitalWrite(4, LOW);
  delay(180);
  digitalWrite(0, LOW);
  digitalWrite(1, LOW);   //5
  digitalWrite(2, LOW);
  digitalWrite(3, LOW);
  digitalWrite(4, HIGH);
  delay(180);
  digitalWrite(0, LOW);
  digitalWrite(1, LOW);   //4
  digitalWrite(2, INPUT);
  digitalWrite(3, HIGH);
  digitalWrite(4, LOW);
  delay(180);
  digitalWrite(0, LOW);
  digitalWrite(1, LOW);     //3
  digitalWrite(2, HIGH);
  digitalWrite(3, LOW);
  digitalWrite(4, LOW);
  delay(180);
  digitalWrite(0, LOW);
  digitalWrite(1, HIGH);   // 2
  digitalWrite(2, LOW);
  digitalWrite(3, LOW);
  digitalWrite(4, LOW);
  delay(180);
  digitalWrite(0, HIGH);
  digitalWrite(1, LOW);  // 1
  digitalWrite(2, LOW);
  digitalWrite(3, LOW);
  digitalWrite(4, LOW);

}
```

body:
You can write, at the end of `loop()`, “if one minute has elapsed, then
go to sleep”. In C++, that would be:

```c++
if (millis() >= 60000)  // 60 seconds elapsed
    sleep_mode();
```

You will need to include `<avr/sleep.h>` in order to have access to the
`sleep_mode()` function. The sleep is likely to be very short though,
probably less than a millisecond, as the ATtiny will be waken up by the
next timer interrupt.

If you want a deeper, longer sleep, you could choose a different sleep
mode in `setup()`:

```c++
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
```

Read the datasheet if you want to know what wakeup sources are available
in each sleep mode.

Alternatively, if you want to make the ATtiny sleep forever (until the
next power cycle), call `cli()` in order to disable the interrupts,
right before calling `sleep_mode()`.


message:
Arduino 5v pin outputting lower power than expected

I have hooked the pin v5 of an Arduino Nano 33 BLE to the A0 pin and measured the value by doing `Serial.println(analogRead(A0));`. I would expect to see 1023 however instead I see the value oscillating around 810.

Any ideas why I am not getting 1023?

P.S.: I am powering the Arduino board through the USB connector.

body:
Well, I thought by now someone else would have answered it.  But, I'll try.  I'm not familiar with this chip and board, so what I can tell you is pretty limited.

In short, you have a 3.3V micro-controller and generally speaking you don't hook 5V signals to them.  There are some 3.3V parts that have "5V tolerant" inputs, but that only makes sense for digital inputs so far as I know.

Barring anything unpleasant happening, the behaviour I would expect to see with hooking 5V to the input of a 3.3V ADC is that it would clip at the high end value.  So yeah, for 10-bit resolution, which [appears to be the default][1] for the Nano 33 BLE and with VDD as the reference, which also [appears to be the default][2], I would expect to see a value at or near 1023.  Up until the point that you fry something that is.

I don't know why you're seeing lower values, but since you seem to be operating it out of specifications, I'm not sure that really matters why.  If you want to measure 5V with your 3.3V max ADC, you should involve a voltage divider.

  [1]: https://www.arduino.cc/reference/en/language/functions/zero-due-mkr-family/analogreadresolution/
  [2]: https://www.arduino.cc/reference/en/language/functions/analog-io/analogreference/


message:
How to difference hardware reset and software reset?

I have an arduino code with an SD card where I save some data. When I load a new code, The SD must update with the new data that I put in the code, but if I reset the Arduino by the reset button, I don´t want the SD data to change.

To sum up, I want to reload SD data only when I update the code, and not with hardware reset

Any ideas?

body:
You can't. There is no "software" reset. When you upload new code a hardware reset is triggered by the DTR pin of the USB interface chip.

Instead I would suggest maintaining a "data version number" on the SD card. Read it on startup and, if it differs from the expected version number (which you update in your code manually) it creates the data for you and sets the version number.


message:
how to display text to 8x8 matrix with 64-bit long integers?

I have an array of 64-bit integers to display on an 8x8 led matrix
```
const int LEN1 = sizeof(Hours);
const uint64_t Hours[] = {
  0x00043c3c3c3c3c00,
  0x000c3c3c3c3c3c00,
  0x001c3c3c3c3c3c00,
  0x0000001818000000,
  0x0000001818100000,
  0x0000001818180000,
  0x00000018181c0000,
  0x000000181c1c0000,
  0x0000001c1c1c0000,
  0x0000041c1c1c0000,
  0x00000c1c1c1c0000
};

```
and here I have a loop to display it:
```
void displayImage(uint64_t image) {
  for (int i = 0; i < 8; i++) {
    byte row = (image >> i * 8) & 0xFF;
    for (int j = 0; j < 8; j++) {
      lc.setLed(0, i, j, bitRead(row, j));
    }
  }
}
```
but I can't use a loop in this way and I'm not proficient in byte shifting principles too.

can you please explain how the loop above works or help me to write this loop as
```
const int LEN1 = sizeof(Hours);

void displayImage(Hours[]) {
  for (int i = 0; i < LEN1; i++) {
    //display Hours
    }
}
```

body:
ok, well there are some things I don't know about your code, and hardware, like if the LCD library can handle uint64_t datatypes. I know the Serial.print() function can only handle up to a unit32_t, so I'm using that.

I think your length variable might not be the right length, you might want to add in a check for that in your code. Much of the Arduino code is 8 bit.

    void setup() {
    Serial.begin(9600);
    uint32_t b = 0x0;

    const uint64_t Hours[] = {
      0x00043c3c3c3c3c00,
      0x000c3c3c3c3c3c00,
      0x001c3c3c3c3c3c00,
      0x0000001818000000,
      0x0000001818100000,
      0x0000001818180000,
      0x00000018181c0000,
      0x000000181c1c0000,
      0x0000001c1c1c0000,
      0x0000041c1c1c0000,
      0x00000c1c1c1c0000
    };

    //const int LEN1 = sizeof(Hours[0]);
    const int LEN1 = sizeof(Hours)/sizeof(uint64_t);
           Serial.print("Length: ");
           Serial.println(LEN1);

       for (int i = 0; i < LEN1; i++) {
           b=Hours[i]>>16;
           Serial.println(b,HEX);
           }
    }

    void loop() {
    }

I think this code will do what you want, at least as I understand it.
beware of what data-types your LCD library can handle.


message:
Listening Serial Ports

guys. I need your help. I have 6 Serial Channels and I need to listen this channel and be sure which channel is working? How can I do that? Can I listen this channel by using digital inputs? Or Do I have to use a devices which has a 6 Serial ports? Like 2 Arduino Mega?

body:
For your needs you don't need actual UARTs. You can do it all with normal GPIO pins and one (or more) interrupts.

UART communication is characterised by having a "start bit" at the beginning of all bytes. That is, in TTL terms, a transition from HIGH to LOW. You just need to look out for that transition.

You could:

* Use Pin Change interrupts on 6 pins to monitor for any FALLING transistion, or
* Use one interrupt pin with a *wired OR* of all the signals along with individual pins for each signal to determine which triggered the interrupt.

To determine "is it active" you just need to know that an interrupt has occurred and which pin triggered it, and has that been seen within a certain time period (to be decided by you).


message:
Arduino NANO clone not detected by computer

I recently purchased 5 Arduino Nano clones and on my Windows PC they were all working fine.
I then gave one to a friend and after installing the CH34OC driver on his Mac he was able to program a simple Morse code blink program that worked fine on the device. However, after uploading it the COM port was no longer showing and his Mac could no longer detect the device.

We verified that the problem was not with the Serial cable and not with the USB port and other the Arduino clones worked perfectly also. So it must be an issue with the device which when connected the RX and TX lights would stay on and the inbuilt LED would display the Morse code as was programmed. The device would then no longer even be registered by my computer as no noise was made when plugging it in and nothing showed up in device manager as if I simply pugged in a USB cable with nothing attached.

I then used my Arduino UNO to run the Arduino ISP program and then burn the bootloader onto my NANO. This was successful and the a new blink program was loaded and the TX light no longer shows when connected to my computer but it is still entirely undetected as if nothing was plugged in.

I have tries many things including but not limited to:

Holding the reset button when plugging it in

Reinstalling the driver as administrator

Switching out the cable

Changing the USB port

Using the old bootloader

Reinstalling the Arduino IDE

Restarting my computer.

Sadly nothing is working and I am out of ideas. Does anyone have any suggestions for a fix or know how I can diagnose the issue further. For example checking to see if the USB chip on the Arduino is operational or maybe the diode was faulty? Methods for testing these things would be greatly appreciated.

body:
It sounds rather like a fault with the Nano's CH340 chip, the one used to communicate over USB between the Nano and a PC. The Atmega 328p seems to be working, as you say the previously loaded Morse Code program still runs. I expect you can still program the Atmega entirely through its ISP.

If the CH340 has been physically damaged, you can still program the Atmega processor via the ISP but you will no longer have USB capability on-board. You could use a CH340- or FTDI-cable (USB <-> TTL serial) connected to Arduino-pins 0 and 1 to provide off-board USB communication if you want to continue using the Nano as usual.

Update:

> Is there any way that I can verify that the CH340 chip has indeed been
> damaged as if it is something smaller like a diode I may attempt to
> repair it.

I don't know of a way unless a visual inspection shows a bad component. Not that there might not be one, just that that level of board repair is beyond my expertise. And assuming you didn't ever see or smell smoke, I wouldn't expect the defect to be visible. No harm in going over it with a strong magnifier, though....


message:
Guru Meditation Error: Core 1 panic'ed (Interrupt wdt timeout on CPU1)

Heres my code:

```
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>

const char* ssid = "wifiSSID";
const char* password =  "wifiPassword";

int sleepTime = 0;
HTTPClient http;

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

  Serial.println("START WIFI");
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
      delay(500);
      Serial.print(".");
  }

  http.begin("http://ip-address:3000/start?appid=1+6vIswDqSmXONCjq4rLtTMd9O2CHEQ4Oe");
  int httpCode = http.GET();
  String payload = http.getString();

  StaticJsonDocument<256> doc;
  deserializeJson(doc, payload);
  sleepTime = doc["sleep"];

  if (sleepTime > 0) {
    Serial.println("Sleeping for: " + sleepTime);
    delay(sleepTime);
    sleepTime = 0;
  }
}

void loop() {
  // Sensor stuff
}
```

Heres the error:

```
START WIFI
.........Guru Meditation Error: Core  1 panic'ed (Interrupt wdt timeout on CPU1)
Core 1 register dump:
PC      : 0x4000c271  PS      : 0x00060034  A0      : 0x8008a48c  A1      : 0x3ffb1c60
A2      : 0x3ffb0058  A3      : 0x3f41ae58  A4      : 0x00000014  A5      : 0x3ffbfea0
A6      : 0x3ffbfee8  A7      : 0x00000001  A8      : 0x00000001  A9      : 0x3f41ae59
A10     : 0x000000a5  A11     : 0x30303030  A12     : 0x8008b043  A13     : 0x3ffbfe70
A14     : 0x00000008  A15     : 0x00000001  SAR     : 0x00000012  EXCCAUSE: 0x00000006
EXCVADDR: 0x00000000  LBEG    : 0x400014fd  LEND    : 0x4000150d  LCOUNT  : 0xfffffffa

ELF file SHA256: 0000000000000000

Backtrace: 0x4000c271:0x3ffb1c60 0x4008a489:0x3ffb1c80 0x4008c034:0x3ffb1ca0 0x4008bfea:0x3ffb1cc0 0x400d5e5c:0x3f725c88

Core 0 register dump:
PC      : 0x40165582  PS      : 0x00060634  A0      : 0x8015196e  A1      : 0x3ffbc120
A2      : 0x00000000  A3      : 0x00000001  A4      : 0x80084032  A5      : 0x3ffbf870
A6      : 0x00060d20  A7      : 0x00000000  A8      : 0x801503f6  A9      : 0x3ffbc0f0
A10     : 0x00000000  A11     : 0x00000001  A12     : 0x80084032  A13     : 0x3ffbf870
A14     : 0x00000000  A15     : 0x3ffbc218  SAR     : 0x00000000  EXCCAUSE: 0x00000006
EXCVADDR: 0x00000000  LBEG    : 0x00000000  LEND    : 0x00000000  LCOUNT  : 0x00000000

ELF file SHA256: 0000000000000000

Backtrace: 0x40165582:0x3ffbc120 0x4015196b:0x3ffbc140 0x4008b031:0x3ffbc160 0x40089882:0x3ffbc180

Rebooting...
ets Jun  8 2016 00:22:57

rst:0xc (SW_CPU_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1216
ho 0 tail 12 room 4
load:0x40078000,len:10944
load:0x40080400,len:6388
entry 0x400806b4
```

What should I do?

body:
I suppose your are using Arduino IDE (maybe 1.x.x), if so, you should install the exception decoder so your can read such hex codes. They will give an more useful hint about the error location.

Here the link:
https://github.com/me-no-dev/EspExceptionDecoder


body:
I got this problem too with the latest IDF version..
check the IDF version as it seems the problem with RTOS handling both cores together.

The solution was for me to downgrade the IDF version to 3.0.0


message:
MPU6050 Calibrating Accelerometer

I recently got an MPU6050 and I noticed the accelerometer data was a bit off, especially on the Z axis.

I'm running it on a Teensy 4.0 with Adafruit's MPU6050 library and basic example code: https://github.com/adafruit/Adafruit_MPU6050/blob/master/examples/basic_readings/basic_readings.ino

While stable on a flat surface (+Z up), it's reading ~8.5 m/s^2 and when flipped over (-Z up), ~11.6 m/s^2:

```
+Z:
Acceleration X: -0.06, Y: 0.00, Z: 8.44 m/s^2
-Z:
Acceleration X: -0.01, Y: -0.07, Z: -11.57 m/s^2
```
Aligning the other axes vertically gives me:
```
+X:
Acceleration X: 10.16, Y: -0.16, Z: -0.03 m/s^2
-X:
Acceleration X: -9.27, Y: -0.10, Z: -0.18 m/s^2
+Y:
Acceleration X: 0.07, Y: 9.55, Z: -0.10 m/s^2
-Y:
Acceleration X: 0.04, Y: -9.93, Z: -0.05 m/s^2
```
The X and Y readings could be adjusted fairly close to 9.81 m/s^2 with just an offset, but it seems like the Z axis would also require some scaling.

My question, is there a standard method of calibrating it in code?

body: Yes an accelerometer can be calibrated.  An offset for each of the 3 accelerometers can be found such that the absolute value of the maximum and minimum values of any given accelerometer axis are equal.  The maximum and minimum values can be found by rotating the accelerometer such that each axes is pointed directly toward and directly away from the earth.  Once each axes is normalized each axes needs a magnitude adjustment value such that the maximum value of all axes equal one another.  It may be convenient the product of the maximum of any given axes and that axes' magnitude adjustment value is 9.8 (meters per second * second).


message:
ESP32 WROOM32 SPI EMF issues

I'm trying to run Waveshare SSD1327 128x128 screen via SPI on ESP32 WROOM32 board. On ESP8266 (D1R1?) it works flawlessly while using HW SPI but when I run it on esp32, anything connected to mains which is sitting <50cm from screen will glitch it out completely. Even if I just hold in one hand phone charger cable connected to mains, and come close to screen with my other hand(at least 1m distance between hands), screen will instantly glitch and shut down.
I'm pretty sure this is not connection issue, since it works on ESP8266 and I even tried soldering wires directly to ESP32 board.

I am using VS Code PlatformIO and Arduino framework. I tried setting CPU freq to 40MHz by adding line to platformio.ini and calling setCpuFrequencyMhz(40); in my setup() function. I don't have oscilloscope to confirm that this actually happend. I read somewhere that this .ini thing didn't work.

I am using U8g2lib for screen which is using global SPI object. Even tho I bought screen from Waveshare I can't use WS implementation. MIDAS one is the only implementation which works for me.  Since my board doesn't have all VSPI pins, I had to set them manually in SPI.begin(...):

    U8G2_SSD1327_MIDAS_128X128_F_4W_HW_SPI display(U8G2_R0, /* cs=*/ 39, /* dc=*/ 16, /* reset=*/ 2);
    ...
    ...
    pinMode(39, OUTPUT);
    pinMode(14, OUTPUT);
    pinMode(13, OUTPUT);
    pinMode(12, INPUT);

    digitalWrite(39, LOW);
    // sck, miso, mosi, ss
    SPI.begin(14, 12, 13, 39);
    display.begin();

 [![This is ESP32 board I'm using][1]][1]

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

BTW, SW SPI worked extremely slow for me(display.sendBuffer() takes about 1sec), on both ESP32 WROOM32 and ESP8266 D1R1 mini. Friend of mine is using ESP32 WROOVER board and even SW SPI is working for him great without any glitching.

body:
Problem was GPIO39 which is internally connected to a hall sensor... Once I changed CS to some other pin, everything started working...

Having pin cheatsheet would be really helpful in these situations.


message:
Can you use multiple arduinos to run two programs simultaneously?

If I want to run 2 different programs simultaneously, can I do this with 2 arduinos wired together?

Context: I’m building a robot that will balance with reaction wheels while doing other tasks. I would like to have the balancing program running continuously in the background while the servos that control the robot are moving. Can I accomplish this by having a 2nd arduino running the balancing while the 1st arduino controls the rest of the robot?

body: The answer is yes, you can run two programs one in each Arduino. There are no restrictions on doing this. There are probably millions of Arduinos currently operating without any interaction with each other. In your robot they would need some sort of communications between them. This is if there is to be any type of interaction between them. I do not know your skill set but it may be  possibly do it with one with some tight code.


message:
Unable to get readings for "Motor with Encoder"

I've posted to the [DFRobot forum][1], who makes the FIT0186 motors, but no one seems to be replying there.  So, excuse the copy pasting.  It's probably an issue with the motor/encoder, but perhaps it has to do with the arduino.  I'm using a Nano, and a TB6612 based motor driver from DFRobot.

I'm trying to get the built-in encoder working for the FIT0186.

The example wiki code doesn't work, and I've modified it as far as I can using sensible changes.
I'm plugging both Hall Sensor A and B outputs to the interrupts.

Currently, when I plug in the 12V, it triggers an interrupt, but then other than that initial pulse, no interrupts are triggerred.

The motor is moving as expected. Attaching my code. Has anyone got the encoder working?

    const byte encoder0pinA = 2;
    const byte encoder0pinB = 3;
    volatile int posA;
    volatile int posB;

    int DIR1 = 8;
    int PWM1 = 9;

    void setup()
    {
      Serial.begin(115200);
      pinMode(DIR1, OUTPUT);
      pinMode(PWM1, OUTPUT);
      pinMode(encoder0pinA,INPUT);
      pinMode(encoder0pinB,INPUT);
      attachInterrupt(digitalPinToInterrupt(encoder0pinA), encoderA, RISING);
      attachInterrupt(digitalPinToInterrupt(encoder0pinB), encoderB, RISING);

    }

    void loop()
    {
      Serial.print("Pulse:");
      Serial.println(posA);
      Serial.println(posB);

      noInterrupts();
      posA = 0;
      posB = 0;
      interrupts();

      delay(100);

      int value;
      digitalWrite(DIR1, HIGH);

      for(value = 0 ; value <= 255; value += 5)
      {
        analogWrite(PWM1, value);   //PWM Speed Control
        delay(20);
      }

      Serial.print("Pulse:");
      Serial.println(posA);
      Serial.println(posB);

      delay(100);

      for(value = 255 ; value >= 0; value -= 5)
      {
        analogWrite(PWM1, value);   //PWM Speed Control
        delay(20);
      }

      Serial.print("Pulse:");
      Serial.println(posA);
      Serial.println(posB);
      delay(100);

      digitalWrite(DIR1, LOW);
      for(value = 0 ; value <= 255; value += 5)
      {
        analogWrite(PWM1, value);   //PWM Speed Control
        delay(20);
      }

      Serial.print("Pulse:");
      Serial.println(posA);
      Serial.println(posB);

      delay(100);
      for(value = 255 ; value >= 0; value -= 5)
      {
        analogWrite(PWM1, value);   //PWM Speed Control
        delay(20);
      }

    }

    void encoderA()
    {
        posA++;
    }

    void encoderB()
    {
        posB++;
    }

  [1]: https://www.dfrobot.com/forum/viewtopic.php?f=8&t=27866

body: From what you have indicated (being wired correctly) there is a high probability you have a bad connection. It could be one of many things such as a loose wire, broken wire, problem with the module, etc... Swp A & B and see what happens.


message:
Arduino randomly stops sending data to python over serial

I want to send commands to Arduino over USB Serial from my python program and Arduino should send back received command to make sure data wasn't lost. However Arduino randomly stops sending data back. For debugging purposes I made builtin LED blink in the loop function. When Arduino stops sending data the LED slows down blinking (about 2-3 times).
I tried this on Arduino Uno and Arduino Nano to make sure it is not damaged board.

Here is my Python code responsible for communication:
```python

class Communication(ABC):
    def __init__(self) -> None:
        self.history: list = []
        self.response_history: list = []
        self.last_responses: dict = dict()
        self.queue: collections.deque[str] = collections.deque()
        self.is_sending: bool = False
        self.command_recived_condition: threading.Condition = threading.Condition()

    def append_commands(self, commands: str) -> None:
        commands = map(lambda x: "c"+x, map(lambda x: x+";", filter(len, commands.split(";"))))
        for command in commands:
            self.queue.append(command)

    def append_and_send(self, commands: str) -> None:
        self.append_commands(commands)
        if not self.is_sending:
            self.sender: threading.Thread = threading.Thread(target=Communication.send_commands, args=(self, ))
            self.sender.start()

    @abstractmethod
    def send_command(self, command: str) -> bool:
        """ Sends command to the controller, waits for the response and tries again if command was not recived succesfully """
        pass

    @abstractmethod
    def listen(self) -> None:
        pass

    @abstractmethod
    def check_for_response(self, command: str) -> None:
        pass

    def send_commands(self):
        self.is_sending = True
        commands = self.queue
        while len(commands) > 0:
            command = commands.popleft()
            self.send_command(command)

        self.is_sending = False

class Serial_comunication(Communication):
    def __init__(self, port: str) -> None:
        super().__init__()
        self.serialcom = serial.Serial(port, 4800)

        self.listen()

        time.sleep(0.1)
        self.send_command("PING;")
        time.sleep(0.1)

    def listen(self) -> None:
        def listen_util() -> None:
            chars = []

            while True:
                if self.serialcom.inWaiting() > 0:
                    time.sleep(0.01)
                    try:
                        char: str = self.serialcom.read().decode()
                    except UnicodeDecodeError:
                        print("decoding err")
                        continue
                    print(char, end=" ")

                    if char[-1] == '#':
                        response_str = "".join(chars)
                        category, content = response_str.split("::")
                        self.last_responses[category] = content
                        self.response_history.append(response_str)
                        chars.clear()
                        print("\n", response_str)
                        if category == 'Info: recived':
                            with self.command_recived_condition:
                                self.command_recived_condition.notify()
                    else:
                        chars.append(char)

                time.sleep(0.01)

        self.listener = threading.Thread(target=listen_util)
        self.listener.start()

    def check_for_response(self, command: str) -> None:
        print("check")

        if self.last_responses.get('Info: recived') == command:
            print('possitive')
            return True

        return False

    def send_command(self, command: str) -> None:

        while True:
            time.sleep(0.1)
            self.serialcom.write(command.encode())
            print("sent", command)

            with self.command_recived_condition:
                self.command_recived_condition.wait()
                print("waited")

            if self.check_for_response(command.strip().strip(';')):
                break
```

And my Arduino Code responsible for communication:
```cpp
#define INPUT_SIZE 50
char input[INPUT_SIZE + 1];

bool check_for_orders(Order& cmd, char *val, uint8_t& place)
{
    if (Serial.available() > 0)
    {
        // Read input from Serial until ; what means command has ended
        size_t size = Serial.readBytesUntil(';', input, INPUT_SIZE);
        input[size] = 0; // Add null terminator

        Serial.print(F("Info: recived::"));
        delay(10);
        Serial.print(input);
        Serial.print(F("#"));
        Serial.flush();

        // Check if command is not empty
        if (input[0] != 0)
        {
            // syntax is "order:pattern_place:value"
            cmd = static_cast<Order>(atoi(strtok(((char*)input)+1, ":"))); // Get order numer and convert to enum
            place = atoi(strtok(NULL, ":")); // Get place number from input (only 0 or 1 is allowed)
            char *value = strtok(NULL, ":"); // Get value from second part of string

            if (value == 0) // If value is empty then syntax is invalid
            {
                return false;
            }

            // Otherwise copy order name and value to c-strings from main function
            strcpy(val, value);
            free(value);

            return true;
        }
        else // Probably never gonna happen
        {
            return false;
        }
    }
    return false;
}
```

The check_for_orders function is run every time loop function is run.

Here is what python printed when I sent the following commands ["PING;", "c0:0:0;", "c0:1:0; c15:0:100,600,20,2,0,200,255,170,255,200;"]

```
sent PING;
I n f o :   r e c i v e d : : P I N G #
 Info: recived::PING
waited
check
possitive
sent c0:0:0;
I n f o :   r e c i v e d : : c 0 : 0 : 0 #
 Info: recived::c0:0:0
waited
check
possitive
sent c0:1:0;
I n f o :   r e c i v e d : : c 0 : 1 : 0 #
 Info: recived::c0:1:0
waited
check
possitive
sent c15:0:100,600,20,2,0,200,255,170,255,200;
I n f o :   r e c i v e d : : c 1 5 : 0 : 1 0 0 , 6 0 0 , 2 0 , 2 , 0 , 2 0 0 , 2 5 5 , 1 7 0 , 2 5 5 , 2 0 0 #
 Info: recived::c15:0:100,600,20,2,0,200,255,170,255,200
waited
check
possitive
sent c1:0:1;
/* and it got stuck */
```
Do someone know why something here is getting stuck and/or how to solve this problem?

body:
I removed ```free(value)``` - rookie mistake - but that didn't completely solved the problem (but reduced frequency of occurrences).
Seems like declaring array like ```char val[50]``` and passing it to function as ```char* val``` was a bad idea. I changed array declaration to ```char *val = new char[50]``` and now seems like everything works fine.


message:
opencv reading the display and doesnot provide serial communication with arduino

I was creating a project where the following part of the code reads certain area of the display(which i screen shared from mobile)

    import cv2 as cv
    import numpy as np
    from PIL import ImageGrab
    import serial
    arduinodata = serial.Serial('com5',9600)

    def led_on():
        arduinodata.write(b'1')

    def led_off():
        arduinodata.write(b'0')
    i=1

    while True:
        screen = np.array(ImageGrab.grab(bbox=(0,0,1920,1080)))
        #define the screen resulation
        screen_res = 1920, 1080
        scale_width = screen_res[0] / screen.shape[1]
        scale_height = screen_res[1] / screen.shape[0]
        scale = min(scale_width, scale_height)
        #resized window width and height
        window_width = int(screen.shape[1] * scale)
        window_height = int(screen.shape[0] * scale)
        #cv.namedWindow('Resized Window', cv.WINDOW_NORMAL)
        cv.resizeWindow('Resized Window', window_width, window_height)
        resized = screen.resize()
        health_bar = screen[262:268, 142:365]

        health_grayed = cv.cvtColor(health_bar, cv.COLOR_BGR2GRAY)
        count1 = cv.countNonZero(health_grayed)

    if i==1:
        e =count1
        i=0

    if e>count1:
        led_on()
        e=count1

    if e<count1:

        e=count1

   and whenever the value of the count1 variable decreases i want the Arduino led should be turned on

this was the arduino code

    char serialData;

    void setup() {
      // put your setup code here, to run once:
      pinMode(13,OUTPUT);
      digitalWrite(13,LOW);
      Serial.begin(9600);

    }

    void loop()
      // put your main code here, to run repeatedly:
    {
      if(Serial.available() >0)
      {
        digitalWrite(13,HIGH);
        delay(1000);
        digitalWrite(13,LOW);

       }

    }

But the led is turning on but does not turns off . I don't know why

can anyone please help me

body:
This happens because you are not reading from `Serial`.

When you send data to the Arduino, it gets placed in the `Serial` buffer. `Serial.available()` then returns the number of bytes in the buffer. The bytes are removed from the buffer by `Serial.read()`ing them, which you don't do. Since you don't remove any bytes from the buffer, `Serial.available()` will always return a number greater than zero from the moment on, that the first byte arrives. After the delay you turn the LED off via `digitalWrite(13,LOW);`, but in the next loop iteration the if statement is again executed (as described above). This happens so fast, that you think the LED just stays on. In reality it gets turned of for maybe a few microseconds and then turned on again.

You are sending a single byte for the LED to react. So it would be the simplest solution to just read a single byte from the buffer inside of the if statement. The result can be discarded.

    void loop()
    {
      if(Serial.available() >0)
      {
        digitalWrite(13,HIGH);
        delay(1000);
        digitalWrite(13,LOW);
        Serial.read();
       }
    }

The `Serial.read()` removes one byte from the buffer and returns it (so it gets discarded here). This way the LED blinks for every byte, that the Arduino receives over `Serial`.

---

Note: Depending on how fast you are sending the data you might want to make more clear, that you have individual bytes. With the above code the LED will light up for 3 seconds straight if you send 3 bytes in (relatively) fast succession (meaning consecutive bytes less than a second apart). To make it more clear, that you have 3 individual bytes, you can add a `delay()` call after turning the LED off. That gives you the chance to actually see it turning off.


message:
What is required to run a program preciously uploaded and working from Arduino IDE via PC... (Nano 33 IoT)... but now powered via VIN, not USB?

The Arduino IDE works beautifully with the Nano 33 IoT using the IDE and is powered via USB. I now want to disconnect the USB and power thru the VIN pin (6-22V). The green led comes on but the program is not there or not running. Please help.  thank you!

body:
Once you upload your code into the Arduino, it is there, burned into the flash memory of the microcontroller and it runs no matter how you power your board.

However, if in order to run your program is dependent on the Serial interface, for instance you added a line like `while(!Serial)` and you have not connected the USB cable, the program will loop at that point and will not continue.

For more information please upload your code.


message:
External Power for MicroServo (SG92R)

Why won't my MicroServo run at external 5v power supply? , I've tested my power supply and can light up 1 LED and also run the servo mainly on arduino and it works just fine. Im currently using a computer power supply using the red wire(5v). I'm not very knowledgeable with voltage and stuff and im hoping someone can answer.
[![enter image description here][1]][1]

and here is my power supply...
[![enter image description here][2]][2]

I've checked the power supply terminals but nothing is wrong there. Also, i've tried 10k potentiometer to be supplied by it but when i read it in ***serial.begin*** it just reads **"0, 0, 0, 0, 1023, 1023, 1023, 1023"** over and over again. Sorry about the formats im still new.

  [1]: https://i.stack.imgur.com/4ccRD.jpg
  [2]: https://i.stack.imgur.com/z8Mmo.jpg

body:
The image you uploaded shown quite clearly that you have not connected the grounds between the Arduino circuit and the servo circuit. In order for it to work, the servo should reference the signal line to ground, currently only PC power supply is providing ground, so the Arduino signal line is floating.

Check out the attached image and connect the GND as shown in dotted yellow line.

[![Connect grounds][1]][1]

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


message:
Atmel SAMD21 microcontroller not making a USB port anymore

My custom board with Atmel SAMD21 microcontroller (same as Arduino MKR Zero) is not making a USB port since yesterday. The board was working fine before that.

Please suggest ways to resolve this issue. What are the possible reasons for such an issue?

Since reset is equivalent to powering the board ON and OFF which has not resolved the issue, can burning the bootloader again help?

Further information:

 1. The board seems fine. It powers ON and OFF in the usual manner.
 2. This problem with the USB port connection happened while I was trying to upload the code.

The USB pin connections on the board have been checked as well as tested with different USB wires.

Appreciate your help.

body:
**Solutions to the problem:**

 1. External Hardware Reset -- using a reset button (that I externally managed to solder using the Reset pin-out) -- to get into bootloader mode and start the program from the beginning

Thanks Majenko, from the comments.

2. Burning bootloader again may also work (theoretically) - I have not tried and tested it.

For detailed understanding - follow this post - https://forum.arduino.cc/t/atmel-samd21-microcontroller-not-making-a-usb-port-anymore/882504/5


body:
>**What are the possible reasons for such an issue?**

I noticed that calling

````
Serial.begin(115200);
...
SerialUSB.begin(115200);
````

in the script can cause this.

See post https://arduino.stackexchange.com/questions/85530/seeeduino-xiao-stopped-connecting-enter-bootloader-mode-is-not-working


message:
run a function for a certain amount of time!

i'm working on a project where i need to run a function for 20 minutes and the function writes to memory using EEPROM every minute. How can i make the function run for 20 minutes, i was thinking of using millis to measure the time between starting time and current but i'm afraid that when the millis rolls over and the the difference in time becomes negative my program will break and my function will run forever . Is there any way to make a function run for a certain amount of time, or will millis handle the rollover if we use unsigned variables for all variables for millis();

body:
See [this answer](https://arduino.stackexchange.com/a/29842/10794) for an explanation. Using unsigned variables, and *subtracting* will definitely work.

Not only will unsigned variables not become negative (by their very nature) but the rollover will be handled smoothly and accurately.


body: Another way to solve this problem is using cronAlarm. It can provide precise control on timings and you can schedule your job also. https://www.arduino.cc/reference/en/libraries/cronalarms/


message:
Dropping a 75V power supply to power an Arduino Mega

I'm looking to power an Arduino Mega using [this IPC-5 power supply](https://www.teknic.com/IPC-5/) from Teknic since I will have a free port (the other powers a servo). I would like to use this extra port to power my Arduino rather than draw power from another source. The problem is that this is 75V coming out which would eat up the Arduino.

Is it as simple as hooking up a resistor in series with the Arduino to bring the voltage down to about 7V for the Arduino? If that's the case, then how can I determine the unknowns to find the appropriate resistor?

Correct me if I'm wrong, but if I apply Ohm's Law and Kirchhoff's Rules, I can set up this relationship: 75V = IR + 7V. Can I make an assumption for the current to solve for the resistance?

This is my first real Arduino project, so my knowledge of many things that y'all may consider common knowledge is lacking.

body:
> Is it as simple as hooking up a resistor in series with the Arduino to bring the voltage down to about 7V for the Arduino?

No, it certainly is not.

> Can I make an assumption for the current to solve for the resistance?

No, you cannot. You *never* assume anything in electronics without a very very good reason.

You require a suitably rated voltage regulator (a switching DC/DC regulator for those kind of voltages) to convert the voltage properly.


body:
The short answer is NO, you can't do that. Consider the size of the resistor needed to dissipate all that wattage and the fact that the current is not stable so it is practically impossible.

What you need is a DC to DC converter.


message:
unbrick Nano RP2040 connect using Uno

I think I have bricked my Nano RP2040. How do I unbrick using a Uno or Mega? I found instructions for using another Nano, but only have the one.

body:
You don't actually need a Uno or mega to unbrick the device.
You need to place a jumper wire between the GND and REC pins.
This will force the bootloader to load, a mass-storage device will appear on the computer. You can than upload a UF2 file to the drive to restore it.

You can read more about it in the arduino documentation.
https://docs.arduino.cc/tutorials/nano-rp2040-connect/rp2040-01-technical-reference#forcing-bootloader

If it is really bad you might also need to use a flash_nuke.uf2 file first. This removes all files on the Arduino Nano RP2040 connect.


message:
I am trying to automate my sun shade on my back porch with a Nema17 Stepper motor

I am very new to Arduino (and fritzing so please excuse my poor layout).
I am trying to automate my patio sun shade, eventually it will incorporate a photocell but I wanted a proof of concept first with buttons. The first and last buttons represent limit switches and the middle button represents a toggle switch (which will eventually become the photocell).

 An example of what I am trying to do is;
If the upper limit switch is active and I press the toggle button, the stepper runs until it hits the lower limit switch, if the lower limit switch is active and I press the toggle button then the stepper should run the other direction until it hits the upper limit switch.

 I have serial prints to show what is happening, if I hold either of the "limit switches" then the serial monitor displays (rather spams) the corresponding print line, however the stepper motor is not moving how I would expect it to. I have to be holding a limit switch and holding the toggle for it to move in a direction, even then it only moves approximately 1 step per second. If I release the limit switch and continue to hold the toggle then the stepper steps one back and one forward for the duration that I depress the switch. The code I have is based off of someone attempting the same thing but with a DC motor, I tried to accommodate it to a stepper motor and am having trouble.
[![enter image description here][1]][1]

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

        // constants won't change. They're used here to set pin numbers:
    const int uplimitPin = 9;     // pin number for upper limit switch
    const int togglebuttonPin = 10;     // pin number for the toggle switch
    const int downlimitPin = 11;     // pin number for the lower limit switch
    const int dirPin =  2;      // direction pin for stepper
    const int stepPin =  3;      // step pin for stepper

    // variables will change:
    boolean uplimitState = 0;         // variable for reading the status of the upper limit switch
    boolean togglebuttonState = 0;         // variable for reading the toggle switch status
    boolean downlimitState = 0;   // variable for reading the status of the lower limit switch

    int shadePosition = 2;  // Tells progam what position the shade is in

    /**
     *  setup inputs for switches and outs for motor pins
     *  serial begin to read the switches to test for errors
     */
    void setup() {
        // initialize the stepper pins as outputs:
        pinMode(dirPin, OUTPUT);
        pinMode(stepPin, OUTPUT);
        // initialize the pushbutton pins as an inputs:
        pinMode(uplimitPin, INPUT);
        pinMode(togglebuttonPin, INPUT);
        pinMode(downlimitPin, INPUT);
        Serial.begin(9600);
    }

    /**
     * this function turns motor foward
     */
    void shadeDown() {
         // turn motor foward:
        digitalWrite(dirPin, HIGH);
        digitalWrite(stepPin, HIGH);
        delayMicroseconds(1000);
        digitalWrite(stepPin, LOW);
        delayMicroseconds(1000);
    }

    /**
     * this function turns motor backwards
     */
    void shadeUp() {
         // turn motor in other direction:
        digitalWrite(dirPin, LOW);
        digitalWrite(stepPin, HIGH);
        delayMicroseconds(1000);
        digitalWrite(stepPin, LOW);
        delayMicroseconds(1000);
    }

    /**
     * Stop the motor form moving
     */
    void stopShade() {
      digitalWrite(stepPin, LOW);

    }

    /**
     *
     */
    void loop() {
       // read the state of the pushbutton value:
       uplimitState = digitalRead(uplimitPin);
       togglebuttonState = digitalRead(togglebuttonPin);
       downlimitState = digitalRead(downlimitPin);

       // check if the limit is active. If it is, the limitState is HIGH:
       if (uplimitState == HIGH) {
          shadePosition = 2;
          Serial.println(F("The shade is up"));
          stopShade();
       }else if (downlimitState == HIGH) {
          shadePosition = 1;
          Serial.println(F("The shade is down"));
          stopShade();
      }

      if (togglebuttonState == HIGH) {
        if( shadePosition  == 1 ){
          shadeUp();
          delay(100);
          shadePosition = 2;
          delay(100);
        }else if (shadePosition == 2 ) {
          delay(100);
          shadeDown();
          delay(100);
          shadePosition = 1;
        }

      }
    }

body:
Assuming you're asking how debug the unexpected behavior your described (and not having any steppers on-hand to have a go at your code) I'll offer some observations and suggestions.

Pushbuttons "bounce" (not really, but their output signal looks like they bounce). For the limit switches, you won't really care - the first make (and I'm assuming positive logic, for simplicity of the discussion) tells you that the shade has reached it's limit, and you don't need to (probably shouldn't!) wait for the switch to settle before stopping the shade. The 'break' of a limit switch is uninteresting except possibly to confirm that the shade is moving when you expected it to, and again, who cares about the bounces? But the toggle button's bounces may well confound your logic unless you debounce it (can be done either electrically or in software - search the topic). And even though the eventual photocell may not bounce (or it may: are there shade-trees within it's view, f/ex?), right now, you're testing with a button which certainly does.

This is a would be a good application to implement as a state-machine, and even if you don't do that formally, diagramming a state-machine to operate your shade should make it clear what your code will need to do. If you're new to software as well as to Arduino, learning about state-machines might be a longer detour than you want to take at the moment, but if this kind of control system is what interests you, you will encounter them sooner or later, because they model your control system pretty directly, both graphically (because you usually sketch them out first) and in software.

State diagrams turn out to be one of the best tools a software designer has to communicate the details of a proposed control system between them and the typically-non-software-trained people who are the experts at building and/or using the devices being automated (think printing presses, copiers, assembly robots, .... ). The picture says it all.


body:
# System State Machine
As JRobert suggested, a state machine would make the code a lot cleaner! Below is some pseudocode (I'll leave the debugging up to you ;)) of how you might set that up.

When you break up your system into 4 distinct states, it's easy to reason about what should be happening at each state and what is required to get to the next state. You can draw a diagram showing this (google "state machine") to help you reason.

```C++
...

enum SystemState {
    SystemState_Opening,
    SystemState_Closing,
    SystemState_Open,
    SystemState_Closed
};

void main()
{
    // Set initial state
    SystemState state;
    if (digitalRead(upLimitState))
    {
        state = SystemState_Closed;
    }
    else
    {
        state = SystemState_Open;
    }

    // Run state machine
    while (1)
    {
        switch (state)
        {
            case SystemState_Closed:
            {
                if (digitalRead(toggleButtonPin))
                {
                    state = SystemState_Opening;
                }
                break;
            }
            case SystemState_Open:
            {
                // TODO: Implement this yourself!
                break;
            }
            case SystemState_Closing:
            {
                if (digitalRead(upLimitState))
                {
                    state = SystemState_Closed;
                }
                shadeUp();
                break;
            }
            case SystemState_Opening:
            {
                // TODO: Implement this yourself!
                break;
            }
    }
}
```
# What's Wrong With Your Code
The actual issue with the code you provided is that you're only calling the `shadeUp()` function once. You need to call it many times to send the step pin many pulses to rotate the motor.

Each time you send a pulse to the step pin (eg. `shadeUp()`), you rotate the motor by one step (or microstep) which is likely only 1.8 degrees!


message:
Save Watchdog ISR Return Address in EEPROM

If the WDT ever fires, from the ISR I save some info in EEPROM for later diagnostics before I drive the reset pin. Stack size, heap size, etc.

It might also be useful to know where the code was when the WDT fired, i.e. the ISR's return address. How do I get that?

body:
GCC has a handy function `__builtin_return_address(depth)` which should do what you want.  To get the return address of the current function (which should be the same whether it's a normal function or an ISR on AVR) you set the `depth` to 0:

```c++
void *addr = __builtin_return_address(0);
```

**EDIT**

The address returned above is a word address. Multiply by two to get a byte address as found in the disassembly from `avr-objdump -SC firmware.elf >disassembled.txt`

The latter is found at `~/.platformio/packages/toolchain-atmelavr/bin/avr-objdump`


message:
Can Arduino UNO be used to emulate a PS4 joystick?

**I Want to know if there is a library that can be used in order to make a PS4 controller with Arduino.**
I have a PS2 steering wheel and I want to use it thorugh Arduino with PS4. I know that PS4 has his own protocol but I think there may be a way to do it.

Cheers!

**EDIT:** I already have the code for reading the PS2 steering wheel, but now I need to "transform" that into PS4 protocol

body:
TLDR: Not sure but the PS4 protocol is known and written for other MCUs, and can be found on github.

Not sure if there is a library for it in Arduino, but there are libraries out there (such as Passing Link) that emulate the protocol on other platforms. You can look at that.

BUT...

PS2 and PS4 are completely different beasts. PS2 uses SPI for its protocol. PS4 uses USB with specific USB drivers. Even if you manage to get the PS4 protocol working, the next problem is authenticating you are a legit/licensed controller. For every legit controller, there lies a security chip inside. And that chip also has a proprietary way to be talked to as well. When a legit controller is talking to a PS4, the PS4 will sometimes ask for the contents in the security chip for authentication. If you can't deliver the contents it wants, your controller is locked out until next power up (maybe even next PS4 power up, not sure).

So while it may be possible, the two huge hurdles are:
1) Implementing the USB code properly with custom drivers defined by Sony.
2) Circumventing the security chip by either ripping contents off a legit controller or mining it and placing it in your own circuit. Both of which will require an understanding how how to communicate with said chip.


message:
How to send data from esp-01 Wi-Fi module to arduino

The L1 is the value i will get from firebase database, but now i wanna send the value that i receive in realtime database to arduino to on LED, how to solve? any suggestion? which mean when arduino receive value 1 from firebase then led will on

ESP8266 code :

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

    // Set these to run
    #define FIREBASE_HOST ""
    #define FIREBASE_AUTH ""
    #define WIFI_SSID "Home "
    #define WIFI_PASSWORD ""

    int value1;

    void setup() {
      //Initializes the serial connection at 9600 get sensor data from arduino.
      Serial.begin(9600);

      delay(1000);

      WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
      while (WiFi.status() != WL_CONNECTED)
      {
        delay(500);
      }

      Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH);
      Firebase.setInt("L1",0);
    }

    void loop()
    {
      while(Serial.available())
      {
            value1 =  Firebase.getString("L1").toInt();
      }

      delay(1000);
    }

Arduino code:

    #define LED 13;

    int value1;

    void setup()
    {
      pinMode(LED,OUTPUT);
      Serial.begin();
    }

    void loop()
    {
      if (value1 == 1)
      {
         digitalWrite(LED, HIGH);
      }
    }

body:
Your ESP needs to

 - receive data from Firebase over WiFi;
 - send the received data (or the useful part of it) to the Arduino, over its serial port.

Your Arduino needs to:

 - watch its own serial port for data becoming available;
 - read the data;
 - decide whether turn the LED on or off.

Your loop() code on the Esp is watching its serial port, but from your description, it shouldn't expect any data from its serial port - that is connected to the Arduino. You need to watch for data arriving *via WiFi* instead.

Your Arduino code is testing the variable `value` but value never gets set to anything. You should set it according to what you receive from the Esp.

Also, since I'm not familiar with Firebase, does the Esp need to tell Firebase each time it wants new data? Or does Firebase send data at intervals without you having to ask for it? If it's the former, your Esp will need code to ask for the data and wait for it to arrive before it can send it on to the Arduino.


body:
ESP8266 code :

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

    // Set these to run
    #define FIREBASE_HOST ""
    #define FIREBASE_AUTH ""
    #define WIFI_SSID "Home "
    #define WIFI_PASSWORD ""

    int value1;
    String string_value;
    void setup() {
      //Initializes the serial connection at 9600 get sensor data from arduino.
      Serial.begin(9600);

      delay(1000);

      WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
      while (WiFi.status() != WL_CONNECTED)
      {
        delay(500);
      }

      Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH);
      Firebase.setInt("L1",0);
    }

    void loop()
    {

            value1 =  Firebase.getString("L1").toInt();
            string_value = String(value1);
            Serial.print(string_value);

      delay(1000);
    }

Arduino code:

        #define LED 13

    int value1;
    String data;

    void setup()
    {
      pinMode(LED,OUTPUT);
      Serial.begin(9600);
    }

    void loop()
    {

      bool Sr =false;

      while(Serial.available()){

            data=Serial.readString();
            value1 =data.toInt();
            Sr=true;

        }

        delay(500);

        if(Sr){

            if (value1 == 1)
            {
               digitalWrite(LED, HIGH);
            }else if(value1 == 0){

                digitalWrite(LED, LOW);
              }
       }
    }

For More details:

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

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