message:
ATTINY85 - RF Transmitter (RH ASK)

I am working on a small RF sensor powered by a battery.
I used the code from Mr K. (https://arduino.stackexchange.com/a/55516/65870) as base and adapted it to the RH Ask protocol:
```
#define F_CPU 8000000  // This is used by delay.h library

#include <util/delay.h>
#include <avr/sleep.h>
#include <avr/wdt.h>
#include <util/crc16.h>

#define LED_PIN           0

#define TX_PIN            4 //3
#define TX_BAUDRATE       2000
#define TX_MILLIINTERVAL  (1000UL/TX_BAUDRATE)
#define TX_MICROINTERVAL  (1000000UL/TX_BAUDRATE)
#define TX_MAXLEN         12
#define RFRepetitions 3
byte RollingCounter = 0;

// Define sensor IDs (for MQTT)
#define SensorIDMoisture 6

// Define moisture sensor variables
#define MoistureSensorPinA    A1
#define MoistureSensorPinD    10
#define MoisturePowerOutPin   1
#define RFPowerPin            3 //4

inline void led(const bool onOff) { digitalWrite(LED_PIN, onOff ? HIGH : LOW); }
inline void tx(const bool onOff) { digitalWrite(TX_PIN, onOff ? HIGH : LOW); }

const uint8_t header[8] = { 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x38, 0x2C };
const uint8_t conv4to6[16] = { 0x0D, 0x0E, 0x13, 0x15, 0x16, 0x19, 0x1A, 0x1C,
                               0x23, 0x25, 0x26, 0x29, 0x2A, 0x2C, 0x32, 0x34 };

// Watchdog timer
#ifndef cbi
  #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
  #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

// Important: Sleep time equals the wdt_length setting multiplied by the wdt_loops_max
#define wdt_loops_max 225
#define wdt_length 9 // 9 = 8 seconds

volatile int wdt_loops = wdt_loops_max; // Start with maximum value in order to have a measurement when powering on the system

void rawSend(const uint8_t * p, uint8_t len) {
  while (len--) {
    const uint8_t val = *p++;
    for (uint8_t mask = 1; mask != 0x40; mask <<= 1) {
      tx(val & mask);
      delayMicroseconds(TX_MICROINTERVAL);

//      _delay_ms(TX_MILLIINTERVAL);
    }
  }
}

void send(const uint8_t * buf, const uint8_t len) {
  #define RH_ASK_HEADER_LEN 4
  //  First create the payload ...
  static uint8_t payload[(TX_MAXLEN+3+RH_ASK_HEADER_LEN)*2];
  uint8_t * p = payload;
  uint16_t crc = 0xFFFF;
  uint8_t v = len + 3 + RH_ASK_HEADER_LEN;
  crc = _crc_ccitt_update(crc, v);
  *p++ = conv4to6[v >> 4];
  *p++ = conv4to6[v & 0x0F];

  uint8_t _txHeaderTo = 0xff;
  uint8_t _txHeaderFrom = 0xff;
  uint8_t _txHeaderId = 0;
  uint8_t _txHeaderFlags = 0;

    // Encode the headers
    crc = _crc_ccitt_update(crc, _txHeaderTo);
    *p++ = conv4to6[_txHeaderTo >> 4];
    *p++ = conv4to6[_txHeaderTo & 0xf];
    crc = _crc_ccitt_update(crc, _txHeaderFrom);
    *p++ = conv4to6[_txHeaderFrom >> 4];
    *p++ = conv4to6[_txHeaderFrom & 0xf];
    crc = _crc_ccitt_update(crc, _txHeaderId);
    *p++ = conv4to6[_txHeaderId >> 4];
    *p++ = conv4to6[_txHeaderId & 0xf];
    crc = _crc_ccitt_update(crc, _txHeaderFlags);
    *p++ = conv4to6[_txHeaderFlags >> 4];
    *p++ = conv4to6[_txHeaderFlags & 0xf];

  for (uint8_t l = len; l--;) {
    v = *buf++;
    crc = _crc_ccitt_update(crc, v);
    *p++ = conv4to6[v >> 4];
    *p++ = conv4to6[v & 0x0F];
  }
  crc = ~crc;
  v = (uint8_t)crc;
  *p++ = conv4to6[v >> 4];
  *p++ = conv4to6[v & 0x0F];
  v = (uint8_t)(crc >> 8);
  *p++ = conv4to6[v >> 4];
  *p++ = conv4to6[v & 0x0F];

  //  Now transmit the header and the payload ...
  rawSend(header, sizeof(header));
  rawSend(payload, (len + 3 + RH_ASK_HEADER_LEN)*2);
  tx(false);

  //Serial.print("CRC: ");Serial.println(crc);
}

ISR(WDT_vect)
{
  wdt_loops++;
}

// Sleep
void system_sleep() {
  cbi(ADCSRA,ADEN);                    // switch Analog to Digitalconverter OFF

  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here
  sleep_enable();

  sleep_mode();                        // System sleeps here

  sleep_disable();                     // System continues execution here when watchdog timed out
  sbi(ADCSRA,ADEN);                    // switch Analog to Digitalconverter ON
}

// Setup for Watchdog
void setup_watchdog(int ii) {
  byte bb;
  int ww;
  if (ii > 9 ) ii=9;
  bb=ii & 7;
  if (ii > 7) bb|= (1<<5);
  bb|= (1<<WDCE);
  ww=bb;

  MCUSR &= ~(1<<WDRF);
  // start timed sequence
  WDTCR |= (1<<WDCE) | (1<<WDE);
  // set new watchdog timeout value
  WDTCR = bb;
  WDTCR |= _BV(WDIE);
}

void setup()   /*----( SETUP: RUNS ONCE )----*/
{
//  pinMode(LEDPin, OUTPUT);
  pinMode(LED_PIN, OUTPUT);
  led(false);

  // Initialize moisture sensor
  pinMode(MoistureSensorPinD, INPUT);

  // RF sensor initialization
  //driver.init();

  setup_watchdog(wdt_length); // approximately 8 seconds sleep

}/*--(end setup )---*/

void loop()   /*----( LOOP: RUNS CONSTANTLY )----*/
{
  if(wdt_loops >= wdt_loops_max)
  {
    //digitalWrite(LEDPin, HIGH);
    led(true);

    wdt_loops = 0;
    moisture_measurement();

    led(false);
  }
  system_sleep();

}/* --(end main loop )-- */

void moisture_measurement()
{
  // Activate sensor
  analogWrite(MoisturePowerOutPin,255);
  analogWrite(RFPowerPin,255);
  _delay_ms(150);

  // Turn On RF transmitter

  float MoistureMedian   = 0;
 // float sensorValue;
  for(int i = 0;i<=100;i++)
  {
    float sensorValue = analogRead(MoistureSensorPinA);
//    moisture_percentage = ( 100 - ( (sensorValue/1023.00) * 100 ) );
//    moistureSensorSum += moisture_percentage;

    MoistureMedian += ( 1 - ( (sensorValue/1023.00) * 1 ) );
    //delay(1);
    _delay_ms(1);
  }

  // Read digital values
  bool digitalValue = digitalRead(MoistureSensorPinD);

  // Switch off sensor
  analogWrite(MoisturePowerOutPin,0);

  // Transmit value
  TransmitSensorValue(SensorIDMoisture,MoistureMedian);

  _delay_ms(150);
  // Turn Off RF transmitter
  analogWrite(RFPowerPin,0);

}

void MessageEncrypt(int adressIn, int parameterIn, float payloadIn, byte pByteArray[])
{
  pByteArray[0] = (byte)adressIn;

  byte * payloadBArray = (byte *)&payloadIn;
  pByteArray[1] = payloadBArray[0];
  pByteArray[2] = payloadBArray[1];
  pByteArray[3] = payloadBArray[2];
  pByteArray[4] = payloadBArray[3];

  RollingCounter = RollingCounter + 1;
  if(RollingCounter > 2)
    RollingCounter = 0;

  pByteArray[5] = RollingCounter;
}

//CRC-8 - based on the CRC8 formulas by Dallas/Maxim
//code released under the therms of the GNU GPL 3.0 license
byte CRC8(const byte *data, byte len) {
  byte crc = 0x00;
  while (len--) {
    byte extract = *data++;
    for (byte tempI = 8; tempI; tempI--) {
      byte sum = (crc ^ extract) & 0x01;
      crc >>= 1;
      if (sum) {
        crc ^= 0x8C;
      }
      extract >>= 1;
    }
  }

  return crc;
}

void TransmitSensorValue(int SensorID, float SensorValue)
{
  byte MessageOut[6];
  MessageEncrypt(SensorID, 1, SensorValue, MessageOut);

    for(int i=0;i<RFRepetitions;i++)
    {
      send((const uint8_t *)&MessageOut, sizeof(MessageOut));
    }
}
```

The code runs like a dream as long as I use 2000 as baudrate. As soon as I use another baudrate (500 or 1000) my test receiver does not receive any messages.

Any ideas what is going wrong here?

Thanks :)

body:
I found the problem.
I used 2 2032 battery to power the attiny85. The internal clock of the chip is not precise enough when running at 6V. To solve the issue I removed 1 battery. The alternative would be to set the baudrate of the transmitter and receiver to different values (I had to set the receiver to 520 bdps to receive the messages from the transmitter with 500 bdps).

Maybe somebody can reuse my code for his project.


sender: user

message:
Power Arduino and LED strip

I saw [this][1] question about powering Arduino and LED strip. So, I searched for a 5v 4a power supply and foud [this one][2].

How does that adapter provide power for both Arduino and LED strip? I thought I might need [DC barrel Plug to alligator clips][3] but I'm not sure as this is the first time I use an external power supply to power multiple components.

So what do I need to make that wall adapter able to power both Arduino and LED strip?

  [1]: https://arduino.stackexchange.com/questions/64807/how-to-power-arduino-nano-and-led-strip
  [2]: https://www.adafruit.com/product/1466
  [3]: https://www.adafruit.com/product/1329

sender: assistant

body:
I assume, that your problem is how to connect everything to the power supply.

You have some different options, depending on your requirements. The linked adaptor (barrel plug to alligator clips) doesn't seem to fit the barrel plug of the power supply. So you cannot use that. Especially it seems, that both are the male part of the connection. For every plug connection you need a male and a female part of the same connector type (much like your power outlet on the wall is a female part, while the power plug on your supply is a male part; in terms of plug systems).

- The best way (especially, when you want to not only experiment, but also use it as a fixed product) would be to solder the wires. For this you need a soldering iron, soldering tin and something to clean the iron (sponge for soldering irons for example).
    - You can buy a barrel jack, solder wires to it and connect them to the Arduinos 5V pin, ground and to the LED strips power lines in parallel (from + pin of the supply one wire each to 5V Arduino and + pin of the LED strip, from - pin of the supply one wire each to ground of Arduino and - pin of the LED strip). Then you can still disconnect the power supply from your project.
    - If you don't want to buy a barrel jack and you don't need to disconnect the power supply from your project, you can splice up the cable of the power supply (only the LOW VOLTAGE PART!!!). You can use nail scissors, if you don't have other tools for it. Cut off the plug by cutting the cable a few cm before it. Then cut the plastic between the 2 connected parts of the cable for a few cm, so that you get the 2 individual cables (+ and -).  Use the scissors to carefully cut the outer plastic around the cables and remove about 1cm of it, so that you now have 2 cable ends with the bare cable core free. Twist each end, so that it each little copper strand stays in the cable shape. Then solder the cable ends. Now you can take another wire/cable to solder the connections from the two ends to the described parts. Be sure to isolate the connections at the cable (in the best case with shrinking pipes, otherwise you can also use tape).

- If you don't want to solder, you can search for fitting connectors for every part. There are breadboard power adaptors, which should work with this power supply. They have pins on them, that you can not only use with breadboards, but you can also connect jumper wires to them. There also exist such adaptors for typical LED stripes, though that depends on the type of strip, that you have. When looking for jumper wires, you should make sure, that they are capable of conducting enough current. The Arduino does not need much current, thus standard jumper wires will be sufficient. But the LEDs can draw much more current, so that the standard jumper wires will start to smolder and catch on fire. Then you need some with a bigger wire diameter.

- You can also use alligator clips, but in my experience, they only work for rather specific cases. The connection, that they make, is fragile and can be easily disturbed. They are slipping and rotating easily. When connecting the LED strip, you might easily connect + and - together and destroy the power supply. Also it is almost impossible with most of them to connect to a standard 0.1 inch pin (which are used on the Uno and Nano), without also connecting other pins. Unless you break out these pins with something else (like jumper cables), that is not a good choice.

---

You can now choose yourself, which way to go. If you plan to do more with Arduino and electronics, I would suggest, that you buy a soldering iron and the needed supplies. You will need it and they only cost a few bucks, if you just buy a simple one (back then I got one for 15€/$, which also had a temperature control, so you can also get it cheaper). If you don't want to buy it, but still want to solder, you could look for a maker space near your location.

I would go for soldering here, because you are very much limiting yourself, when you choose to do not. Then you need to buy fitting parts, which is more difficult.

> how do I know what the ground is and the 5v?

For the power supply you can see it on the label. There you will find the following sign:

[![Polarity sign on power supply][1]][1]

It means, that the outer shell of the connector is ground (`-`) and the inner pin is 5V (`+`). With cables there are 2 possibilities:

- Often the wires inside a cable each have an own isolating plastic shell around them, which is color coded. Black is normally ground, while red is 5V/+.

- When having a 2 wire cable, the cable is often designed as coaxial cable (which reduces noise on the signal). In that case you have one inner wire, which has it's own isolating plastic shell, and the outer wire, which is laid around the inner wire without any further isolation. The outer wire is normally ground.

When using an extra cable for connecting 2 parts, make sure to use the same wires on both sides (for example the red wire for 5V on both sides).

To be sure, you can check the voltage on the wires with a multimeter (also a very useful tool), when the cable is connected. A multimeter has a positive and a negative lead, which are marked as red and black respectively. When you connect the multimeter to the wires and it shows a positive voltage, you have found the correct association of the wires with their voltage (5V or ground).

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


body:
You can feed 5V directly into the 5V pin of the Arduino as ChrisL says. However, that bypasses the protection circuits built into the Arduino. If you ever forget to disconnect the 5V and plug a USB cable into your Arduino then you risk damaging it, since both your external power supply and the USB port will be feeding 5V into the 5V line.

What I decided to do is to cut the end off of USB cable and connect that to my 5V power supply. On almost all USB cables, the +5V wire is red and the ground wire is black. You'd just solder red to +5V and black to ground, then plug the USB cable into your Arduino. Then when you need to connect the Arduino to your computer, you disconnect the USB power cable and plug in a USB data cable. It's impossible to feed power from both sources at once.

If you're going to be doing much tinkering with Arduinos and electronics you should get a decent soldering iron and an auto-ranging multimeter. You can use the multimeter to figure out which wires are which. (See chrisl's on how to use a multimeter to find positive and negative power connections.

Another issue you may face is voltage droop on your power supply as your LED strip turns groups of LEDs on and off. If you draw near the max current from your power supply then there will likely be fluctuations in the power supply voltage as the LEDs turn on and off.

What are the max current requirements for your LED strip? You don't want to draw too close to the full output of your power supply or you might get fluctionations in voltage that could cause your Arduino to malfunction. If you use a power supply with something like 25% extra capacity (Say your LED strip draws 4A and you use a 5A power supply instead) you should be ok.


message:
Digital Pin won't ground when set to LOW

My friend and I are repurposing an old rc car for a project. When we connect the dc motors to 5V and ground, the motors spin. However, when we power the motors from 5v and ground it in the digital output pin set to LOW, nothing happens. The identical circuit works in tinkercad. We are using a nano, but have tried an uno and mega as well.[![][1]][1]

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

body:
**Never directly connect a motor to an Arduino IO pin**

You *will* destroy the Arduino.

An Arduino cannot source (or sink in your case) enough current to drive a motor, and if the motor did manage to turn the huge amounts of EMI it generates would literally blast holes in the silicon inside the chip.

You *must* use a motor driver of some form. If you only want one direction that driver can be a single NPN Bipolar transistor or N-channel MOSFET.  If you need it to change direction then an H-bridge is what you want.


message:
if I add a .cpp file, Serial becomes unusable

I am using the mega 2560. When I just use .ino and .h files, if I use Serial, it works fine, without even using:

    #include <SoftwareSerial.h>

However, when I add a .cpp file I start getting 2 errors, one is solved by adding the aforementioned include, the second one, after adding it, is :

    'Serial' was not declared in this scope

I know I can declare it manually and use the RX/TX pins, but I would like to be able to use the default Serial so that I don't have to occupy more pins. Especially since it works file w/o the .cpp file. Can anyone explain to me why this happens? Is it because I specify a C++ file so the compiler changes?

body:
A CPP file isn't an Arduino file. It doesn't know about anything Arduino-esque unless you tell it about it.

The simplest way is to just add, at the top of the file:

    #include <Arduino.h>


message:
What does display.setSegments(&segto, 1, 1); do?

I am using a TM1637 display for my Arduino Uno. The goal was to just light up one point of the colon in the middle - what seems to be kind of impossible to accomplish. During research I stumbled over the following snippet, which I dont fully understand:

      uint8_t segto;
      int value = 1244;
      segto = 0x80 | display.encodeDigit((value/100));
      display.setSegments(&segto, 1, 1);

Ok line 1 seems to declare s.th. like a char, an unsigned 8bit integer. Line 2 should be clear.
Line 3: The pipe symbol seems to do a kind of addition - never seen this before. The rest here is also not clear to me - why these strange calculation to pass a value (here 2) to .encodeDigit() ?
Finally line 4: Why is the adress of 'segto' passed to the function instead of just the value?

This all ends up showing a "2:" on the display. I got the snippet from this 'manual': https://robojax.com/learn/arduino/robojax-TM1637_display_manual.pdf

Maybe s.o. can help to light things up a bit

body:
Let's take the hardest line first.  We'll start from the "inside" outwards.

    segto = 0x80 | display.encodeDigit((value/100));

The innermost bit is:

    value/100

That gives you 12 from 1244.

Then there's modulus 10.

    12

That gives you 2 (divide by 10 and return the remainder - 12/10 = 1.2, or 1 remainder 2)

That is then passed through a function that calculates what segments need to be turned on to represent the digit 2. Let's say that's `00110111` in binary, where each bit represents a segment to display.

To that you want to add the colon, which is in the most significant bit's place.  So you set that bit. That's done with the `OR` operator, which in C is `|`. `0x80` is `10000000` in binary.

OR the two values together:

    00110111
    10000000
    ========
    10110111

That value is then assigned to the `segto` variable.

I am not familiar with that library, but I would assume that the `setSegments` function is expecting an array of segment settings, a number of digits to apply it to, and maybe a digit offset in the display (at a guess).

In C there is no real difference between using a 1 element array and using a variable and taking its address.

You could just as well have used:

```
uint8_t segto[1];
int value = 1244;
segto[0] = 0x80 | display.encodeDigit((value/100));
display.setSegments(segto, 1, 1);
```

If you were doing more than one digit you'd be wanting to use an array anyway.


message:
GPS date and time not displaying correctly in Arduino Uno,NEO6M GPS module

I am learning how the Arduino and GPS module work so I can apply it to another project.
My components are an Arduino Uno, NEO-6M GPS module, and a Adafruit 1.8" TFT display.

The code did not work as expected.  It does display "waiting for sats".

However, it still displays the generic time and date, 1-1-1970 and 12:00:00 AM, for a while until the local time adisplays.

Plus the updated code takes a lot longer to display the time

Here is the code so far.  What I would like it to do is:
1) Display "waiting for sats"
2) continue when a successful GPS signal is received
3) adjust GPS time & date to local
4) display date and time

Eventually this will be the basis for a Speed and GPS trackker for my RC vehicles.
Any help is greatly appreciated.
<!-- language-all: lang-cpp -->

    #include <SPI.h>
    #include <Adafruit_GFX.h>
    #include <Adafruit_ST7735.h>
    #include <TimeLib.h>

    #define cs   10
    #define dc   8
    #define rst  9

    #include <TinyGPS++.h>
    #include <SoftwareSerial.h>
    Adafruit_ST7735 tft = Adafruit_ST7735(cs, dc, rst);

    static const int RXPin = 2, TXPin = 3; //GPS communication

    // Change this value to suit your Time Zone
    const int UTC_offset = -4;   // Eastern Australia Time is 10

    static const uint32_t GPSBaud = 9600;

    TinyGPSPlus gps;
    SoftwareSerial ss(RXPin, TXPin);

    time_t prevDisplay = 0; // Count for when time last displayed

    void setup()
    {

      Serial.begin(9600);  //set baud rate for serial monitor
         ss.begin(GPSBaud);  //set baud rate for GPS

       tft.initR(INITR_BLACKTAB);     //correct INITR for my display

      tft.fillScreen(ST7735_BLACK);
      tft.setCursor(20, 58);
      tft.setTextSize(1);
      tft.setTextColor(ST7735_GREEN,ST7735_BLACK);
      tft.println("GPS Date & Time");
      tft.print("        Monitor");
      delay(3000);
      tft.fillScreen(ST7735_BLACK);
    }

    void loop()
    {

      tft.setTextSize(1);
      tft.setTextColor(ST7735_GREEN,ST7735_BLACK);

         if (ss.available() < 1)
    {
           gps.encode(ss.read());
     }

            GPS_Timezone_Adjust();  // Call Time Adjust Function

    }

    void GPS_Timezone_Adjust(){
      while (ss.available() > 0) {
        gps.encode(ss.read());
        if (gps.location.isUpdated()) {

          int Year = gps.date.year();
          byte Month = gps.date.month();
          byte Day = gps.date.day();
          byte Hour = gps.time.hour();
          byte Minute = gps.time.minute();
          byte Second = gps.time.second();

    //Hour = hourFormat12();
            // Set Time from GPS data string
            setTime(Hour, Minute, Second, Day, Month, Year);
            // Calc current Time Zone time by offset value
            adjustTime(UTC_offset * SECS_PER_HOUR);

        }
      }

      if (timeStatus()!= timeNotSet) {
      if (now() != prevDisplay) {
          prevDisplay = now();
          ClockDisplay();
        }
     }
    }

    void ClockDisplay(){
        tft.setCursor(5, 8);

        tft.setTextColor(ST7735_GREEN,ST7735_BLACK);
        tft.print("Date:   ");
        tft.setTextColor(ST7735_CYAN,ST7735_BLACK);

          if(month() < 10){
            tft.print("0");
            }
          tft.print(month());

          tft.print("-");

          if(day() < 10){
            tft.print("0");
            }
          tft.print(day());

          tft.print("-");

          tft.print(year());

        tft.setCursor(4, 30);
        tft.setTextColor(ST7735_GREEN,ST7735_BLACK);
        tft.print("Time:   ");
        tft.setTextColor(ST7735_CYAN,ST7735_BLACK);

          if(hourFormat12() < 10){
            tft.print("0");
            }
        tft.print(hourFormat12());
        tft.print(":");

          if(minute() < 10){
            tft.print("0");
            }
        tft.print(minute());
        tft.print(":");

          if(second() < 10){
            tft.print("0");
            }
        tft.print(second());

        if (isAM()) {
        tft.println(" AM ");
        } else {
        tft.println(" PM ");
        }

        tft.setCursor(5,50);
        tft.setTextColor(ST7735_WHITE,ST7735_RED);
        tft.println("RAW GPS DATE & TIME");

        tft.setCursor(5,58);
        tft.print(gps.date.month());
        tft.print("-");
        tft.print(gps.date.day());
        tft.print("-");
        tft.print(gps.date.year());

        tft.setCursor(5,66);
        tft.print(gps.time.hour());
        tft.print(":");
        tft.print(gps.time.minute());
        tft.print(":");
        tft.print(gps.time.second());

      smartDelay(400);
      }
        // deadline for a good recption
          static void smartDelay(unsigned long ms)
      {
      unsigned long start = millis();
      do
      {
        while (ss.available())
          gps.encode(ss.read());
      } while (millis() - start < ms);
    }

body:
I'm guessing that the GPS module doesn't receive a time reading until it acquires a GPS lock. That can take many seconds.

You haven't posted your code so we can't tell how you're handling the time reading.

I would suggest checking for the midnight 1970 time (which is the UNIX "epoch time") and handling that with special-case code. If you're reading the time as a numeric value it is almost certainly 0.


body:
> Display "waiting for sats" ... continue when a successful GPS signal
> is received

You are (or the Arduino library you are using is) using the [time.h library][1] which starts on January 1st, 1970.  If no adjustments are made, time.h will report January 1st, 1970.

You are not (or the Arduino library you are using is not) waiting for a "good GPS signal" indication from the GPS module before displaying the time.

> adjust GPS time & date to local

If you are using time.h you (or the Arduino library you are using) should set a time-zone offset instead of correcting the time by hand.  This will take advantage of the time.h library utilities which take care of troublesome cases like calculating a time & date which crosses midnight with respect to [UTC (aka GMT)][2].

> display date and time

The time.h library stores the date / time as the number of seconds since January 1st, 1970.  So when displaying the current time, use time.h function calls to convert this counter to the current local time.

Hints / Suggestions:

 - The GPS module is a radio receiver.  It works best when the view of
   the sky is unobstructed by buildings, trees, hills or bad weather.
   Such obstructions results in slow lock times or no lock at all.  The
   more satellites the GPS module can see the better.
 - The GPS module is a computer in and of its self.  The computer will
   analyze messages form satellites several times before it is ready to
   report location and time data.  If possible, leave the GPS module
   powered up even if the Arduino is not.  This should likely reduce or
   eliminate the delay the GPS module needs before  reporting location
   and time.

----
Added later...

@Tvr4 brings up a good point.  While time.h is more ubiquitous (used almost everywhere in C programming), in the Arduino paradigm, the [built in Arduino time library][3] is often used.  For more, this is discussed in [this stackoverflow question / answer][4].  If you want to dive into the Arduino time library, the code is in [this github repository][5].  Also, you should find more help with this time libaray in the readme file displayed on that web page.

  [1]: https://www.tutorialspoint.com/c_standard_library/time_h.htm
  [2]: https://en.wikipedia.org/wiki/Coordinated_Universal_Time
  [3]: https://playground.arduino.cc/Code/Time/
  [4]: https://stackoverflow.com/questions/59815331/how-to-use-time-library-in-arduino
  [5]: https://github.com/PaulStoffregen/Time


message:
ESP32 - `Brownout detector was triggered ` upon Wifi begin

I'm Using an ESP32 - NodeMCU. One of the MCU's is acting weird upon boot, while at start I thought it was something to do with its sleep cycle. But, it seems that even on a minimal code as shown below, I get this message at the Serial output: `Brownout detector was triggered `

    void setup()
    {
      Serial.begin(9600);
      Serial.println("\nBegin");
      Serial.println(bootCounter);

      WiFi.begin("Xiaomi", "guy");

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

Edit 1: attaching MCU picture.

[![ESP32 NodeMCU][1]][1]Can someone please explain ?

Edit 2: A workaround
[stop alerting][2]

  [1]: https://i.stack.imgur.com/Td5e3.jpg
  [2]: https://github.com/espressif/arduino-esp32/issues/863#issuecomment-347179737

body:
Those boards have an inherent weakness in that they don't provide enough decoupling capacitance for the module.

Not all modules are quite the same, and some have more internal decoupling than others (not by design, just due to component tolerances).

I have found that unless you provide adequate decoupling of your own some modules work just fine and some don't. Some brown-out and some fail to flash.

For all my designs now I always provide both a 100nF *and* an 10uF capacitor right at the power pins of the module. However those boards don't provide anything like that.

You need to modify the board to add a capacitor (about 10uF) directly across the power and ground pins (pins 1[ground]-2
[3.3v]) of the ESP32 module. I like to use an 0805 MLCC capacitor as they fit nicely across the pins and are discrete, but they can be tricky for a novice to solder. So an electrolytic through-hole capacitor can be a simpler proposition (make sure you get the polarity right).


body:
I came across the same issue on my experiments.

What sorted the issue for me was powering the ESP-32_CAM from the 5V pin on the programmer. Take the cable off the 3V and plug it into the 5V pin on the cam. Then use the jumper on the programmer to select the 5V.

I hope this makes sense and that it helps someone.


body:
After some Tests i recognized, that the problem is between the miro-USB-connector to the Vin Pin. So i soldered a thin wire from Pin 5 of the USB-Connector (5V-Pin) to the Vin-Pin of The Dev-Board.
And it works without Problems.


body:
I had the same problem. I found that solution in a forum on Github, which helped at once:

    #include "soc/soc.h"
    #include "soc/rtc_cntl_reg.h"
    void setup(){
    WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); //disable brownout detector


body: It could even be a software issue, i.e Code, if you use LedCWrite without its setup then it causes this issue.


body:
Swapping USB cable solved my issue of continuous brownout detector triggering.

I tried some above answers. Disabling brownout detector as suggested by Vahe Arakelyan helped on Blink sketch, but WiFi including sketches would still fail to run.

Then started to suspect HW and power failure. Did not soldering pins as suggested by user73106, but this made me notice voltage fluctuation. So swapped USB cable and this seemed to keep the voltage steady enough for good operation... It looks like some cable/connector fault may limit the current to allow some low power sketch to run but to fail on more current drawing sketch.


message:
Is it possible to get which pin generated interrupt?

I wrote some code that handles rotary encoder using an interrupt, but I would like to get which pin generated the interrupt, so I'll be able to handle many interrupts in a single method.

Something like:
<!-- language-all: lang-cpp -->

    void ISREncoders()
    {
      int pin = GetCurentInterruptPin(); // <============= this
      int dataPin = dataPins[pin];
      int data = DigitalRead(dataPin);
      if(data == HIGH)
      {
        encoders[pin] += 1;
      }
      else
      {
        encoders[pin] -= 1;
      }
    }

Is it anyhow possible?

------------------

As mentioned in the answer this is not possible. Still, after peeking some encoder libraries that use interrupt found out that they do the following:

The Encoder class contains several static ISR methods hard coded.

As you create new objects it increments an internal counter and sets proper ISR method on the interrupt.

This is for sure the best solution available, but this is not at all scalable, for instance if you have an imaginary board with thousand pins that handle thousands encoders you will have to hard code each ISR method.

body:
It is not possible to know which interrupt caused the ISR to be called. The INTFx flag gets cleared when the interrupt routine is called, so you lose that information (which is a shame).

The closest you could do is to have a separate ISR for each pin which just calls the common routine with a parameter to say which ISR it was executed via. That will add some extra latency though as it has to make an extra function call, but that can be somewhat mitigated by having the common function marked as `always_inline`, which means the compiler will duplicate it and place it within the code where it's being called from. This reduces latency but increases code size.

```
static ISREncoder(uint8_t pin) __attribute__ ((always_inline)) {
    // Do stuff with the `pin` variable
}

void ISR0() { ISREncoder(2); }
void ISR1() { ISREncoder(3); }
```


message:
How to send a number as a byte?

I want to send a number between 0 and 120 as a byte over Serial port. I'm working on a project that involves sending ultrasonic sensor readings over Bluetooth to an Android. I would like to send the entire reading as a byte and I think this can be done because an signed byte ranges from -128 to 127. However, the byte received in my Android app doesn't show the correct sensor reading. Here's the relevant code snippet:

      while (true){
          //ultrasonic sensor sends out signal
          digitalWrite(trigPin, LOW);
          delayMicroseconds(2);
          digitalWrite(trigPin, HIGH);
          delayMicroseconds(10);
          digitalWrite(trigPin, LOW);
          pinMode(echoPin, INPUT);
          duration = pulseIn(echoPin, HIGH);

          cm = (duration / 2) / 29.1;   // Divide by 29.1 or multiply by 0.0343
          inches = (duration / 2) / 74; // Divide by 74 or multiply by 0.0135
          // max range is 156 inches, but our app will only display up to 100 inches
          inches = min(127, inches);
          Serial.print(inches, BIN);
          delay(50);

In my Android app written in Java I read the value like this:

    b = (byte) inputStream.read();
For example, if `inches` is 100 and I send that over Serial port, how can I expect to get the same reading in my Android app?

body:
The problem is the BIN in your print statement.  Everything is ALWAYS binary.  The BIN means to break that binary up into ascii digits 0 and 1.  So if you send

`Serial.print(21, BIN);`

then the print function takes 21 as a binary number, 00010101 and then sends those binary digits as ascii.  So what goes out on the wire is 8 separate bytes, it goes 48, 48, 48, 49, 48, 49, 48, 49 as 48 and 49 are the ascii codes for 0 and 1.

What you want to do is just to send the raw byte.  So use Serial.write instead.  The print functions convert things to ascii representations but the write function just sends the raw bytes out.  So if you write:

    Serial.write(inches);

Assuming that inches is a byte type variable then it just sends the raw byte out.


message:
Arduino using delay in I2C receiveEvent

I have read before that you can't use delay() inside I2C receiveEvent because it is an ISR.

What I want to do is as follows: I have a servo connected to my Arduino Uno and I want to control that using an I2C signal. Since I want to decrease the speed of the servo, I was previously using a loop with delay inside, which doesn't work when the function is called by I2C.

This is the code that I used before to control the servo:
```
void setServo(bool status) {
    if (status) {
        for (int pos = 0; pos <= 180; pos += 5) {
            servo.write(pos);
            delay(50);
            Serial.println(pos);
        }
    } else {
        for (int pos = 180; pos >= 0; pos -= 5) {
            wasteFlapServo.write(pos);
            delay(50);
            Serial.println(pos);
        }
    }
    servoStatus = status;
}
```

How could I still control the speed of the servo even if I use I2C? Thanks for your help.

Kind regards,
Moritz

body:
The general way of doing long things triggered by an ISR is to simply set a flag insode the ISR, which then gets checked inside `void loop()`.

    volatile byte flag = 0;

    void loop(){
        if(flag){
            // Do something here
            flag = 0; // reset the flag
        }
    }

    void receiveEvent(int howMany){
        flag = 1; // set flag, if correct data was received
    }

Here keep the following in mind:

- The `loop()` needs to run fast to react fast. Long delays are doing other long stuff there will impact the responsiveness of the code. Depending on your plans for the exact behavior, the usage of `delay()` is generally not good. You should look into the `BlinkWithoutDelay` example, that comes with the Arduino IDE. It is worth learning that rather early.

- `flag` mus be declared volatile, to tell the compiler, that is may change at any time. Otherwise it might optimize the variable away.

- `flag` is of type `byte` here. It is imprtant, that this flag only has a single byte, because reading and writing of a single byte cannot be interrupted. Multi-byte variables get read or written in multiple COU cycles, thus it would be possible, that the interrupt writes parts of the variable, while you are reading it in the main code. That would lead to garbled data. By using a single byte, you avoid using critical sections for keeping the reading in main code save. For a flag thats way simpler.


message:
using PN532 chip on arduino

I've recently purchased an NFC-PN532 module online, which I connected to my arduino board and tried to get working. After connecting the pins and using the PN532 adafruit lib I encountered and error where the board was not being picked up. I was using the 'readMifareClassic' example from the lib and uploaded the example to the board and it resulted in the image below where I would receive a '?' or the first print output which is 'hello' in the code. [![image of the result output in serial monitor][1]][1]

I'm not that experienced with NFC atm and so im seeking some guidance on what may be the issue. If you need more information please leave a comment.

Thank you

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

body:
A very common error when PN532 module is not recognized, is that you are not using the right bus (I2C, SPI, UART).

Make sure:

In Arduino sketch make sure to follow carefully the lines that need to be commented out.

On the PN532 make sure that DIP switches match your bus configuration


message:
Power supply for Seeeduino Xiao

The [Seeeduino Wiki][1] claims that it can run on 3.3V/5V. It doesn't specify if it can step down higher voltages. I am looking to power the XIAO using a battery. It usually uses a USB-C cable which can provide 5V. Will I need to step the voltage down, or does it behave like a normal Arduino Nano and automatically step down the voltage?

  [1]: https://wiki.seeedstudio.com/Seeeduino-XIAO/

body:
If you scroll down on that page you link to you can see the power circuit. It uses an [XC6206](https://www.torexsemi.com/file/xc6206/XC6206.pdf) voltage regulator which has a maximum input voltage of 7V and a dropout voltage that could be as high as 680mV.

So you can feed between about 4V and 7V in to the VIN pad and it will step it down to 3.3V. Anything below 4V and you will go "out of regulation" though the system may still run down to lower voltages. If you go above 7V you will blow it up.


body:
A batch of 60 XAIO ESP32C3's will not power on using a 3.3V DC supply applied to pins 3V3 and GND. They only power on using a 5V input applied to pins 5V and GND.
The test rig was a bench DC power supply.
The XIAO ESP32C3 seems to power on as low as 4.1V DC applied to the 5V pin.
No external component is required, just a direct connection from the bench power supply to the 5V pin. Therefore the posts somewhere on the internet about needing a diode in the path of the positive supply do not appear to be necessary.
Note that the ESP32C3 were not programmed, ie. they arrived from the factory and were powered without downloading any code to them. Thus the posts about sleep mode are not applicable as the 3.3V and 5V behavior should then be identical, but they are not.


message:
Why is there a need of use delay() after using Serial.flush() in the program

This code is a part of a long code for understanding serial communication and the functions related to it.
```
char buffer[18];
int red, green, blue;
int RedPin = 11;
int GreenPin = 10;
int BluePin = 9;

void setup()
{
Serial.begin(9600);
Serial.flush();
pinMode(RedPin, OUTPUT);
pinMode(GreenPin, OUTPUT);
pinMode(BluePin, OUTPUT);
}

void loop()
{
if (Serial.available() > 0) {
int index=0;
delay(100); // let the buffer fill up
int numChar = Serial.available();
if (numChar>15) {
numChar=15;
}
while (numChar--) {
buffer[index++] = Serial.read();
}
splitString(buffer);
}
}
```

In void setup(), Serial.flush() is used. On internet, I have read that it flush out any character present in a serial line. After calling it we can be sure that all the data has been sent before moving on to the next line of the program.

In void loop(), in the first if condition, delay(100) ensures to fill the buffer. Basically, buffer is the place in memory where the received serial data is stored prior to processing.

The question is that is there any need of using delay(100), if we call the Serial.flush() initially because it ensures that all the serial data has been transmitted (as in serial transmission one bit is transmitted at a time)? Does it takes further time to store the transmitted data in the memory (buffer) and does this is the reason to use delay(100)? Please clarify why delay(100) is used after calling Serial.flush(), I am confused.

body:
The Serial.flush() is doing nothing. It delays until all bytes have been sent out of the UART. Since nothing has been sent it's not got anything to wait *for*.

The delay after the `available` call is very bad practice. It's a really really bad way of dealing with serial reading.

You should read [this](https://majenko.co.uk/blog/reading-serial-arduino) for a better understanding of serial communication.


message:
How to convert RGB values to Intensity

I made an arduino color sensor with tcs3200 and arduino uno. I have coded the arduino to find the RGB values when I place the color paper below the sensor. How can I derive the intensity using the RGB values.

body:
There is no simple way to have a formula from the RGB values to intensity.
Also, there is intensity that can be measured with an intensity meter/sensor, but what people (humans, or each individual) consider more intensity (perceived intensity) is not fully related.

However, some things I found when I had a similar problem:

- Typically a LED value of 0 is OFF, 1 is shining a little and 255 a lot. However, the difference in (perceived) intensity between value 1 and 10 is much higher than between e.g. 100 and 255.
- Also, each LED color has a different intensity, e.g. red seems more bright than blue or green, with the same R, G or B value for the DMX lights I have, as can be read from the remarks from Duncan C and Majenko below, red is less bright than others.
- Also, it depends on the physical device probably (it could have an internal algorithm to convert an RGB value to some power driven to the LED(s)).

What you can do is measure for each value and color the intensity with an intensity meter or sensor.
Or, in case you are more interested in the perceived intensity, manually check two LEDs with values to and create your own intensity algorithm.

I ended up having 3 arrays (for R, G, B), having for each value from 0-255 an 'intensity' value. I did it partly by measuring, partly by manually checking.


body:
I remember a formula that calculated luminance (perceived brightness) using simple weights applied to the red, green, and blue values in a light source.

This formula allows for the fact that the human eye is most sensitive to green light and least sensitive to blue light.

The Wiki article on HSV/HSL has these different weightings for R,G, and B. (In all of the following, `Y'` is the computed brightness value.)

    Y' = 0.2989 • R + 0.5870 • G + 0.1140 • B
    Y' = 0.2120 • R + 0.7010 • G + 0.0870 • B
    Y' = 0.2126 • R + 0.7152 • G + 0.0722 • B
    Y' = 0.2627 • R + 0.6780 • G + 0.0593 • B

All of them weigh green more than the other 2. I didn't read the article closely enough to understand the different weightings of the different formulas. Perhaps they convert colors using different color models like Adobe RGB and sRGB.

See the link at https://en.wikipedia.org/wiki/HSL_and_HSV for more information.


message:
nRF24L01 - Measuring distance using time elapsed

For school usage, my team and I are working on a wristband that will alert the user if they are too close to another wristband (for social distancing). The problem is measuring distance using radio waves. Since I cannot use signal strength, I'm thinking about calculating distance from time taken to transfer some data and velocity (which will be around the speed of light). I discarded the idea of using ultrasound because it is too easily interfered with by other obstacles.

My plan is along the lines of this:

 - Sensor 1 and 2 are synchronised to a clock.
 - Both will run a
   "stopwatch", and the time values should be exactly the same at the
   same time.
 - Sensor 1 sends out a message to Sensor 2. The message
   contains the time at which the transmission started.
 - Sensor 2
   receives the message, immediately records the time of reception, and
   calculates the time taken for data to travel
 - d = v/t
 - Vice-versa

If the distance is smaller than the radius, a warning is triggered in the form of a vibration motor.

Limitations include clock speed; I intend on using a Seeeduino XIAO, an Arduino-compatible board. The clock speed is max. 48MHz, meaning that the smallest increments it can measure is 20.82 nanoseconds. I also calculated that it would take 13.33 nanoseconds to travel two metres (the former distance to keep in public). Hence, with the clock speed available to me, I can only measure 3m and beyond.

Assuming I was happy with this distance, would I be able to do this using one single Arduino sketch? I know that Arduino programs can only run one at a time. Would a constant background clock/stopwatch be too complex? Could you give me any other pointers?

body:
Speed-of-light-delay measurements are not practical for the use-case you propose. As Majenko suggests in his comment, you'd need EXTREMELY accurate time measurement, as well as high speed radio-frequency signal processing. Any measurements you do through software will be far too inaccurate as a result of the software timing.

Apple's iBeacons (which are based on BLE) offer immediate, near, medium, and far distance readings that are based on signal strength. You should be able to achieve something similar with your own wristbands using BLE. The different distance thresholds would have some slop to them, but it should be possible to get decent results.


message:
Connect two SD cards to one Arduino board and copy from one to another

I'm trying to connect 2 SD cards to an Arduino Uno board.

1. My first question is: Is it possible to connect two SD cards to one Arduino simultaneously?
2. The second question is: If it is possible to connect 2 SD cards, How can I copy card 1 data to card 2

My project goal is to copy data from one peripheral memory to another peripheral memory when an external interrupt occurs.
Can anyone help me please ?

body:
You can't do it with your **Arduino-Uno** (and usual SD libraries).

SD cards are organized in 512 byte "sectors". You need at least one sector for the file system itself and one sector for the data. If you try to have two files open simultaneously, all your 2048 bytes RAM are required for the SD buffers and you can't return from the file open() call any more.


message:
Nano: All digital pins do not output anything

New user here. Using the examples provided on the Arduino IDE software I could produce melodies with a piezo buzzer, or have a blinking LED.

Not anymore. No digital pin is giving anything. I can see the embedded LED blink if I program the Pin 13, but no impact outside of it.

So I tried connecting an output digital pin (13) to an Analog input pin, or any one that can be put as input (A7, D5, etc.) (with a resistor so not to destroy the little thing).

    const char out=13;
    const char  in=8;
    char         i=0;
    void setup() {
      Serial.begin(9600);
      pinMode(out, OUTPUT);
      pinMode(in,  INPUT);
      digitalWrite(out, LOW);
    }
    void loop() {
      if(i&1){
        digitalWrite(out,i&2?HIGH:LOW);
      }else{
        Serial.println(analogRead(in));
      }
      i++;
      delay(50);
    }

The output has been 0, whichever digital pin it is connected to.

How can I actually find out if, by any chance, I successfully (!) damaged all my digital pins?

  - I currently use a breadboard
  - The ground is connected correctly (to GND)
  - It stopped working between uses, last time I was trying a `Tone(out,val)` melody
  - I'm measuring the out-pin value by connecting it to an analog in-pin with a resistor in series
  - I did set the out-pin as such during setup. (`pinMode(out, OUTPUT);`)

---

So! Looks like I didn't understand the codes for the digital pins. I thought we had to use the pin number, but the digital pin number (say `10` for `D10`) is what it takes to address it. And I was always referring myself back to the schematic for each pin -_-.

As well with the accepted answer, I needed to pull down (or up? still can't figure it out!) the input pin with a resistor to ground.

Thanks everyone!

body:
Your sketch works on a Nano (clone) that I have

[![Nano with LED][1]][1]

I am using a high-brightness white LED with a 10kΩ resistor to bring the brightness down to a bearable level, so the current drawn is about (5v-2.2v)/10kΩ = 0.28mA. This is a low level of current and should be safe for poking around with.

> **I can see the embedded LED blink if I program the Pin 13, but no impact outside of it.**

That suggests that the ATmega328P is essentially undamaged and that at least the IC leg connected to D13 is working as it should.

> **How can I actually find out if, by any chance, I successfully (!) damaged all my digital pins?**

Without a multimeter or other tools,  I would take a LED and resistor that draw less than 5mA, test them between VCC and GND to make sure they work

Then I would use the resistor and LED to check the output of each of the D2 to D13 outputs using your existing sketch.

When the onboard LED blinks, I am able to attach a LED and series resistor to pin D13 and get it to blink.

---

I wasn't sure what you intended by setting `in` to `8` so I later changed your program as follows:

    const char  in=A1;

and I got this output on the serial monitor after connecting a jump lead from D13 to A1

    0
    1010
    0
    1009
    0
    1009
    0
    1009
    0
    1009
    0
    1009
    0
    1009
    0
    1009
    0
    1008

---

If I pivot the LED away from pin D13, I can use a jump lead as a test probe

[![using a jump-lead as a probe][2]][2]

Main points:

- pick a high resistor value that minimises current drawn but is still easily visible.
- check the LED works! (is right way around etc)
- use a jump lead as a probe.

There are more sophisticated test circuits you could build with a FET etc but this would normally be enough for me to decide if an Arduino's outputs are damaged.

---

Extract from ATmega328 datasheet - note the max current draw per pin is 40mA. Exceeding that is probably the easiest way to damage the IC but if the onboard LED labelled "L" (and connected to D13) works, it means that part of the IC is undamaged.

[![enter image description here][3]][3]

  [1]: https://i.stack.imgur.com/5XBFE.jpg
  [2]: https://i.stack.imgur.com/tRlPK.jpg
  [3]: https://i.stack.imgur.com/9V7a5.png


message:
Arduino Micro: 69 is supposed to show up when I press 1 on the keypad, however some weird number (15 in this case) is showing up

// **I AM ALSO GETTING WEIRD CLUELESS DELAYS WHEN I PRESS BUTTONS ON THE MODE MENU**

    /*
       Jebediah's Launch Control System for Kerbal Space Program
       Alpha Build 0.70
       An Open-Source Project by John Seong
    */

    #include <Wire.h>
    #include <LiquidCrystal_I2C.h>
    #include <Keypad.h>

    const byte ROWS = 4;
    const byte COLS = 3;

    char keys[ROWS][COLS] = {
      {'1', '2', '3'},
      {'4', '5', '6'},
      {'7', '8', '9'},
      {'*', '0', '#'}
    };

    int timeV, thrustV, massV, gravityV;

    byte rowPins[ROWS] = {12, 11, 10, 9};
    byte colPins[COLS] = {8, 7, 6};

    Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);

    bool keyDetect = false;
    bool menuKeyDetect = false;
    bool goHomeDetect = false;

    bool countDownDetect = false;
    bool countDownOutput = false;
    bool twrCalDetect = false;

    String timeValue, thrustValue, massValue, gravityValue;

    LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

    void setup() {
      Serial.begin(9600);
      lcd.begin(16, 2);
      lcd.clear();

      Startup();

      timeV = constrain(timeV, 15, 120);
    }

    void loop() {
      PressKey();

      if (menuKeyDetect == true) {
        PressMenuKey();
      }

      if (goHomeDetect == true) {
        GoHome();
      }

      if (countDownDetect == true) {
        CountDownSequence();
      }

      if (countDownOutput == true) {
        CountDownOutputSequence();
      }
    }

    // Pages & Sections
    void Startup() {
      lcd.print("Jeb's Launch");

      lcd.setCursor(0, 1);
      lcd.print("Control System");

      delay(3000);

      lcd.clear();
      lcd.print("Alpha Build 0.70");

      lcd.setCursor(0, 1);
      lcd.print(" STUDIO HORIZON");

      delay(3000);

      lcd.clear();
      lcd.print("Welcome, Kerman");

      lcd.setCursor(0, 1);
      lcd.print("Press any key...");

      keyDetect = true;
    }

    void ModeMenu() {
      menuKeyDetect = true;

      lcd.clear();
      lcd.print("1. Countdown");

      lcd.setCursor(0, 1);
      lcd.print("2. TWR");
    }

    void CountDown() {
      lcd.print("Time (sec): ");

      lcd.setCursor(0, 1);
      lcd.print("# to continue...");

      goHomeDetect = true;
      countDownDetect = true;
    }

    void TwrCal() {
      lcd.print("Thrust: ");

      lcd.setCursor(0, 1);
      lcd.print("# to continue...");

      goHomeDetect = true;
    }

    // Actions & Behaviours
    void PressKey() {
      char key = keypad.getKey();
      if (key) {
        Serial.println(key);
        if (keyDetect == true) {
          lcd.clear();
          ModeMenu();
          keyDetect = false;
        }
      }
    }

    void PressMenuKey() {
      char key = keypad.getKey();
      if (key == '1') {
        Serial.println(key);
        if (menuKeyDetect == true) {
          lcd.clear();
          CountDown();
          menuKeyDetect = false;
        }
      } else if (key == '2') {
        Serial.println(key);
        if (menuKeyDetect == true) {
          lcd.clear();
          TwrCal();
          menuKeyDetect = false;
        }
      }
    }

    void GoHome() {
      char key = keypad.getKey();
      if (key == '*') {
        lcd.clear();
        ModeMenu();
      }
    }

    void CountDownSequence() {
      char key = keypad.getKey();

      if (key == '0') {
        timeV = timeV + 0;
      }

      if (key == '1') {
        timeV = 69;
      }

      countDownDetect = false;
      countDownOutput = true;
    }

    void CountDownOutputSequence() {
        lcd.setCursor(13, 0);
        Serial.println(timeV);
        lcd.print(timeV);
    }

body:
According to [the documentation][keypad], the `getKey()` function is
_non blocking_. This means it does _not_ wait for a key to be pressed:
it instead returns immediately whether a key has been pressed or not. If
no key has been pressed (i.e. most of the time), it returns a NUL
character, which has the numeric value zero and evaluates to `false` in
a boolean context. Hence the idiom:

```cpp
char key = keypad.getKey();
if (key) {  // if a key has actually been pressed
    // handle it
}
```

The `CountDownSequence()` function fails to account for this:

```cpp
void CountDownSequence() {
  char key = keypad.getKey();  // no check for NUL

  if (key == '0') {
    timeV = timeV + 0;  // this has no effect at all
  }

  if (key == '1') {
    timeV = 69;  // this is what you would expect to be executed
  }

  countDownDetect = false;  // these two lines tell the rest of the
  countDownOutput = true;   // program that we are done.
}
```

Since `key` will almost certainly be `'\0'`, the program will move to
the next step without ever initializing `timeV`.

As a side note, I recommend you try to rewrite your program as a [finite
state machine][fsm]. A single `state` variable would make it less
confusing and easier to understand than the current collections of
booleans.

[keypad]: https://playground.arduino.cc/Code/Keypad/
[fsm]: https://majenko.co.uk/blog/finite-state-machine

------------------------------------------------------------------------

**Edit**: Expanding on the idea of the finite state machine. I tried an
implementation of your concept based on it.

For handling a menu system, where the user can navigate through several
on-screen “pages”, the most obvious first approach is to have one state
per page displayed. For this program, these states could be:

* `MENU`, which offers the choice to move to either of the following two
  pages
* `SET_COUNT` allows the user to set the countdown duration
* `TWR` allows him to compute the thrust/weight ratio
* `COUNT_DOWN` actually runs the countdown timer

In the following, I added an extra _transitional_ state called `START`
that comes right before `MENU`. This is not required, and its only
purpose is to avoid code repetition by having a single transition
(`START` → `MENU`) responsible for actually drawing the menu.

When implementing a finite state machine, my first recommendation would
be to start by drawing a [state diagram][] like this:

[![State diagram of Jebediah's Launch Control System][1]][1]

In this diagram, each transition is labeled with the event that triggers
it. The events are key presses, save for “finished” which means that the
countdown is done. The state diagram can become significantly more
complex than this as you add new functionality. It is, however, a very
good way of _designing_ your system from the point of view of user
interaction.

Once you are happy with the state diagram, the coding is just a matter
of translating it to a `switch`/`case` construct, with one `case` per
state. Here is my take at it:

```cpp
/*
   Jebediah's Launch Control System for Kerbal Space Program
   Alpha Build 0.70
   An Open-Source Project by John Seong
*/

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>

const byte ROWS = 4;
const byte COLS = 3;

char keys[ROWS][COLS] = {
  {'1', '2', '3'},
  {'4', '5', '6'},
  {'7', '8', '9'},
  {'*', '0', '#'}
};

byte rowPins[ROWS] = {12, 11, 10, 9};
byte colPins[COLS] = {8, 7, 6};

Keypad keypad=Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);

LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

// Show a two-line message on the LCD.
void lcdShow(const char *line0, const char *line1) {
  lcd.clear();
  lcd.print(line0);
  lcd.setCursor(0, 1);
  lcd.print(line1);
}

void setup() {
  Serial.begin(9600);
  lcd.begin(16, 2);
  lcdShow("Jeb's Launch", "Control System");
  delay(3000);
  lcdShow("Alpha Build 0.70", " STUDIO HORIZON");
  delay(3000);
  lcdShow("Welcome, Kerman", "Press any key...");
  while (!keypad.getKey()) ;  // wait for key press
}

void loop() {
  static enum {START, MENU, SET_COUNT, COUNT_DOWN, TWR} state = START;
  static uint32_t last_second;  // millis() value on last full second
  static int count;             // countdown value

  char key = keypad.getKey();

  switch (state) {
    case START:  // transitional state
      lcdShow("1. Countdown", "2. TWR");
      state = MENU;
      /* fallthrough */
    case MENU:
      if (key == '1') {  // Countdown
        lcdShow("Enter time", "seconds: ");
        count = 0;
        state = SET_COUNT;
      } else if (key == '2') {  // TWR
        lcdShow("Thrust:", "# to continue...");
        state = TWR;
      }
      break;
    case SET_COUNT:
      if (key >= '0' && key <= '9' && count <= 99) {
        lcd.print(key);
        count = 10 * count + (key - '0');
      } else if (key == '#') {
        lcdShow("Take off in", "     seconds");
        // Force a refresh on entering COUNT_DOWN:
        last_second = millis() - 1000;
        count++;
        state = COUNT_DOWN;
      } else if (key == '*') {
        state = START;
      }
      break;
    case COUNT_DOWN:
      if (millis() - last_second >= 1000) {
        last_second += 1000;
        count--;
        if (count == 0) {
          Serial.println("Take off!");
        } else if (count < 0) {
          state = START;
          break;
        }
        lcd.setCursor(1, 1);
        lcd.print(count<10 ? "  " : count<100 ? " " : "");  // pad
        lcd.print(count);
      } else if (key == '*') {
        state = START;
      }
      break;
    case TWR:
      if (key == '*' || key == '#') {
        state = START;
      }
      break;
  }
}
```

Note the comment “fallthrough” between `START` and `MENU`. This
indicates that the lack of `break` at this place is intended: the
processing of the `MENU` case will follow right after the processing of
the `START` case, in the same loop iteration. The purpose of the fall
through is to not loose the current key press, if any. If this is not
important, you could put a regular `break` here and defer the handling
of `MENU` to the next loop iteration.

Note also that the key presses are checked with tests of the form
`if (key == SOME_VALUE)`, which means there is no need for an extra
`if (key)` to test whether there was an actual key press.

[state diagram]: https://en.wikipedia.org/wiki/State_diagram
[1]: https://i.stack.imgur.com/eloFi.png


message:
Can Bluetooth HC-05 Module detect other modules and relay data back to phone?

I want the following to happen:

1. The HC-05 is paired to a phone. The module is called "Amy". The module is worn, say, as a wristband by a person.
2. Amy passes another wristband-with-HC-05-module called "Bob".
3. Amy inquires about Bob, and if the RSSI signal received is strong, it relays the name "Bob" to the phone which will somehow store the information in an app.
4. The HC-05 will pass many other modules, each with different usernames. A list of names will be stored by the phone app.
5. All other HC-05 modules, i.e. Bob and co. , would be doing the same thing with their own phones.

How feasible is this?

body: Correction - BLE devices give off RSSI, but not Bluetooth. BLE devices can be used as iBeacons. I have settled on the HM-19 Bluetooth 5.0 module. A phone acts as an iBeacon scanner.


message:
Arduino Yun receives UDP packets but prints them with gibberish

Arduino Yun is set to receive UDP packets. It receives those data with some gibberish.

How is all set up: Arduino Yun (acts as a server) is connected through Ethernet to a PC which is (through WiFi) connected to the router. Another PC (acts as client), is also connected to the router (through Wifi).

Client uses netcat to connect to Arduino Yun. I write something and press enter. The packets are received by the Arduino Yun with some gibberish. For example, I write "test" and press enter, but this is what I receive on the Arduino Yun:
[![enter image description here][1]][1]

Sometimes gibberish characters are different, but always exist. This is what Wireshark monitors when I send the "test" packet (with netcat) to my Arduino Yun:
[![enter image description here][2]][2]

It shows that indeed I send only "test", so the gibberish is created on the Arduino side, I suppose.

This is my sketch (not the entire code, but the important part):

    void loop() {
      int udp_received = Udp.parsePacket();
      if (udp_received) {
        char udp_buffer[16];
        udp_buffer[15] = '\0';
        Udp.read(udp_buffer, 15);
        Serial.println(udp_buffer);
      }
    }

I use BridgeUdp.h
Any insights appreciated.

  [1]: https://i.stack.imgur.com/1MZe9.png
  [2]: https://i.stack.imgur.com/vEc3Y.jpg

body:
You are receiving a small packet of about 5 or 6 characters (depending on your line ending). That is being received into a 16 byte buffer which has contents unknown.  So the first 5 or 6 bytes of the array have valid data in it. The rest is whatever was already in there.

You need to use the return value of `Udp.parsePacket()` to tell you how many of the bytes in your buffer are actually valid received bytes and only print those.

The simplest way:

    Serial.write(udp_buffer, udp_received);


body:
You send only 5 or 6 characters "test\r\n". the rest is random memory content.

The return value of [parsePacket][1] should be the count of received characters, but [the implementation in BridgeUdp][2] is wrong and returns always 1 on success.

You you can use `BridgeUdp.available()` to get the count.

```cpp
void loop() {
  if (Udp.parsePacket()) {
    int udp_received = Udp.available();
    char udp_buffer[16];
    Udp.read(udp_buffer, udp_received);
    udp_buffer[udp_received] = '\0';
    Serial.println(udp_buffer);
  }
}
```

  [1]: https://www.arduino.cc/en/Reference/EthernetUDPParsePacket
  [2]: https://github.com/arduino-libraries/Bridge/blob/c185c2f2803a8b869b2b3d931e97a8000e55dbac/src/BridgeUdp.cpp#L105


message:
How do you remove an item from array arduino?

Is there a way that can change `{3, 5, 3, 6}` to `{3, 5, 6}` with a function? I checked all the arduino forums but they don't give the answer i need (just delete 1 item from an array with a function like `delete(myArray, 2)`).

body: In C++, arrays are fixed-length data structures. There is no way you could remove an item. You could replace it with an invalid item, though.


body:
There is no such concept in C. Arrays are a fixed size and that size can never be changed. You can't "delete" an entry. You can replace one with something else, and you can introduce the concept of a variable that says how many entries the array has, but you can't delete one.

So you *could*:

* Keep a count of how many entries are in the array
* Shuffle down all the entries one space so the unused one is at the end
* Decrement the count of entries

So in your example `{3, 5, 3, 6}` becomes `{3, 5, 6, 6}` and your "count" holds `3` to say the first three entries are valid and to ignore the last.

Alternatively you can introduce the concept of "end of array". C strings do this with the NULL character (0). Anything before that character is valid, and anything from that character onwards is ignored.  So say you nominated the value -1 to be "end of array" you could have, after again shuffling down the values: `{3, 5, 6, -1}`.

You could also have `-1` (or whatever you chose) indicating an "invalid" entry, so your array would be `{3, 5, -1, 6}` and you would ignore the `-1` entry in your code.


message:
Any limitation on array size in Arduino Mega 2560?

I am writing an Arduino code with 3 arrays.

Two of those are *double* and other one is *int*. Further first two arrays have nearly 420 elements **for each**.
Now I noticed that with more that 89 elements on 3rd array the program stall, and stuck executing. But with 89 or less number of element it runs with out an issue.

What would be the issue?

body:
A Mega has 8 KB of memory.

You are using:

- double (same as float on an Arduino, see [double][1]) , 4 bytes * 420 elements * 2 arrays = 3,360 bytes
- int (2 bytes) * 89 = 178 bytes

In total this is 3,538 bytes

This is about 50%, so I'm unsure what the 'rest' is.
You can take a look at the other related question that may show some answers (like using dynamic memory, memory gaps, or local/stack variables): https://arduino.stackexchange.com/questions/76619/what-are-the-traditional-ways-to-optimize-program-memory-usage/76620#76620

  [1]: https://www.arduino.cc/reference/en/language/variables/data-types/double/


message:
Joining several PIR sensors

I wish to use some PIR (HC-SR501) sensors and give some response if at least one of them detects human movements.

For simplicity I wish to use *only one input pin* in an Arduino UNO. My idea is to connect all the output wires into a single Arduino digital input. Should it work?

I am in doubt because the following two reasons:

- The sensors must be far away from each other (about 5 sensors partially covering an area of about 200 m^2). That implies that wires are long and I do not know if this can have some adverse effect.
- I do not know if it is bad to supply the 3.5V of some sensor that is currently detecting movement to the output of the sensors that are not detecting anything.

Thanks in advance

body:
The BISS0001 that your unit uses provides an "active high" output. To connect multiple devices together you just need to "OR" the signals.

There's many ways of doing that.

The simplest method is the "wired OR" circuit, which just involves one pulldown resistor plus one diode per device:

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

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

<!-- End schematic -->

You could also use a multiple-input OR gate chip. You can get these in 2- (74HC32), 3- (74HC4075), 4- (74HC4072) input versions.


message:
ESP8266 CCLOCK Odd behavior

I'm trying to write some extremely fast code for the ESP8266, so I'm trying to figure out how to time things.  I've discovered `CCLOCK`, a register that reflects the number of clock cycles since startup. ([https://github.com/esp8266/Arduino/issues/4632#issuecomment-380632906][1], and other references.) In testing it out, though, I've encountered some weird behavior.  Consider the following code:

```
static inline volatile uint32_t asm_ccount(void) {
    uint32_t r;
    asm volatile ("rsr %0, ccount" : "=r"(r));
    return r;
}

char outgoingPacket[4];

...

void loop() {

  // ... some stuff ...

  uint32_t startTime = asm_ccount();
  uint32_t stopTime = asm_ccount();
  uint32_t elapsed = stopTime-startTime;

  outgoingPacket[0] = (elapsed >> 24) & 0xff;
  outgoingPacket[1] = (elapsed >> 16) & 0xff;
  outgoingPacket[2] = (elapsed >> 8) & 0xff;
  outgoingPacket[3] = elapsed & 0xff;
  Udp.beginPacket(targetUdpIp, targetUdpPort);
  Udp.write(outgoingPacket, 4);
  Udp.endPacket();
}
```

(On my computer, I have basically the following Java code running to receive these messages:)

```
    while (true) {
      DatagramPacket packet = new DatagramPacket(buf, buf.length);
      socket.receive(packet);

      byte[] data = packet.getData();
      StringBuilder sb1 = new StringBuilder();
      StringBuilder sb2 = new StringBuilder();
      for (int i = 0; i < packet.getLength(); i++) {
        sb1.append(String.format("%8s", Integer.toString(((int) data[i]) & 0xFF, 2)).replace(' ', '0'));
        sb2.append(String.format("%2s", Integer.toString(((int) data[i]) & 0xFF, 16)).replace(' ', '0'));
      }
      System.out.println(sb1 + " " + Integer.parseInt(sb2.toString(), 16));
    }
```

(Yes, it's a little hacky, I know, but the results have seemed correct.)

Now, most of the time, the output looks like

```
00000000000000000000000000000001 1
00000000000000000000000000000001 1
00000000000000000000000000000001 1
00000000000000000000000000000001 1
00000000000000000000000000000001 1
00000000000000000000000000000001 1
```

But about 5 times in 77000, I'll get lines like

```
00000000000000000000000000000001 1
00000000000000000000000000000001 1
00000000000000000000000110101000 424
00000000000000000000000000000001 1
00000000000000000000000000000001 1
...
00000000000000000000000000000001 1
00000000000000000000000000000001 1
00000000000000000000010010100001 1185
00000000000000000000000000000001 1
00000000000000000000000000000001 1
...
00000000000000000000000000000001 1
00000000000000000000000000000001 1
00000000000000000000010001001100 1100
00000000000000000000000000000001 1
00000000000000000000000000000001 1
```

I ran the code for 1 minute 4 seconds, and got 3 counts of 424, 1 of 1100, and 1 of 1185.  It seems particularly odd that 424 would show up three times.

Given that, as far as I understand, the relevant lines of code (the two calls to `asm_ccount`) would have been compiled to a given set of instructions, I'd have expected it to take exactly the same number of cycles every time.

Why is this not happening?

Is it interrupts?  Something something caching?  Does that register not actually work as claimed or as I understand?  Have I done something dumb in the transmission or logging code?  Something else?

  [1]: https://github.com/esp8266/Arduino/issues/4632#issuecomment-380632906

body: You've got interrupts running and interrupting your code. Those take some cycles to run.


message:
74HC595 to 5v pin shuts down uno

I'm new to using the [SN74HC595][1] shift register, and trying to follow this tutorial: https://www.arduino.cc/en/tutorial/ShiftOut based on this configuration:

[![SN74HC595 IC pinout][2]][2]

When my arduino Uno R3 is plugged in by USB to my Windows-7 x64 PC, it works (in general etc.), but right when I attach pin 16 or pin 10 of the 74HC595  to the 5V pin on the Uno, as it says to do, the entire arduino shuts off and the computer no longer recognizes it, until I disconnect the jumper wire from pin 16 or 13, from the 5v pin on the Uno, then it starts up again

Also just tested, and the same thing happens when I try to connect any of the 74HC595  pins to the 5v Uno pin (after pin 8 of the 74HC595  is connected to the Uno's GND), the whole Uno shuts off and disconnects from the computer

Am I missing something here?

  [1]: https://www.ti.com/lit/ds/symlink/sn74hc595.pdf?ts=1594199103837&ref_url=https%3A%2F%2Fwww.google.com%2F
  [2]: https://i.stack.imgur.com/XFIph.png

body:
> **when I attach pin 16 or pin 10 of the 74HC595 to the 5V pin on the Uno ... the entire arduino shuts off**

This sort of thing usually happens to me when I have made a mistake in the wiring.

This is easy to do as the 595 needs a lot of connections in a small space and it is easy to make a mistake.

In your case it seems you have a wiring mistake that is pulling Vcc low and the ATmega328 IC etc can't run.

---

I would

- Re-check the orientation of the 595
- Re-check each wire paying particular attention to the ground wires, especially the one that pulls 595 OE to ground (it's pin 13 on the 595).
- If necessary, pull everything off the breadboard and start again with things in a completely different position (turn the IC's round etc) to make me re-think everything.

----

For fun, I set this up on a Uno clone. I made some mistakes in the wires linking the 595 to the Uno but careful inspection found the problem. I found it easy to mix up the pin-number on the 595 with that on the Uno. Using the same wire colours mentioned in the guide may help.

Here's it working

[![Uno clone with 595][1]][1]

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


message:
Node MCU Wifi connection problem

I'm trying to connect my nodeMCU to my WiFi network also i have provided ip address  but it keeps printing ........ it is not connecting to the network. Below is my code.

    #include <ESP8266WiFi.h>
    #include <ESP8266WebServer.h>

    // Configration Parameter for Access Poin
    char * ssid_ap = "";
    char * password_ap = "";
    IPAddress ip(192, 168, 1, 158);
    IPAddress gateway(192, 168, 1, 1);
    IPAddress subnet(255,255,255,0);

    // Set up the server object
    ESP8266WebServer server (80);

    // Keep track of sensor data that's going to be sent by the client
    float sensor_value = 0.0;

    void setup()
    {
      WiFi.mode(WIFI_AP);
      WiFi.softAPConfig(ip,gateway,subnet);
      WiFi.softAP(ssid_ap,password_ap);

      Serial.begin(115200);
      delay(10);
      Serial.println();
      Serial.println();
      Serial.print("Connecting to ");
      Serial.println(ssid_ap);

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

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

      server.begin();
      Serial.println("Server started");
      Serial.print("IP Address:");
      // Serial.print(WiFi.localIP());
      // Configure Server Router
      server.on("/",handleIndex); // use the top root path to report the last sensor value
      server.on("/update",handleUpdate);
      // server.begin();
    }

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

    }

    void handleIndex()
    {
      server.send(200,"text/plain",String(sensor_value)); //we'll need to refresh the page for getting the latest value

    }

    void handleUpdate()
    {
     sensor_value = server.arg("value").toFloat();
     Serial.println(sensor_value);
     server.send(200,"text/plain","Updated");

    }

body:
You are creating a SoftAP (in essence creating a separate Wifi network). In this configuration, the ESP8266 will not "connect" to anything so polling `WiFi.Status` for the `WL_CONNECTED` status is meaningless.

To see if the SoftAP instance was created successfully, you should look at the output of `WiFi.SoftAP()` when you create the SoftAP instance, which returns a boolean indicating success (`true`) or failure. Or you should see the SSID of your newly created access point appearing on your PC or phone.

I suggest you look at the ESP8266 examples included in the Arduino IDE when you install device support for the ESP8266 to get some ideas about what you can do with a SoftAP.


message:
Storing IR Sensor value not working

This is my first time working on Arduino for my project and I ran into an issue. I'm trying to make a very simple Vending Machine. Coin or any obstacle passes in front of the IR sensor and based on that, the user can either press button 1 or 2 and based on that motor 1 or 2 would run respectively.\
The overall logic works exactly how I want it to, the issue I'm facing is that the variable (```sensorStatus```) storing the IR sensor value isn't working correctly. Whether anything passes in front of it or not, it lets me press the buttons anyways and the motor starts working.
```
void loop() {

  int sensorStatus;

  //this is where im having the issue
  if (digitalRead(inSensor) == LOW) sensorStatus = LOW;

  if(sensorStatus == LOW) {
      buttonStatus1 = digitalRead(inButton1);

      if(buttonStatus1 == HIGH) {
        digitalWrite(relayControl1_1, LOW);
      } else {
        digitalWrite(relayControl1_1, HIGH);
      }

      buttonStatus2 = digitalRead(inButton2);

      if(buttonStatus2 == HIGH) {
        digitalWrite(relayControl2_1, LOW);
      } else {
        digitalWrite(relayControl2_1, HIGH);
      }

      sensorStatus = HIGH;
   }
}
```
If I don't use this logic and store the value of the sensor directly into the variable (```sensorStatus```), the whole program seems to be working till I have an obstacle in front of the sensor continuously. I don't want this to happen, I want it to work in such a way that once an obstacle passes in front of the sensor it keeps the value (even after the obstacle is gone) until a button is pressed and after that, it gets rid of the value to repeat the process once again. It seems to be a code logic issue but I can't seem to figure out the logic behind it.

**My Complete Source Code:**
```
const int relayControl1_1 = 13; // relay 1 of 1 (input 1)
const int relayControl1_2 = 12; // relay 1 of 2 (input 2)
const int relayControl2_1 = 11; // relay 2 of 1 (input 3)
const int relayControl2_2 = 10; // relay 2 of 2 (input 4)

const int inButton1 = 9; //input button 1
const int inButton2 = 8; //input button 2

int buttonStatus1 = 0;
int buttonStatus2 = 0;

const int inSensor = 7;

void setup() {
  Serial.begin(9600);
  pinMode(relayControl1_1, OUTPUT);
  pinMode(relayControl1_2, OUTPUT);
  pinMode(relayControl2_1, OUTPUT);
  pinMode(relayControl2_2, OUTPUT);

  pinMode(inButton1, INPUT_PULLUP);
  pinMode(inButton2, INPUT_PULLUP);

  pinMode(inSensor, INPUT_PULLUP);

}

void loop() {

  int sensorStatus;

  //this is where im having the issue
  if (digitalRead(inSensor) == LOW) sensorStatus = LOW;

  if(sensorStatus == LOW) {
      buttonStatus1 = digitalRead(inButton1);

      if(buttonStatus1 == HIGH) {
        digitalWrite(relayControl1_1, LOW);
      } else {
        digitalWrite(relayControl1_1, HIGH);
      }

      buttonStatus2 = digitalRead(inButton2);

      if(buttonStatus2 == HIGH) {
        digitalWrite(relayControl2_1, LOW);
      } else {
        digitalWrite(relayControl2_1, HIGH);
      }

      sensorStatus = HIGH;
   }
}
```

body:
Thanks to the help from ```@Majenko♦``` I was able to fix the issue.

1 - ```int sensorStatus;``` should have been set to ```static int sensorStatus = HIGH;``` to make the program remember the value of the sensor.

2 - ```sensorStatus = HIGH;``` should have been right after ```digitalWrite(relayControl1_1, HIGH);``` in the ```buttonStatus``` conditional else part to make the program set the ```sensorStatus``` back to HIGH correctly.

3 - Unrelated to the question posted, doing the above steps made the program run the motors continuously unless they were stopped by an obstacle from the IR sensor. This was fixed by adding ```delay(2000); digitalWrite(relayControl1_1, LOW);``` after the ```sensorStatus = HIGH;``` mentioned in the 2nd step.

**Source Code after fixing:**
```const int relayControl1_1 = 13; // relay 1 of 1 (input 1)
const int relayControl1_2 = 12; // relay 1 of 2 (input 2)
const int relayControl2_1 = 11; // relay 2 of 1 (input 3)
const int relayControl2_2 = 10; // relay 2 of 2 (input 4)

const int inButton1 = 9; //input button 1
const int inButton2 = 8; //input button 2

int buttonStatus1 = 0;
int buttonStatus2 = 0;

const int inSensor = 7;

void setup() {
  Serial.begin(9600);
  pinMode(relayControl1_1, OUTPUT);
  pinMode(relayControl1_2, OUTPUT);
  pinMode(relayControl2_1, OUTPUT);
  pinMode(relayControl2_2, OUTPUT);

  pinMode(inButton1, INPUT_PULLUP);
  pinMode(inButton2, INPUT_PULLUP);

  pinMode(inSensor, INPUT_PULLUP);

}

void loop() {

  static int sensorStatus = HIGH;

  if (digitalRead(inSensor) == LOW) {
    sensorStatus = LOW;
  }

  if(sensorStatus == LOW) {
      buttonStatus1 = digitalRead(inButton1);

      if(buttonStatus1 == HIGH) {
        digitalWrite(relayControl1_1, LOW);
      } else {
        digitalWrite(relayControl1_1, HIGH);
        sensorStatus = HIGH;
        delay(2000);
        digitalWrite(relayControl1_1, LOW);
      }

      buttonStatus2 = digitalRead(inButton2);

      if(buttonStatus2 == HIGH) {
        digitalWrite(relayControl2_1, LOW);
      } else {
        digitalWrite(relayControl2_1, HIGH);
        sensorStatus = HIGH;
        delay(2000);
        digitalWrite(relayControl2_1, LOW);
      }
   }
}
```


message:
Char buffer for serial input: char str[2] vs char* str = (char*) malloc(2)

I am using software serials on my Arduino nano to read data from my esp01 in functionality testing for the software serial. I simply make the esp01 to send a string "OK" to an Arduino's software rx serial port (in this case pin 9) , and then the Arduino prints it on the monitor via its hardware serial (USB).

I've found that when I allocate space for the string in Arduino using `char str[2]`, the message seems to be correct. However, with `char* str = (char*)malloc(2)`, there appear to be an unkown character tai
ling the string "OK"

Below is the code I use

```
#include<SoftwareSerial.h>

SoftwareSerial s(9,10);
void setup() {
  pinMode(2,OUTPUT);
  Serial.begin(9600);
  s.begin(9600);      // link to esp01
}

void loop() {

  if(s.available() > 0){
    char txt[2];
    int indx = 0;

   // read input
    while(s.available() > 0 && indx <=SIZE-1){
        char buff;
        buff=  s.read();
        txt[indx] =  buff;
        Serial.println(indx);
        indx++;

    }
   // bink an LED for debugging
   if((String)txt == "OK"){
    digitalWrite(2,HIGH);
    delay(500);
    digitalWrite(2,LOW);
    delay(500);
   }

   //reset index
   if(indx ==2){

     Serial.println(txt);
     Serial.print("Size of string:");
     Serial.println(sizeof(txt));
    indx = 0;
   }
  } // if(s.available())

}
```
here is the print-out of the serial monitor

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

That tailing square is the myster for me.

Any help would be grateful!!

Boris

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

body:
As others have pointed out, C strings are null-terminated. So to hold 2 characters of content you need a 3-byte array. Your code that reads the chacters into the buffer also needs to be changed. (That code isn't adding the required terminating null.)

You should probably rewrite your code to use the `strncat()` function.


body:
First, a few general notes:

* The difference between `char str[2]` and
  `char* str = (char*) malloc(2)` is irrelevant to you problem. It
  changes the place where the array is stored, the meaning of
  `sizeof str`, and `malloc()` will blow up your RAM if you call it
  repeatedly and forget to `free()`.
* In your code, `sizeof(txt)` is the constant `2`: the actual size in
  bytes of the array `txt`, irrespective of how much relevant data it
  holds.
* You want `txt` and `indx`to remember their contents across calls to
  `loop()`. You should either make them global or qualify them as
  `static`.
* Avoid the `String` class if at all possible. Here, since you use it
  only to compare two strings, you can use the traditional
  [`strcmp()`][strcmp] function instead.

Now, the bulk of my answer is just about expanding on what has already
been said about properly terminating strings.

A string is a variable-length list of characters. Whenever you are
dealing with a list that has a variable length, you need to somehow keep
track of this length. There are two common ways to do so:

1. either you store the length in a variable,
2. or you put a [sentinel value][] (a value that would be invalid within
   the list) after the last element to mark the end of the list.

Both methods are valid, and I am going to illustrate both of them below.
However, in the case of strings, the C++ language uses method 2,
with the ASCII “NUL” character (numeric value 0) as a sentinel.

**Method 1**:

```cpp
void loop() {
  static char txt[2];
  static size_t indx = 0;

  while (s.available()) {
    // read input
    char c = s.read();
    txt[indx++] = c;

    // report
    Serial.print("Received: '");
    Serial.print(c);
    Serial.print("', string: \"");
    Serial.write(txt, indx);
    Serial.print("\", size: ");
    Serial.println(indx);
    if (indx == 2 && memcmp(txt, "OK", 2) == 0) {
      Serial.println("Correct message");
    }

    // reset index
    if (indx >= sizeof txt) {
      indx = 0;
    }
  } // if(s.available())
}
```

Some things to note:

* The `indx` variable holds the length of the string. It also happens to
  be the index of the next available cell in the `txt` array, if any.
* The string is printed using the
  `write(const char *buffer, size_t size)` method, which accepts a size
  as a second argument. Unlike `print(const char *)`, it doesn't depend
  on the string being NUL-terminated.
* In order to check that we received “OK”, we have to check for both the
  correct length (`indx == 2`) and correct contents. The contents is
  checked using the `memcmp()` function, which can compare arbitrary
  byte arrays and, again, does not depend on NUL-termination.
* An important loop invariant here is `idx < sizeof txt`. It is true at
  initialization and is restored by the “reset index” section at the end
  of the loop. The “read input” section depends on this invariant to not
  overflow the buffer.

**Method 2**:

```cpp
void loop() {
  static char txt[3];
  static size_t indx = 0;

  while (s.available()) {
    // read input
    char c = s.read();
    txt[indx++] = c;
    txt[indx] = '\0';

    // report
    Serial.print("Received: '");
    Serial.print(c);
    Serial.print("', string: \"");
    Serial.print(txt);
    Serial.print("\", size: ");
    Serial.println(indx);
    if (strcmp(txt, "OK") == 0) {
      Serial.println("Correct message");
    }

    // reset index
    if (indx >= sizeof txt - 1) {
      indx = 0;
      txt[indx] = '\0';
    }
  } // if(s.available())
}
```

Again, some notes:

* This is actually an hybrid of methods 1 and 2, as the `indx` variable
  is still used to keep track of where to insert the next incoming
  character. This just happens to be more convenient and efficient than
  putting that character into its own length-1 string and using
  `strcat()`.
* The array is now one cell longer, to make room for the terminating
  NUL.
* There is another loop invariant now: correct string termination
  (`txt[indx] == '\0'`). This invariant has to be enforced both on
  reading and on resetting.
* The string being NUL-terminated, it can now be printed with `print()`
  and compared with `strcmp()`. The string literal `"OK"` is guaranteed
  to be NUL-terminated by the compiler.

This second method is generally safer because there are a lot of
functions and methods in Arduino and C++ that expect strings to be
NUL-terminated. If your strings are not, you have to be extra careful to
not use any of these string-oriented functions.

[strcmp]: https://www.nongnu.org/avr-libc/user-manual/group__avr__string.html#ga46f3cbd2de457c0fb340a1f379fc33ba
[sentinel value]: https://en.wikipedia.org/wiki/Sentinel_value


message:
ESP8266 malloc/calloc-related crashes ("segfaults")

This is sort of the continuation of [this problem](https://arduino.stackexchange.com/questions/76771/esp8266-constantly-crashes-in-malloc-related-check-poison-neighborsunsigned-sh). After getting hints that the problem I had were related to bad memory, I checked all of my heap-allocating code again and found a malloc that didn't allocate enough memory for an array. After fixing that and fiddling around with calloc, which may be safer for array-related stuff, I think I exposed the actual programming errors themselves. The crash message I get now is:

```
No poison after block at: 0x3fff0fb8, actual data: 0x84 0xf 0xff 0x3f

User exception (panic/abort/assert)
Panic umm_malloc.cpp:422 umm_malloc_core
```

which sounds to me like some sort of ESP segfault. The code where this happens according to the stack trace is the following:

```c++
Menu* createMenuStructure(ace_time::TimeZone* mainTZ) {
  // create an array of all clock faces, i.e. a pointer to an array of function pointers
  void (**allClockFaces)(T_DISPLAY*, ace_time::ZonedDateTime*);
  // funkiest malloc in the world; undefined behavior? I hope not.
  allClockFaces = (void (**)(T_DISPLAY*, ace_time::ZonedDateTime*)) calloc(DESIGN_MENU_SIZE, sizeof(*allClockFaces));
  // initialize array
  allClockFaces[0] = &basicDigitalCF;
  allClockFaces[1] = &digitalWithSecondsCF;
  allClockFaces[2] = &basicAnalogCF;
  allClockFaces[3] = &binaryCF;
  allClockFaces[4] = &fullDayBinaryCF;
  ClockFaceSelectMenu* cfMenu = (ClockFaceSelectMenu*) malloc(sizeof(ClockFaceSelectMenu));
  cfMenu = new ClockFaceSelectMenu((char**)design_menu, (size_t)DESIGN_MENU_SIZE, allClockFaces);

  // time zone select menu
  TimeZoneSelectMenu* tzMenu = (TimeZoneSelectMenu*) malloc(sizeof(TimeZoneSelectMenu));
  tzMenu = new TimeZoneSelectMenu();

  Menu** allMenus = (Menu**) calloc(3, sizeof(*allMenus));
  // initialize first layer of sub menus
  allMenus[0] = cfMenu;
  allMenus[3] = tzMenu;

  OptionsMenu* mainMenu = (OptionsMenu*) malloc(sizeof(OptionsMenu));
  mainMenu = new OptionsMenu((char**)main_menu, (size_t)MAIN_MENU_SIZE, allMenus);

  // for now, manually set the sub menu's parent to the main menu. When all menus are finished, the main menu will do this automatically
  allMenus[0]->parent = mainMenu;
  allMenus[3]->parent = mainMenu;

  ClockMenu* clk = (ClockMenu*) malloc(sizeof(ClockMenu));
  // timeClient is a global NTPClient variable
  clk = new ClockMenu(&timeClient, mainTZ, (Menu*)mainMenu);

  return clk;
}
```

All names containing `Menu` are classes derived from that base class, and the top couple of lines allocate an array of function pointers. And just to be clear: This code was working perfectly fine for the last several days of development until I made some changes to the SD card functionality that caused the constant crashes.

I am not very used to working in manual memory management. Is this way of allocating appropriate, and if so, correct? What am I doing wrong, or does the error lie somewhere else in the (~1500sloc) project?

Edit: Although the issue is already solved, thanks to the approved answer, I wanted to clarify that the constants used in the array allocation are all correct and correspond to the string array's length. E.g. main_menu is a string array of length 5 and MAIN_MENU_SIZE is a constant defined right next to the array definition that is also defined to 5. This is of course necessary as C arrays have no way (that I know of) of finding the length of complex pointer arrays such as these.

body:
You wrote:
> ```cpp
> // funkiest malloc in the world
> ```

Funky, indeed. ;-) I kind of like its twisted beauty, but not everyone
does. Some may urge you to `typedef` that function type.

> ```cpp
> allClockFaces[4] = &fullDayBinaryCF;
> ```

Are you sure `DESIGN_MENU_SIZE` is strictly larger than 4? Maybe an
`assert()` would be good to use here.

> ```cpp
> ClockFaceSelectMenu* cfMenu = (ClockFaceSelectMenu*) malloc(...);
> cfMenu = new ClockFaceSelectMenu(...);
> ```

You are assigning a value to `cfMenu` twice in a row, which means the
value assigned first is lost. This is a memory leak. You do not need
`malloc()` here, as `new` takes care of the memory allocation prior to
initializing the object. This error is repeated several times in this
function.

> ```cpp
> allMenus[3] = tzMenu;
> ```

`allMenus` has length 3: valid indices range from 0 to 2. This is an
out-of-bounds array access, and the likely cause of the errors you see.


message:
ESP8266 NodeMCU 3v3 current for fingerprint sensor

From what i see that 3.3Vpin provide 3.3V and 400mA. The fingerprint module i use is AS608. Connecting the fingerprint module power pin to 3.3V of the nodemcu. From the datasheet it only can handle 3.3VDC, operating current<60mA and peak current at <70mA. Do i need to add a resistor to take the current away. Since last time i use another fingerprint module which is R307 connecting to Vin of the nodemcu and now it not working anymore?

body:
**Be careful using Vin on the NodeMCU for 3.3V devices!** If you are powering it by 5V USB power, this Vin pin will probably have something like 4.76V on that pin. The [circuit diagram](https://github.com/nodemcu/nodemcu-devkit-v1.0/blob/master/NODEMCU_DEVKIT_V1.0.PDF) shows that Vusb is connected to Vin with just a schottky diode, which drops the current about .34 volts and provides some noise isolation from the Vusb supply. If you connected a 3.3V device to this pin at 4.76V, you may have damaged your component.

You'd have to check the datasheet or documentation for the fingerprint module, but it sounds like the fingerprint module will only draw 60-70mA when it's given 3.3 volts. Datasheets often provide application examples and may specify that you do need additional resistors, capacitors, etc. The refrain in cases like this is always *read the datasheet*.

If your NodeMCU datasheet says it can provide 400mA then it should certainly be able to provide the 60-70mA that the fingerprint sensor needs. I've powered an ESP8266 by connecting its Vin pin to the Vin of another NodeMCU and they seem fairly happy together, although there tends to be quite a bit of noise on the Vin pin.


body:
Dont mix your pins. and use 3V pin (NOT Vin), that should be able to output it.
AMS1117 used in most nodeMCU's I have seen can reasonably provide 800mA medium lenght periods with voltage drop of 8-9 Volts.
The MCU can reasonably take 100mA-350mA. This varies based on the amount of the work it does, running core frequency (I am not advanced enough to mess with that yet), Whether its communicating over wifi and how strong does it have to make the signal (influenced by distence, other wifi devices around). This leaves you with about 450mA to play about. As designers were responsible a good designers 50mA was cut as a margin.

Because of how voltage regulators work, the more voltage you are droping the lover current you can sustain. (worth researching heat decipation) Next is the matter of wether the device is enclosed etc.
So 60mA is OK for most nodeMCU as extra load.
If you reach few hundred mA and are really concerned you can reasonably control consumption simply by controling whether the nodeMCU is sending any majour communication over or if it does encryption (demanding tasks) etc.