message:
DS18B20 oneWire analog vs digital

I just discovered that the Dallas DS18B20 can be read from either digital or analog pins. I never thought analog was an option until I stumbled across an article searching for another issue.
So now I'm wondering, if I have a dozen DS18B20's on about 20 feet of wire with a 4.7k resistor, what would be the better option for reading? Digital or Analog?

body:
To use multiple DS18B20 devices on the same bus

1/ First get the address of each DS18B20 device by attaching it alone to the Arduino, and calling the `discoverOneWireDevices();` function. Write down the address. This is a set of 8 hexadecimal digits, eg 0x28, 0x13, 0x97, 0x9A, 0x0A, 0x00, 0x00, 0x6A

2/ Hard-code the address of each device, e.g. `#define TEMP_SENSOR1 {0x28, 0x13, 0x97, 0x9A, 0x0A, 0x00, 0x00, 0x6A}` before the call to the setup, and define the corresponding device address: `DeviceAddress tempSensor1 = TEMP_SENSOR1;`

3/ each time you launch a command to a DS18B20, specify to which you are speaking, eg `temperature1 = sensors.getTempC(tempSensor1);`


sender: user

sender: assistant

body:
Analog is not an option as the 1-wire is a digital communication bus, however using an analog pin is on many processors to do this is possible. This is achieved on many of the processors because the analog pin can be configured and used for digital I/O.  Arduinos such as the UNO can accomplish this because of the processor they use. Note not all microprocessors are designed use an analog pin for digital I/O.

There is an application note by AMD called "1-Wire Search Algorithm", https://www.analog.com/en/app-notes/1wire-search-algorithm.html. By using this process you can read all of the sensors independently without knowledge of there addresses. Using this method will not guarantee which sensor you are reading but the sequence will repeat and you can simply replace a sensor but the order will probably change. This allows you to change sensors etc when there are not many sensors involved. Here are some links to better explain this.

https://docs.arduino.cc/learn/communication/one-wire

https://www.arduino.cc/reference/en/libraries/onewire/


message:
Whether my board analog pins shorted? I see same input on all

I am puzzled. I just connected 3.3 V input to the Analog pin A5 of the Arduino UNO. On the script, I am reading all the input pins. Surprizingly, all the pins are giving voltage as that of A5 pin. This made me think whether all of them shorted?

code:

    int a0_analogPin = A0;
    float a0_val = 0;
    int a1_analogPin = A1;
    float a1_val = 0;
    int a2_analogPin = A2;
    float a2_val = 0;
    int a3_analogPin = A3;
    float a3_val = 0;
    int a4_analogPin = A4;
    float a4_val = 0;
    int a5_analogPin = A5;
    float a5_val = 0;

    void setup() {
      Serial.begin(9600);           //  setup serial
      pinMode(a0_analogPin,INPUT);
      pinMode(a1_analogPin,INPUT);
      pinMode(a2_analogPin,INPUT);
      pinMode(a3_analogPin,INPUT);
      pinMode(a4_analogPin,INPUT);
      pinMode(a5_analogPin,INPUT);
      Serial.println("A0_val,A1_val,A2_val,A3_val,A4_val,A5_val");
    }

    void loop() {
      a0_val = analogRead(a0_analogPin)*5.0/1023.0;  // read the input pin
      Serial.print(a0_val);          // debug value
      Serial.print(",");
      a1_val = analogRead(a1_analogPin)*5.0/1023.0;  // read the input pin
      Serial.print(a1_val);
      Serial.print(",");
      a2_val = analogRead(a2_analogPin)*5.0/1023.0;  // read the input pin
      Serial.print(a2_val);
      Serial.print(",");
      a3_val = analogRead(a3_analogPin)*5.0/1023.0;  // read the input pin
      Serial.print(a3_val);
      Serial.print(",");
      a4_val = analogRead(a4_analogPin)*5.0/1023.0;  // read the input pin
      Serial.print(a4_val);
      Serial.print(",");
      a5_val = analogRead(a5_analogPin)*5.0/1023.0;  // read the input pin
      Serial.println(a5_val);
    }

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

Serial Monitor:
[![enter image description here][2]][2]

  [1]: https://i.stack.imgur.com/mStO4.jpg
  [2]: https://i.stack.imgur.com/8jiBs.png

body:
Most of your analog pins are not connected to anything. In electrical engineering, that's called "floating". It means they have no reference to anything and thus their value can be anything.

Basically their value is determined by static electricity. Moving your hands near the pins or moving them away may be enough to change the value you read.

It could be that your "oscilloscope view" actually shows that nicely. One pin gets the voltage immediately (`value 6`) and through static electricity, the other pins slowly take that value as well (`value 1`, `value 2`, ...). Probably the steepest curve of those is closest to the pin that is high and the most shallow curve is furthest away. Your observations may vary depending on humidity and temperature, since that makes static electricity spread faster or slower.

Solution: don't let your pins float. Connect them to a defined value, e.g. ground if you want them to have a predictable value.


body:
You are seeing crosstalk between the analog input channels. In the
[datasheet of the microcontroller][datasheet] you can see the analog
input circuitry. See the capacitor labeled “CS/H”? This is
the “sample and hold” capacitor. Its job is to hold the voltage being
read while the ADC performs the conversion. When you measure channel A5,
you are charging this capacitor to 3.3 V. Then, when you switch to
a floating input, the capacitor has no path to discharge, and you end
up measuring the same voltage.

Actually, you do not measure exactly the same voltage. The reason is
that each input pin has a parasitic capacitance. When you switch from A5
to A0, the charge in CS/H splits between this capacitor and
the stray capacitance of the pin A0. Then, you switch to A1 and the
remaining charge is split between CS/H and the stray
capacitance of A1, and so on. Eventually, when you come back to A5, you
charge again CS/H to the full 3.3 V and the cycle starts
again. The net effect is that you are progressively moving charges
between the successive pins. This is why the curves look like
exponential relaxations, where each successive pin charges more slowly
than the preceding one.

The solution, as already written in other answers, is to avoid leaving
the pin floating. The datasheet recommends making sure the connected
source has an impedance no larger than 10 kΩ.

[datasheet]: https://ww1.microchip.com/downloads/aemDocuments/documents/MCU08/ProductDocuments/DataSheets/ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061B.pdf#G3.1738797


message:
Programming barebones ATMega328 with external programmer and no bootloader

I have created a circuit with a barebones ATMega328.
I also have an external programmer (Sparkfun's Pocket AVR Programmer)...

Now I want to program a particular sketch... When uploading a sketch, do i also have to flash the bootloader beforehand?

Or is it possible to upload the sketch directly to the microcontroller without a bootloader?

body:
The Pocket AVR Programmer is just a standard ISP programmer, meaning it uses the ISP protocol built into the hardware of the microcontroller to write data to flash and EEPROM. That is also the way, that the bootloader got onto the microcontroller in the first place.

The bootloader of the Arduino on the other hand is a small program to communicate over Serial (or USB depending on the Arduino board) and then write the data to flash and EEPROM.

So: **No, you don't need the bootloader, if you want to use the ISP programmer.** Select your programmer in the corresponding menu of the Arduino IDE to use it.

Though keep in mind, that you won't be able to upload a new sketch via Serial/USB without the bootloader. You can always use the ISP programmer to again write the bootloader to the microcontroller.


message:
NodeMcu V3 & BMe280 -> Temperature, Humidity, Pressure: value nan

I've just started playing around with a NodeMcu V3 and a [BME280 sensor][1].

[![enter image description here][2]][2]

wiring

    VCC -> 3.3V
    GND -> GND
    SCL -> D1 (GPIO5)
    SDA -> D2 (GPIO4)

I've tried this sketch /  I2C scanner: it finds the BME280 at 0x76

    #include <Wire.h>

    // Set I2C bus to use: Wire, Wire1, etc.
    #define WIRE Wire

    void setup() {
      WIRE.begin();

      Serial.begin(9600);
      while (!Serial)
         delay(10);
      Serial.println("\nI2C Scanner");
    }

    void loop() {
      byte error, address;
      int nDevices;

      Serial.println("Scanning...");

      nDevices = 0;
      for(address = 1; address < 127; address++ )
      {
        // The i2c_scanner uses the return value of
        // the Write.endTransmisstion to see if
        // a device did acknowledge to the address.
        WIRE.beginTransmission(address);
        error = WIRE.endTransmission();

        if (error == 0)
        {
          Serial.print("I2C device found at address 0x");
          if (address<16)
            Serial.print("0");
          Serial.print(address,HEX);
          Serial.println("  !");

          nDevices++;
        }
        else if (error==4)
        {
          Serial.print("Unknown error at address 0x");
          if (address<16)
            Serial.print("0");
          Serial.println(address,HEX);
        }
      }
      if (nDevices == 0)
        Serial.println("No I2C devices found\n");
      else
        Serial.println("done\n");

      delay(5000);           // wait 5 seconds for next scan
    }

Then I've tried library BMx280I2C into this sketch:

    #include <Wire.h>
    #include <BMx280I2C.h>

    BMx280I2C bmx280(0x76);

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

      // Setup BMx280
      Wire.begin();
      bmx280.begin();
      bmx280.resetToDefaults();
      bmx280.writeOversamplingPressure(BMx280I2C::OSRS_P_x16);
      bmx280.writeOversamplingTemperature(BMx280I2C::OSRS_T_x16);
      bmx280.writeOversamplingHumidity(BMx280I2C::OSRS_H_x16);

    }

    void loop() {

      // T,P,H measurements
      bmx280.measure();

      do{
        delay(100);
        Serial.println("No value, yet!");
      } while (!bmx280.hasValue());

      Serial.print("Pressure ");
      Serial.println(bmx280.getPressure());

      Serial.print("Temperature ");
      Serial.println(bmx280.getTemperature());

      Serial.print("Humidity ");
      Serial.println(bmx280.getHumidity());

      delay(1000);

    }

the output is always and only:

>     -> No value, yet!
>     -> Pressure nan
>     -> Temperature nan
>     -> Humidity nan

Why? How can I understand the origin of the problem?Thanks!

  [1]: https://www.ebay.it/itm/173602844579?mkcid=16&mkevt=1&mkrid=711-127632-2357-0&ssspo=zP2vxbj4Rpe&sssrc=4429486&ssuid=P9XaWv98RhG&var=&widget_ver=artemis&media=COPY
  [2]: https://i.stack.imgur.com/t7Uqi.png

body:
Solved with [Adafruit library][1]

    #include <Wire.h>
    #include <Adafruit_Sensor.h>
    #include <Adafruit_BME280.h>

    #define SEALEVELPRESSURE_HPA (1013.25)

    Adafruit_BME280 bme;

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

      if (!bme.begin(0x76)) {
        Serial.println("Could not find a valid BME280 sensor, check wiring!");
        while (1);
      }
    }

    void loop() {
      Serial.print("Temperature = ");
      Serial.print(bme.readTemperature());
      Serial.println(" *C");

      Serial.print("Humidity = ");
      Serial.print(bme.readHumidity());
      Serial.println(" %");

      Serial.print("Pressure = ");
      Serial.print(bme.readPressure() / 100.0F);
      Serial.println(" hPa");

      Serial.print("Approx. Altitude = ");
      Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA));
      Serial.println(" m");

      Serial.println();

      delay(2000);
    }

  [1]: https://www.arduino.cc/reference/en/libraries/adafruit-bme280-library/


message:
How EEMEM maps the variables? (avr/eeprom.h)

I can store and restore my data with avr/eeprom.h if I don't change the sketch.

 1. I have a sketch that stores the data. After power cycle of the device the data are fine.
 2. If I change the sketch with Serial.print statements (I want to re-read the data on-screen) the sketch seeks the data in wrong addresses of EEPROM, although I can verify with another sketch that the data are fine.

More detailed: I store around 50 bytes, but I verified the location for only the 4 bytes variable. I can see that this variable is at the start of the EEPROM (address: 0). But the second sketch seeks the data on address 30. Not even close.

To my understanding avr/eeprom.h is more easy to use since you don't need to police the location of data. But it seems that if change (what?) in your sketch it seeks the data on other locations although on eeprom are fine.

In other words, it's like if I change the firmware (not the EEMEM variables / definitions!), that firmware seeks the data on different places.

I understood something wrong?

In my situation is better to use the arduino EEPROM.h with static location of EEPROM addresses?

Fun fact. Google Bard seems it got it completely wrong:
>What are the differences of avr/eeprom.h and EEPROM.h from arduino?

(Google Bard Answer)

>The avr/eeprom.h and EEPROM.h libraries in Arduino are both used to access the EEPROM memory on AVR microcontrollers. However, there are some key differences between the two libraries.
>avr/eeprom.h is a lower-level library that provides direct access to the EEPROM registers. This means that it can be used to access any location in the EEPROM, but it also requires more code and can be more error-prone.
>EEPROM.h is a higher-level library that provides a more user-friendly interface to the EEPROM. It only allows you to access addresses that are within the range of the EEPROM, but it is easier to use and less error-prone.
>In general, avr/eeprom.h should only be used if you need to access specific locations in the EEPROM that are not within the range of EEPROM.h. Otherwise, EEPROM.h is the preferred library to use.

Edit: avr-objdump of eeprom section

| Prints on Sketch | Without prints | Prints both on Library and Sketch |
|------------------|-------------------|----------------|
|00810000 <eeprom_lw_dev_nonce>:| 00810000 <eeprom_lw_f_nwk_s_int_key>:| 00810000 <eeprom_lw_dev_addr>:|
|00810002 <eeprom_lw_f_nwk_s_int_key>:| 00810010 <eeprom_lw_s_nwk_s_int_key>:| 00810004 <eeprom_lw_dev_nonce>:|
|00810012 <eeprom_lw_s_nwk_s_int_key>:| 00810020 <eeprom_lw_has_joined>:| 00810006 <eeprom_lw_f_nwk_s_int_key>:|
|00810022 <eeprom_lw_join_nonce>:| 00810021 <eeprom_lw_dev_nonce>:| 00810016 <eeprom_lw_s_nwk_s_int_key>:|
|00810026 <eeprom_lw_has_joined>:| 00810023 <eeprom_lw_join_nonce>:| 00810026 <eeprom_lw_nwk_s_enc_key>:|
|00810027 <eeprom_lw_tx_frame_counter>:| 00810027 <eeprom_lw_tx_frame_counter>:| 00810036 <eeprom_lw_app_s_key>:|
|00810029 <eeprom_lw_rx_frame_counter>:| 00810029 <eeprom_lw_nwk_s_enc_key>:| 00810046 <eeprom_lw_has_joined>:|
|0081002b <eeprom_lw_nwk_s_enc_key>:| 00810039 <eeprom_lw_rx_frame_counter>:| 00810047 <eeprom_lw_rx_frame_counter>:|
|0081003b <eeprom_lw_app_s_key>:| 0081003b <eeprom_lw_app_s_key>:| 00810049 <eeprom_lw_tx_frame_counter>:|
|0081004b <eeprom_lw_dev_addr>:| 0081004b <eeprom_lw_dev_addr>:| 0081004b <eeprom_lw_rx2_data_rate>:|
|0081004f <eeprom_lw_rx2_data_rate>:| 0081004f <eeprom_lw_rx1_delay>:| 0081004c <eeprom_lw_rx1_data_rate_offset>:|
|00810050 <eeprom_lw_rx1_data_rate_offset>: |00810050 <eeprom_lw_rx2_data_rate>:| 0081004d <eeprom_lw_join_nonce>:|
|00810051 <eeprom_lw_rx1_delay>:| 00810051 <eeprom_lw_rx1_data_rate_offset>:| 00810051 <eeprom_lw_rx1_delay>:|

Image kept for historical reasons.

1st window: Serial.print(s) only in sketch.
2nd window: without Serial.print(s)
3rd window: Serial.print(s) both on sketch and library.
[![EEMEM from avr-objdump -D][1]][1]

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

body:
I managed to reproduce your issue with the simple sketch below:

```c++
#include <avr/eeprom.h>

EEMEM uint8_t int8_ee;
EEMEM uint16_t int16_ee;
EEMEM uint32_t int32_ee;
EEMEM char str_ee[40];

void show(const char *name, void *address)
{
    Serial.print(name);
    Serial.print(": ");
    Serial.println((uint16_t) address);
}

void setup() {
    Serial.begin(9600);
    show("int8_ee", &int8_ee);
#ifdef SWAP_PRINTING_VARS
    show("int32_ee", &int32_ee);
    show("int16_ee", &int16_ee);
#else
    show("int16_ee", &int16_ee);
    show("int32_ee", &int32_ee);
#endif
    show("str_ee", str_ee);
}

void loop(){}
```

As is, it prints:

    int8_ee: 46
    int16_ee: 44
    int32_ee: 40
    str_ee: 0

If I `#define SWAP_PRINTING_VARS`, it prints instead:

    int8_ee: 46
    int32_ee: 42
    int16_ee: 40
    str_ee: 0

I have no proper answer to your question. Although one may try to unveil
the linker's reasoning, I believe it is safer to just assume that the
way these variables are allocated is unpredictable, and unstable between
subsequent versions of the program.

For your specific issue, I suggest you allocate _only one_ variable to
EEMEM: put everything you need in a single `struct`, and allocate that
as a whole. I am quite confident it will always end at address zero.
This should be robust against changes in the program provided that, if
you ever add extra fields to that `struct`, you add them at the end.


body:
I wouldn't rely on the compiler necessarily allocating variables at any particular memory address, especially after what you posted. You can make a little include file that simplifies reading from/writing to EEPROM, as below:

<!-- language: lang-c++ -->

    #include <Arduino.h>  // for type definitions
    #include <EEPROM.h>

    template <typename T> unsigned int EEPROM_writeAnything (int ee, const T& value)
    {
        const byte* p = (const byte*)&value;
        unsigned int i;
        for (i = 0; i < sizeof(value); i++)
         EEPROM.write(ee++, *p++);
        return i;
    }

    template <typename T> unsigned int EEPROM_readAnything (int ee, T& value)
    {
        byte* p = (byte*)&value;
        unsigned int i;
        for (i = 0; i < sizeof(value); i++)
         *p++ = EEPROM.read(ee++);
        return i;
    }

Then you can do something like this:

<!-- language: lang-c++ -->

    int someData;  // declare a local variable

    ...

    EEPROM_readAnything (0, someData);  // read into it, from address zero in EEPROM

    ...

    someData++;
    EEPROM_writeAnything (0, someData);  // write it back out, to address zero

The library above uses templates to manage any size data, so you can write or write ints, arrays, etc. One possibility would be to make a struct and read/write the whole thing every time. That way you don't need to keep track of offsets (the whole struct could be written to address 0).

---

Here's an example of doing that, using `offsetof` to manage the offsets of individual fields inside your overall struct, the thing that is stored in the EEPROM.

<!-- language: lang-c++ -->

    #include <EEPROMAnything.h>

    const long MAGIC_ID = 'Nick';

    // information in EEPROM
    typedef struct {
        unsigned long magic;   // to see if we initialised EEPROM
        unsigned long counter;
        char myName [30];
    }  myInformation;

    void setup() {
      Serial.begin (115200);
      Serial.println ("Starting ...");

      // see if EEPROM initialised

      unsigned long magicTest;
      EEPROM_readAnything (offsetof (myInformation, magic), magicTest);

      if (magicTest != MAGIC_ID)
        {
        Serial.println ("Initialising EEPROM");
        myInformation initStuff;
        initStuff.magic = MAGIC_ID;
        initStuff.counter = 0;
        strcpy (initStuff.myName, "Nick Gammon");
        EEPROM_writeAnything (0, initStuff); // write whole struct
        } // end of if not initialised

      // find counter
      unsigned long myCounter;
      EEPROM_readAnything (offsetof (myInformation, counter), myCounter);
      Serial.print ("Counter is ");
      Serial.println (myCounter);

      // find name
      char hisName [sizeof (myInformation().myName)];
      EEPROM_readAnything (offsetof (myInformation, myName), hisName);
      Serial.print ("Name is ");
      Serial.println (hisName);

      // add to counter
      myCounter++;

      // write counter back
      EEPROM_writeAnything (offsetof (myInformation, counter), myCounter); // write whole struct

      Serial.println ("Done.");

    } // end of setup

    void loop()
    {
      // whatever
    }   // end of loop


message:
Push button issues

I have been using https://wokwi.com/ to learn Arduino and I am having a problem that seems to be happening no matter what I do. I am trying to set up a push button and an LED. The end goal here is to set it up so that when I tap the push button down and release it that the LED blinks like a turn signal in a car. When I push it down and release it again, the LED should stop blinking. I have tried tons of different code, even using code copied and pasted directly from Arduino's website. What ends up happening is that the button is unreliable. Sometimes the button will click, other times it won't register. It is very bizarre behavior. I read about the bouncing effect but any code I put in to ignore bouncing doesn't seem to have any effect on the system. Why are push buttons so unreliable? I know in real life they aren't because I am able to type this using presumably push buttons on my keyboard. What am I doing wrong??

Here is an example. The push button is totally unpredictable. Why is it behaving like this?

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

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

    int state = 0;

    void setup()
    {
      pinMode(9, OUTPUT);
      pinMode(6, INPUT);
    }

    void loop()
    {
      if (digitalRead(6)) {
        state = !state;
      }
      digitalWrite(9, state);
    }

body:
You've got the button wired wrong.  Your resistor is inline with the signal going to the pin.  It should be going from the pin to 5V.  The button should be wired directly to the pin and ground.  Or you can use INPUT_PULLUP in pinMode instead of INPUT and eliminate the resistor entirely.

Your code should test for the button pin being LOW, not HIGH.  When you press the button it will read LOW.  When unpressed it will read HIGH.  This is the normal way that buttons are wired up.

Also note that your loop() function will repeat thousands of times per second.  As long as you still have your finger on the button it will keep cycling the state.  That means that every time you press the button, the state gets cycled a few tens of thousands of times and there's no real way of knowing which state it will be on when you finally get your finger off the button.

You should look at the "State Change Example" in the Arduino IDE.  It shows how to keep track of the previous state of the button so you can react once to each press.


message:
How does actually arduino measure voltage?

I am not interested into the AnalogRead() part, but rather on how he converts 5 or 2 V into a number between 0 and 1023. How does it practically do it to convert the voltage level into a number or into bits to then send to the processor? Thanks in advance

body:
The Arduino Uno is powered by an ATmega328P microcontroller. According
to [the datasheet][]:

> The ATmega48A/PA/88A/PA/168A/PA/328/P features a 10-bit successive
> approximation ADC.

On the next page, you can see the following schematic, where I have
highlighted the most essential parts of the converter. You can see the
DAC, the comparator, and the SAR data register.

[![Schematic of the ADC of the ATmega328P][1]][1]

If you want to get into the details of how this works, see the Wikipedia
article on [Successive-approximation ADC][w]. You may notice the
schematic at the top of that Wikipedia page is somewhat similar to the
one above.

[the datasheet]: https://ww1.microchip.com/downloads/aemDocuments/documents/MCU08/ProductDocuments/DataSheets/ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061B.pdf#G3.1738665
[w]: https://en.wikipedia.org/wiki/Successive-approximation_ADC
[1]: https://i.stack.imgur.com/r7qpu.png


body:
The ATmega328P features a 10-bit successive approximation ADC. The ADC is connected to an 8-channel Analog Multiplexer.

[![ADC schematic][1]][1]

First, an input is selected from the multiplexer on the left. This allows any of 8 input channels to be active at one time (but only one). These are: A0 to A5 on the Uno (some boards also have A6 and A7). There are also additional input channels (not shown) which also allows the selection of:

* The internal temperature sensor
* Ground
* Bandgap reference voltage

The input channel (multiplexer output) is connected to a "sample and hold" capacitor, as shown. Once an analog conversion starts the switch is opened after 1.5 ADC cycles (12 µs with the default prescaler of 128) so that the capacitor retains its current reading (ie. it holds it) so that the input voltage can now change without affecting the result. This would be useful for fast-changing signals, as the whole conversion can take 104 µs (depending on the prescaler).

To work out the voltage the logic applies the analog reference voltage (ARef) divided down by a DAC (digital-to-analog converter) under the control of the ADC logic. The output of the DAC is sent to the comparator which determines if the input voltage is higher or lower than the reference voltage, at its current divided state. For example, the high-order bit would be set or cleared by setting the DAC to divide the reference voltage by 2 (ie. 2.5V if ARef is 5V). If the input is higher than 2.5V then the high-order bit in the result is set. This takes one ADC cycle (8 µs at the default prescaler of 128 with a 16 MHz processor clock).

To get the next result bit the DAC would be set to the next step (ie. 0.25 of ARef or 0.75 of ARef depending on whether the first bit was set or not) and another comparison done. This process is repeated for all 10 bits.

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


message:
DS3231 Not Matching Up Time when Arduino is Turned Off

I am trying to make an LED clock using DS3231 to keep track of time, but for some reason, it's not keeping time when Arduino is turned off. I tried to disconnect the clock from a power source for 5 minutes, and when I powered it back on, the clock picks up the time it was displaying before powering off. I thought the battery I was using at first ran out, and so I replaced it with a new one, but the issue persist. Then I read that it could be that I am using the non-rechargeable one, and to fix this, I removed some resistors and diodes to turn off the charging function, but that also didn't fix the issue. At this point, I'm not sure if this is more on hardware or software issue that the clock is not keeping count of time when Arduino is turned off. It could be that the module I bought was the cheap knockoff, which doesn't function like it should, so I ordered a better one.

I'll the provide the snippet of codes I used:
```
#include <RTClib.h>
#include <Wire.h>

RTC_3231 rtc;

int hoursNow;
int minutesNow;
int secondsNow;

void setup() {
  Serial.begin(9600);
  Wire.begin();
  rtc.begin();
  rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
//  rtc.adjust(DateTime(2023, 6, 31, 14, 21, 0));
}

void loop() {
  DateTime now = rtc.now();
  hoursNow = now.hour();
  minutesNow = now.minute();
  secondsNow = now.second();
  Serial.print(hoursNow);
  Serial.print(":");
  Serial.print(minutesNow);
  Serial.print(":");
  Serial.print(secondsNow);
  delay(1000);
}

```
Maybe I'm missing something on the code that is causing it to not do the way I wanted it to do, but I've looked online, and most were pretty similar to the code I have.

body:
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));

You have this line in setup that sets the date and time to the date and time that the code was compiled.  That's fine to set it once, but that time never changes.  It's the time that it was when you compiled the code.  So every time it runs, you are setting the time back to this.  The RTC keeps the time running while the Arduino is off, but as soon as it's turned on your code sets it back to what it was before.

If you remove that line, then things will work the way you want.  You might need to load a sketch once with a line like this to set the time, run it once, then load a new sketch without that line.  Or include a routine in your code to allow a user to set the time.


message:
LoRa Ra-02 Module begin and beginPacket not working in Arduino Nano

Here there, recently I am testing **Lora Ra-02 module** I saw many videos and it is easy to set up, according to this schematic:

> LoRa SX1278 Module-----Arduino Nano Board
>
> 3.3V-------
>
> Gnd---------Gnd
>
> En/Nss------D10
>
> G0/DIO0------D2
>
> SCK---------D13
>
> MISO----------D12
>
> MOSI----------D11
>
> RST-------------D9

I am using a very common library called [sandeepmistry][1]. and I tried this code:

```c
#include <SPI.h>
#include <LoRa.h>

int counter = 1;

void setup() {
  Serial.begin(9600);
  while (!Serial);
  Serial.println("LoRa Sender");
  if (!LoRa.begin(433E6)) {
    Serial.println("Starting LoRa failed!");
    while (1);
  }
}

void loop() {
  Serial.print("Sending packet: ");
  Serial.println(counter);
  // send packet
  LoRa.beginPacket();
  LoRa.print("hello ");
  LoRa.print(counter);
  LoRa.endPacket();
  counter++;
  delay(500);
}
```
When I run it, it just sticks in this line {Serial.println("**Starting LoRa failed!**");}

Then I updated the code and tried to reduce the SPI Frequency because I am using **Arduino Nano**  now the code is this:

```c
#include <SPI.h>
#include <LoRa.h>

int counter = 1;
int frequency = 8E6; // Set the desired frequency here

void setup() {
  Serial.begin(9600);
  while (!Serial);
  Serial.println("LoRa Sender");
  LoRa.setSPIFrequency(frequency); // Add the missing semicolon here
  if (!LoRa.begin(433E6)) {
    Serial.println("Starting LoRa failed!");
    while (1);
  }
}

void loop() {
  Serial.print("Sending packet: ");
  Serial.println(counter);
  // send packet
  LoRa.beginPacket();
  LoRa.print("hello ");
  LoRa.print(counter);
  LoRa.endPacket();
  counter++;
  delay(500);
}
```
This code passes the line **Starting LoRa failed!** but it again stuck in here

>    LoRa Sender
>    Sending packet: 1

So why won't it do `LoRa.beginPacket();` and loop the code? Why does it stop here?

  [1]: https://github.com/sandeepmistry/arduino-LoRa

body:
Have you set the pins properly? Try doing:

```c
  LoRa.setPins(csPin, resetPin, irqPin);// set CS, reset, IRQ pin
```

There is a problem with the way your SX1276 is connected to the board, which is why `.begin()` returns false.


message:
ATtiny85 with sleep and serial

I want to communicate over serial to another device (dfplayer) and also set the microcontroller into sleep mode.

The ATtiny85 does not have a hardware serial pin so I need to use a virtual serial (like `SoftwareSerial.h`)

I've googled a lot and tried a lot of things but it basically seems to come always to the same problem. `SoftwareSerial` (or `NeoSWSerial`) do not work with `avr/sleep`. Something to do with interrupts,

> NeoSWSerial.cpp.o (symbol from plugin): In function `NeoSWSerial::read()':
(.text+0x0): multiple definition of `__vector_2'
.pio\build\attiny85\src\main.cpp.o (symbol from plugin):(.text+0x0): first defined here

AltSoftSerial won't work because it requires a 16bit timer which the ATtiny does not have__

Is there anything I can do about this?

---------

What I actually want to do

Connect 6 buttons with 6 different resistors to a single ADC pin of the controller. When a button is pressed wake up the device /if necessary), read the ADC value, pick a track based on that value and then play the track on the dfplayer.

After a while, if no button is pressed, put the dfplayer and the mcu to sleep. And that's why I need the mcu at all. You can't set the dfplayer to sleep or wake it up without serial

--------

Update:

I confused SPI and Serial indeed. I need to use serial communication

I want to send and receive packages. Send: `InitCommand`, Receive: `PlayerInitialized` / `InitializationFailed`. And so on.Well it's some hex codes of course but you get the point I think

My flow should basiclly look like this:

boot/wakeup  // <-- this is where I need the interrupt, don't I?
read adc value
pick track number based on adc value
send PlayTrack command to DFPlayer
delay x ms
send Sleep command to DFPlayer
go back to sleep

But the issue is in the combination of the Sleep and SoftwareSerial library. It's not the interrupt that is an issue. At least not yet

body:
Thanks to [@Delta_G](https://arduino.stackexchange.com/users/33871) I was able to figure out a solution.

I took the source files of the SoftwareSerial library [from github](https://github.com/arduino/ArduinoCore-avr/tree/master/libraries/SoftwareSerial/src) and copied it to my project. I renamed it so it wont give any conflicts. I then continued to comment out the interrupts in the cpp file and took care of calling `handle_interrupt` from my program. I also had to remove the inline keyword from the `handle_interrupt` function

I've posted my [modified files on github][1].

  [1]: https://gist.github.com/boop5/0cad063d281f181d31f84593eaffd12a


body:
> boot/wakeup // <-- this is where I need the interrupt, don't I?

Is the interrupt to detect that you have pressed one of the buttons? If you have that then you shouldn't need to use a timer to wake up.

If you connect your buttons with resistors in such a way that any button at all will send at least 0.6Vcc (ie. 3V upwards for a 5V system) then that could be configured to generate an interrupt (a rising interrupt). So you might set up the resistors so the buttons send 3.2V, 3.5V, 3.8V, 4.1V, 4.4V and 4.7V. That gives you six different voltages and they are all high enough to be considered "high" on a digital pin. Then make that pin generate the interrupt and also do the ADC reading on it once you wake up.

Then you can put the processor into a deep sleep until a button is pressed. While the track is playing you might also set up a watchdog timer interrupt so that you can wake up and check if it is time to put the player to sleep as well.


message:
"Best" architecture for handle events

I come from web world, so i usually code in a more procedurally manner, so the loop is a bit difficult to handle.

i mean if i do something like `if(condition) doSomething()` it will exec `doSomething()` a lot, or a click of a button....

```cpp
bool condition = false;
void loop(){
  if(condition){
    doSomething();
  }

}

void doSomething(){
  condition = false;
  // ........
}
```
iam doing things like this, but i feel its wrong somehow

so iam struggling why could be the "best" architecture to execute `doSomething()` only once, in a way it not become a hell of state management, some kind of event driven, event sourcing or something more battle tested for arduino

iam totally newbie in this hardware/arduino world

body:
You don't have to use their "setup" and "loop" paradigm, you know. This will work:

<!-- language: c++ -->

    #include <Arduino.h>

    int main ()
      {
      init ();  // initialize timers
      Serial.begin (115200);
      Serial.println ("Hello, world");
      Serial.flush (); // let serial printing finish
      }  // end of main

So, inside your code, if you want to do something once, do it once. If you want to make a loop, make one. Just like in C++. Which is what the Arduino code is.

---

> so iam struggling why could be the "best" architecture to execute doSomething() only once

Put it in `setup` if you want to run with their "setup" and "loop" paradigm. It was just designed for beginners, to clarify that some things you do once, and some things you do in a loop.


body:
The usual way to do things only once (at startup) is to put them in `setup()`.

You put only statements in `loop()` that need endless repetitions.

You can think of the underlying main function as:

```c++
int main() {
    setup();
    for (;;) {
        loop();
    }
}
```

Therefore, your example can be:

```c++
void setup() {
    doSomething();
}

void loop() {
}

void doSomething() {
    // ........
}
```

---

**Addition after clarification**

You commented:
> as far as i know i cant detect a button press outside of the loop right? when i said to execute once i mean, when press a button, it should do somenthing only once, this control of what should/was executed is a bit tricking, can go out of control and became a mess

With that requirement, you are right, you need to put the check and reaction inside `loop()`. However, you can "hide" the "mechanic" inside the called function:

```c++
void setup() {
}

void loop() {
    doSomething();
}

void doSomething() {
    static bool isDone = false;
    if (!isDone && condition) {
        isDone = true;
        // ........
    }
}
```

A dedicated variable is simple and clear. You might choose some other type and value, depending on the actual things to do.


body:
Coming from the Web world, you are most likely used to work in a
single-threaded environment (save for Web workers). You have been
trained to program in a non-blocking fashion, as blocking the browser's
UI thread would freeze the user interface. This is actually **a valuable
asset** when moving to Arduino programming. Most Arduino programs run on
a single-threaded, bare-metal platform. Non-blocking code is a must for
all but the most trivial programs, and is not easy to master for
newcomers.

The most striking difference between an Arduino and your typical
JavaScript environment (be it a browser or Node.js) is that in
JavaScript the event loop is _implicit_. You do not see it, but it runs
under the hood of your interpreter. It looks conceptually like this:

```c++
void JavaScript_event_loop() {
    if (there_is_a_pending_event()) {
        dispatch_the_event_to_the_registered_callback();
    }
}
```

On the Arduino, however, you have to write the event loop yourself. Most
often you do not need full-blown event queue management, as you know
beforehand the set of events your program will have to handle. Your
typical Arduino loop should normally look like this:

```c++
void loop() {
    if (event_foo_happened())
        handle_event_foo();
    if (event_bar_happened())
        handle_event_bar();
    if (event_baz_happened())
        handle_event_baz();
    // etc...
}
```

There are a few recurring idioms for testing common events. Here are
some examples:

```c++
// Handle a periodic event (like setInterval()).
uint32_t now  = millis();
static uint32_t last_event_time;
if (now - last_event_time >= event_period) {
    // Use `last_event_time = now;` instead of this if you want to
    // guarantee a minimal interval between events:
    last_event_time += event_period;  // this avoids systematic drift
    handle_periodic_event();
}

// Handle a rising edge on an input_pin.
uint8_t pin_state = digitalRead(pin);
static uint8_t previous_pin_state;
if (previous_pin_state == LOW && pin_state == HIGH)
    handle_input_rising_edge();
previous_pin_state = pin_state;

// Handle Serial data.
if (Serial.available())
    handle_input_byte(Serial.read());

// Handle a push button with a debouncing library.
button.update();
if (button.fell())
    handle_button_press();
```

A few recommended readings:

* The [Blink Without Delay][blink] Arduino tutorial shows how to handle
  periodic events
* [Reading Serial on the Arduino][serial] is a tutorial showing how to
  buffer serial input in order to handle one full message at a time
* [Bounce2][debounce] is an example of a button-debouncing library
* [The Finite State Machine][fsm] is a nice tutorial on writing finite
  state machines, which sooner or later you will need for handling some
  situations in a non-blocking way

[blink]: https://www.arduino.cc/en/Tutorial/BuiltInExamples/BlinkWithoutDelay
[serial]: https://www.majenko.co.uk/blog/our-blog-1/reading-serial-on-the-arduino-27
[debounce]: https://github.com/thomasfredericks/Bounce2
[fsm]: https://www.majenko.co.uk/blog/our-blog-1/the-finite-state-machine-26

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

**Edit**: Regarding the example code you posted, I would like to rewrite
your `loop()` like this:

```c++
void loop() {
    if (condition) {
        doSomething();
        condition = false;  // <- move this out of doSomething()
    }
}
```

It doesn't look like a big change, but there is an idea here that can
help make your code more readable and maintainable. The idea is to think
of your program in terms of “events” you have to respond to. This should
feel natural to someone raised on JavaScript, and it is also a good
approach for programming microcontrollers. You then want to handle the
event detection/dispatching and the event response as separate problems.
The function `doSomething()` should not have to care about the
`condition` variable, as it is only used to handle the event detection
and dispatching, which is the responsibility of the event loop.

> When i said to execute once I mean, when press a button, it should do
> something only once, this control of what should/was executed is a bit
> tricking, can go out of control and became a mess.

To detect a button press you _do_ have to manage some state, there is no
way around it. Your program should not respond to the _state_ of the
button (pressed or released) but instead to specific _transitions_ of
this state (press or release events).

In its most basic form, the problem is about detecting a falling edge
(or rising edge, depending on how the button is wired) on the input
signal. This is handled by remembering the state you had on the previous
loop iteration, and comparing this previous state with the state you are
reading right now, as show in the “Handle a rising edge on an input pin”
example above.

Real buttons have an additional issue, namely mechanic bounce: when the
button is actuated, the signal can go through many fast transitions
before settling into a stable state. In order to deal with this, you
have to look at the timing of the transitions and sort out the legit
ones from the spurious ones. This is called [debouncing][]. There are a
few libraries out there than can handle this for you. Most will also do
edge detection, which makes handling button presses as simple as testing
for `button.fell()` (again, see example above). Some will even report
distinct event types for short press, long press and double press.

[debouncing]: https://learn.adafruit.com/make-it-switch/debouncing


message:
How .data + .text section can be = How much flash the final program will consume

I could not understand one point related with Arduino code.

Let's say i have following code

```cpp
void setup()
{
  Serial.begin(9600);
  Serial.println("foo");
}

void loop()
{

}
```

When i compile above code for Arduino Uno. Arduino IDE gives.

> Sketch uses 1478 bytes (4%) of program storage space. Maximum is 32256
> bytes. Global variables use 192 bytes (9%) of dynamic memory, leaving
> 1856 bytes for local variables. Maximum is 2048 bytes.

I examine the generated file with `avr-size`.

    .data                         26   8388864
    .text                       1452         0
    .bss                         166   8388890
    .comment                      17         0
    .note.gnu.avr.deviceinfo      64         0
    .debug_aranges               208         0
    .debug_info                 6150         0
    .debug_abbrev               2721         0
    .debug_line                 2239         0
    .debug_frame                 504         0
    .debug_str                  1770         0
    .debug_loc                  1908         0
    .debug_ranges                 80         0

As you can see .data + .text = consuming program storage space. Then i checked this document. https://courses.cs.washington.edu/courses/csep567/04sp/pdfs/avr-libc-user-manual.pdf. It says about `avr-size`

    Note:
    The avr-size program (part of binutils), coming from a Unix background,
    doesn’t account for the .data initialization space added to the .text section, so in
    order to know how much flash the final program will consume, one needs to add
    the values for both, .text and .data (but not .bss), while the amount of pre-allocated
    SRAM is the sum of .data and .bss.

Then, i check contents of .data section with

    avr-objdump.exe -s -j .data <my.elf>

Then I got

    Contents of section .data:
     800100 00000000 ff005f00 8c004c01 bd009b00  ......_...L.....
     800110 af00666f 6f000d0a 0000               ..foo.....

I'm confused, what above quote really means ? "foo" stored in .data section, but why i need to add this section to .text section in order to calculate how much flash consumes ?

body: The values of your initialized-data (.data) are stored in flash together with your code. The initialized-data gets copied to RAM after every upload, reset, or power-up, before your code starts executing.


body:
Just to expand on what JRobert said, variables which are initialized, and other literals (eg. the word "foo" in your example) have to come from somewhere, and thus are stored in program (flash) memory and copied into RAM as part of the C++ initialisation.

However, uninitialised variables do not take up flash memory. Compare:

<!-- language: lang-c++ -->

    char foo [1000];
    void setup()
    {
      Serial.begin(9600);
      Serial.println("foo");
      Serial.print (foo);
    }

    void loop()
    {
    }

This reports for the Uno:

    Sketch uses 1498 bytes (4%) of program storage space. Maximum is 32256 bytes.
    Global variables use 1192 bytes (58%) of dynamic memory, leaving 856 bytes for local variables. Maximum is 2048 bytes.

However if you initialise that global variable foo, like this:

<!-- language: lang-c++ -->

    char foo [1000] = { 1, 2, 3, 4, 5 };
    void setup()
    {
      Serial.begin(9600);
      Serial.println("foo");
      Serial.print (foo);
    }

    void loop()
    {
    }

Now the flash takes 1000 more bytes:

    Sketch uses 2498 bytes (7%) of program storage space. Maximum is 32256 bytes.
    Global variables use 1192 bytes (58%) of dynamic memory, leaving 856 bytes for local variables. Maximum is 2048 bytes.

This clearly shows that, since uninitialised variables at global scope are set to zero, the compiler has generated code to do just that. However initialised variables have to be copied from flash into RAM.

A very useful technique when using these chips with not much RAM is to use the "F" macro, which effectively tells the compiler to copy strings directly from flash, rather than into RAM, thus saving RAM space. For example:

<!-- language: lang-c++ -->

    Serial.println (F("Hello, world"));

In this case the string "Hello, world" still has to be in flash, but doesn't have to be copied into RAM, thus saving precious memory for other purposes.

---

# Putting initialised arrays into flash

I've got a lengthy discussion about using PROGMEM for storing data, other than just literal strings for printing [on my forum](https://www.gammon.com.au/forum/?id=12615).

This example code here shows how you can store messages in PROGMEM (flash memory) and retrieve them at runtime. It uses `pgm_read_word` to read the pointers, and then `strcpy_P` to copy the string from PROGMEM into RAM, so it can then be printed.

<!-- language: lang-c++ -->

    const int NUMBER_OF_ELEMENTS = 10;

    const char Message0000 [] PROGMEM = "Twas bryllyg, and ye slythy toves";
    const char Message0001 [] PROGMEM = "Did gyre and gymble";
    const char Message0002 [] PROGMEM = "in ye wabe:";
    const char Message0003 [] PROGMEM = "All mimsy were ye borogoves; And ye mome raths outgrabe.";
    const char Message0004 [] PROGMEM = "\"Beware the Jabberwock, my son! \n The jaws that bite, the claws that catch!";
    const char Message0005 [] PROGMEM = "Beware the Jubjub bird, and shun\n The frumious Bandersnatch!\"";
    const char Message0006 [] PROGMEM = "He took his ";
    const char Message0007 [] PROGMEM = "vorpal sword in hand:";
    const char Message0008 [] PROGMEM = "Long time the manxome foe he sought - ";
    const char Message0009 [] PROGMEM = "So rested he by the Tumtum tree, \n And stood awhile in thought.";

    const char * const messages[NUMBER_OF_ELEMENTS] PROGMEM =
       {
       Message0000,
       Message0001,
       Message0002,
       Message0003,
       Message0004,
       Message0005,
       Message0006,
       Message0007,
       Message0008,
       Message0009,
       };

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

      unsigned int count = 0;

      for (int i = 0; i < NUMBER_OF_ELEMENTS; i++)
        {
        char * ptr = (char *) pgm_read_word (&messages [i]);
        char buffer [80]; // must be large enough!
        strcpy_P (buffer, ptr);
        Serial.println (buffer);
        count += strlen (buffer) + 1;
        }   // end of for loop

      Serial.print (F("String memory used = "));
      Serial.println (count);

      }  // end of setup

    void loop () { }

This particular example doesn't use much RAM:

    Sketch uses 2220 bytes (6%) of program storage space. Maximum is 32256 bytes.
    Global variables use 188 bytes (9%) of dynamic memory, leaving 1860 bytes for local variables. Maximum is 2048 bytes.


message:
Does the UNO R4 still have the standard on-board led on pin 13?

I need to add support for the UNO R4 (both models) for a library I'm maintaining. The library uses the LED on pin 13 as status indicator. I can't find any information whether that LED is still there on the R4 Minima and Wifi boards. The R4 Wifi has this nice LED matrix, so the other LED might be gone for it.

body: The schematics for the R4 Minima and Wifi boards can be found at:  https://docs.arduino.cc/resources/schematics/ABX00080-schematics.pdf and https://docs.arduino.cc/resources/schematics/ABX00087-schematics.pdf .  Pin 13 is also labeled SCK. A LED is attached to this pin.


message:
Separate from Serial for digitalWrite()

This is my current code (Arduino Mega 2560):

    #define p1 2
    #define p2 3

    void setup() {
     pinMode(p1, OUTPUT);
     pinMode(p2, OUTPUT);
     Serial.println("ARDUINO : CONNECTED");
    }

    void loop() {
     if (Serial.available()) {
      String state = Serial.readString();

      if (state.startsWith("LED1ON")) {
        digitalWrite(p1, HIGH);
      }
      if (state.startsWith("LED1OFF")) {
        digitalWrite(p1, LOW);
      }
      if (state.startsWith("LED2ON")) {
        digitalWrite(p2, HIGH);
      }
      if (state.startsWith("LED2OFF")) {
        digitalWrite(p2, HIGH);
      }
      // ... and next condition LED
     }
    }

how can i do for multiple input serial use seperator(";") ? like : LED1ON;LED2OFF

expacted:
one time command (LED1ON;LED2OFF) many condition (led turn on and led 2 turn off)

please, tks

body: Consider refactoring your code such that you read in strings then search through the string character by character copying each character to a new string until you find a semicolon.  When this happens do not copy the semicolon.  Instead execute the existing "if" statements to turn on / off the LEDs based on the content of the new string.  When done, erase the new string, loop back and continue to copy characters to the new string until the next semicolon.  If there is no more data to be copied, read in more data until data is unavailable.


body:
You might want to get used to visit [the Arduino library reference][1] to learn what is possible and how to use it.

For your case, you are interested in the method [`readStringUntil()`][2].

The reading, understanding, experimenting, debugging, and finishing is left as an exercise to the user.

  [1]: https://www.arduino.cc/reference/en/
  [2]: https://www.arduino.cc/reference/en/language/functions/communication/serial/readstringuntil/


body:
[readString](https://www.arduino.cc/reference/en/language/functions/communication/serial/readstring/) reads from Serial until it times out. This means it might undershoot or overshoot both the end of the line (if there is one) or the semicolon.

I suggest reading into a `char` buffer (say, of 30 bytes length) until either a newline or semicolon is reached. Then terminate the buffer with 0x00 (to make it a proper "C" string) and then do a simple string compare (`strcmp`).


message:
How to use Arduino Uno as PS/2 to USB converter for typical keyboard usages?

I'm beginner in Arduino and recently programmed an Arduino uno board with various PS/2 to USB converters. They work when typing in Serial Monitor of Arduino IDE, but not in the other programs such as Notepad.

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

How can I connect the board as HID keyboard for usual works with my PS/2 keyboard?

**Update:**

As @KIIV mentioned in the comments, Uno hasn't native USB and his suggestion is to start with boards such as Leonardo.

I want to ask, what is the straightforward way of using Uno for this purpose?

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

body:
As the Uno has no generic USB module, it generally works only as a virtual serial device. Without additional hardware you cannot make a Uno work as a USB keyboard. In principle.

A possible solution is the usage of [V-USB][1]. This nice library uses [bit-banging][2] to realize low-speed USB communication. A USB keyboard commonly is such a low-speed USB device.

Another possible solution is an accompanying software "driver" on the PC. It will receive the key events via the USB serial port and translate them to key events for the operating system. But I'm sure you will not want this.

  [1]: https://www.obdev.at/products/vusb/index.html
  [2]: https://en.wikipedia.org/wiki/Bit_banging


message:
changing a single bit in an arduino EEPROM byte

In my code I have a number of boolean flags that tell me if data has been written to specific places in the EEPROM. I need to save these flags to the EEPROM and recover them on a restart.

Is the following syntax valid to update a single bit in an EEPROM cell?
```
EEPROM.update (0, EEPROM.read(0)| 0x20);
```

ie I'm reading cell '0' , putting a '1' into bit 5 and then updating cell; '0' of the EEPROM. There will be several other bits to be updated throughout the running of the programme.

body:
Yes, your syntax is indeed correct. The `|` operator is the bitwise OR operator in C and C++, and it's used to set a specific bit in a byte. Here's a breakdown of what your line of code does:

- `EEPROM.read(0)` reads the current value of the first byte in the EEPROM.
- `0x20` is the hexadecimal representation of 32, which is `00100000` in binary. This means that the fifth bit (counting from zero) is set to 1, and all other bits are set to 0.
- `EEPROM.read(0) | 0x20` performs a bitwise OR operation on the current value of the first byte in the EEPROM and `0x20`. This will set the fifth bit of the byte to 1, and leave the other bits unchanged.
- `EEPROM.update(0, EEPROM.read(0) | 0x20)` updates the first byte in the EEPROM with the new value.

So, your approach to set a specific bit in an EEPROM byte is correct.

Here's a more detailed example:

```cpp
byte bitToSet = 5; // Bit number to set (0-7)
byte eepromAddress = 0; // EEPROM address (0-1023 for ATmega328)

// Read current value
byte currentValue = EEPROM.read(eepromAddress);

// Create mask for bit to set
byte mask = 1 << bitToSet;

// Update value
byte newValue = currentValue | mask;

// Write updated value back to EEPROM
EEPROM.update(eepromAddress, newValue);
```

It's worth noting that the `EEPROM.update()` function is smart enough to only perform a write if the new value is different from the old one. This is important because the EEPROM has a limited number of write cycles. So using `EEPROM.update()` instead of `EEPROM.write()` can help extend the life of the EEPROM.


message:
Overhead of using 'new' to create object in dynamic ram vs automatic to create on stack

Let's suppose I have a class named `Foo`, and `sizeof(Foo)` is 10 bytes.

As I understand it, creating a Foo with 'automatic' scope (on the stack) has zero overhead. If the Object occupies 10 bytes, it consumes 10 bytes on the stack. Period.

I'm kind of fuzzy about how creating objects with 'new' works on an 8-bit AVR. I know that 'new' ultimately calls malloc(), and that on Windows/Linux, malloc() ultimately asks the operating system for memory whose management is up to the OS itself. But... with 8-bit AVR, there *is no* operating system. So, presumably, something else has ultimate responsibility for managing its heap. And presumably, there's some kind of overhead involved so it can keep track of which bytes have been returned to it by a destructor, and which ones are still in use.

So... using the hypothetical 10-byte `Foo` as an example... if I make 7 sequential calls in a row to `new Foo()`, how many bytes will it *actually* burn through (including overhead)?

For objects that have to be instantiated via `new`, but will persist "forever" (until the next reset), is there any special syntax that tells the compiler/malloc()/whatever, "This object will **never** be destroyed, so there's no need to preserve any information that would otherwise be necessary to release its memory eventually"?

---

Giving this a bit of context, assume `View` is a class with multiple templated subclasses (let's say, `TemperatureView<int, int, int, int>` and `LabelView<int, int, int, const char*>`), and I'm doing something like this:

~~~
const PROGMEM char* pLABEL = "Foo:";
View* views[] = {
    (new TemperatureView<0,3,0,2>{}),
    (new LabelView<1,4,0,pLABEL>{})
};
~~~

I'm trying to figure out just how big of a penalty hit (in terms of wasted ram from overhead) I'm taking by rolling it all into one nice, neat combined declaration instead of doing something like:

~~~
const PROGMEM char* pLABEL = "Foo:";
TemperatureView<0,3,0,2> firstTemp {};
LabelView<1,4,0,pLABEL> firstLabel {};
View* views[] = {
    &firstTemp,
    &firstLabel
};
~~~

(I originally wanted to put the objects whose addresses were being added to views[] in automatic/stack, but apparently, that's taboo because the compiler thinks the array will outlive the objects whose addresses would otherwise be stored there)

body:
If you make an automatic variable, its lifetime is the lifetime of the function it is inside, so it won't persist forever, unless it is at global scope, or it is declared `static`.

The overhead of using `new` is the size of the object you allocate plus a couple of bytes to keep track of what that bit of memory is used for.

> if I make 7 sequential calls in a row to new Foo(), how many bytes will it actually burn through (including overhead, which appears to be two bytes, see test below)

Seven times the size of the object plus the overhead I mentioned.

Normally you would release that memory with `delete` unless you want it kept forever.

> For objects that have to be instantiated via new, but will persist "forever" (until the next reset), is there any special syntax that tells the compiler/malloc()/whatever, "This object will never be destroyed ...

No. It persists until you call `delete` which there is no compunction to do.

I wrote a test program for my Uno to see what the overhead was, to use `new`.

<!-- language: lang-c++ -->

    #include "memdebug.h"

    void showFreeMemory ()
      {
      Serial.print (F("Free memory = "));
      Serial.println (getFreeMemory ());
      } // end of showFreeMemory

    typedef struct {char s [20]; } foo;

    void setup ()
      {
      Serial.begin (115200);
      Serial.println ();
      showFreeMemory ();   // 1664
      foo * bar = new foo;
      showFreeMemory ();   // 1642
      strcpy (bar->s, "Hello, world");
      Serial.println (bar->s);
      delete bar;
      showFreeMemory ();   // 1664
      }  // end of setup

    void loop () { }

> I'm trying to figure out just how big of a penalty hit (in terms of wasted ram from overhead)

Two bytes, by the looks, for each allocation.

> (I originally wanted to put the objects whose addresses were being added to views[] in automatic/stack, but apparently, that's taboo because the compiler thinks the array will outlive the objects whose addresses would otherwise be stored there)

I'm not sure what you mean by that, can you give a concrete example?

---

I think you will save more memory by using PROGMEM, which you seem to be doing, a bit.

See my post [here](https://www.gammon.com.au/forum/?id=12615) for ideas about doing that.

---

## Reference

I got memdebug.h (and memdebug.c) from [Andy's workshop - Debugging AVR dynamic memory allocation](https://andybrown.me.uk/wk/2011/01/01/debugging-avr-dynamic-memory-allocation/)


body:
Just as a small complement to the previous answer... The documentation
of the avr-libc has a whole page discussing the workings of `malloc()`.
The section titled [Implementation details][doc] states:

> Dynamic memory allocation requests will be returned with a two-byte
> header prepended that records the size of the allocation. This is
> later used by `free()`. The returned address points just beyond that
> header.

This is consistent Nick Gammon's experimental finding.

[doc]: https://www.nongnu.org/avr-libc/user-manual/malloc.html#malloc_impl


message:
Digital Pot with Arduino

I am a newbie in electronics. Please correct me if I am wrong.
I am replacing a pot with a digital pot (DS3502) in a circuit.
The Vcc of the circuit is 12V. But the digital pot can have a maximum of 5.5V as Vcc.
I am controlling the digital pot with an Arduino UNO. Can I use 5V from the Arduino as the Vcc of the digital pot and 12V as the Vcc of the circuit?
I kept the ground common for both.

The connection is as below:

DS3502 Arduino Uno

VCC --- 5V

GND --- GND

SDA --- A4

SCL --- A5

DS3502 Circuit

RL --- GND

RW --- Circuit

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

This is a constant current circuit of 21mA, to drive a laser. But I want to slightly tune the intensity of laser using the digital pot. So I am replacing it with digital pot. But I am getting an open connection in the place of resistor. I have only use RL and RW to circuit. RH is kept opened. Do I need to connect RH and V bias to 12V(Vcc of my constant current circuit)? I don't have much knowledge in circuits. Please spare me if I am wrong

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

body:
If you look at [the datasheet](https://www.analog.com/media/en/technical-documentation/data-sheets/DS3502.pdf) it mentions that Vcc can be from 2.5V to 5.5V, and clearly the I2C connection is referenced to Gnd. Therefore you would connect the Uno to the DS3502 in the usual way (Gnd, Vcc, SDA and SCL).

The "digital pot" side has a separate input (V+) which can be from 4.5V to 15.5V.

>  Can I use 5V from the Arduino as the Vcc of the digital pot and 12V as the Vcc of the circuit?

Your terminology is a bit loose here. You can use 5V from the Arduino to the Vcc pin of the pot (pin 3) and 12V to V+ and RH (pins 6 and 9). The output will be on RW (the wiper, pin 7).

It also looks like you would connect Gnd and RL (pins 2 and 8) to Gnd on the Arduino.

Although, conceivably I think, you could connect Gnd (pin 2) to Gnd on the Arduino, and RL (pin 8) to the Gnd of the "other circuit" - the one you are controlling. It looks like they are separate.

I think you might keep RL and Gnd not connected, to reduce digital noise.

The A0 and A1 pins are for modifying the I2C address.

[![DS3502 typical wiring][1]][1]

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


message:
Parse char* mac-string to uint8_t array

I have to handle a String coming in over UART containing a bunch of information, part of it is a MAC-address that I get by using String.substring(a, b) returning a 12-char String representing a mac-address `"B8C9A45BA770"` <- (just an example).

**I need the format of the mac-address to be a uint8_t array like so
`{ 0xB8, 0xC9, 0xA4, 0x5B, 0xA7, 0x70 }`.**

So I need a function to convert a String to a uint8_t*. Sadly I have no clue how to convert this. There has so be an easy way right? its "C8" to 0xC8 and so forth...

Any ideas on this?

body:
Personally I'd go with a basic implementation such as this one.

    const uint8_t MAC_length = 6;
    uint8_t* MAC_buffer[6];

    uint8_t fromHexChar(char c)
    {
        uint8_t result = 0
        if ((c >= '0') && (c <= '9'))
            result = c - '0';
        else if ((c >= 'A') && (c <= 'F'))
            result = 10 + c - 'A';
        else if ((c >= 'a') && (c <= 'f'))
            result = 10 + c - 'a';
        return result
    }

    uint8_t* toMAC(String s)
    {
        for (uint8_t i = 0; i < MAC_length; i++)
        {
            MAC_buffer[i] = (fromHexChar(s.charAt(2*i)) << 4) | fromHexChar(s.charAt(2*i + 1));
        }
        return MAC_buffer;
    }

Probably it can be optimized, but this is such a simple job and to be used so rarely that I think this is enough.

Important: I did not test this code, so there may be bugs inside.

If you need to start from an arbitrary point in the String instead of at the beginning, you simply have to modify it this way:

    uint8_t* toMAC(String s, uint8_t startIdx)
    ...
            MAC_buffer[i] = fromHexChar(s.charAt(2*i + startIdx)) << 4 | fromHexChar(s.charAt(2*i + startIdx + 1));

Note for future me: I checked both on a simulator and in the code, and `charAt` is safe to use even when the index is outside the string boundaries (it simply returns 0).


message:
Having trouble uploading sketch to Nano

I have a few cheap Nano clones that I bought online that have worked for the past couple of months. They were working fine today until suddenly the Arduino IDE had trouble uploading sketches to them.

Here is the full error message:
```
Arduino: 1.8.19 (Windows 10), Board: "Arduino Nano, ATmega328P (Old Bootloader)"

Sketch uses 2080 bytes (6%) of program storage space. Maximum is 30720 bytes.

Global variables use 212 bytes (10%) of dynamic memory, leaving 1836 bytes for local variables. Maximum is 2048 bytes.

An error occurred while uploading the sketch

avrdude: ser_open(): can't set com-state for "\\.\COM5"
```

I have tried troubleshooting multiple ways, but none of the following worked:
- unplugged/replugged in nano
- restarted computer
- swapped to another nano clone
- changed USB cables
- changed USB ports
- tried uploading other code
- downloaded the CH340 drivers

I tried uploading to an Arduino Mega and that DID work, however, I would like to be able to use the Nano.

I am using version 1.8.19

Thanks for the help.

body:
See https://arduino.stackexchange.com/questions/13292/have-i-bricked-my-arduino-uno-problems-with-uploading-to-board/13293#13293.

I know you mentioned Nano, but it is the same concept.

If a sketch you previously uploaded sets up the watchdog timer to fire too quickly the new sketch may not upload.

Try holding down reset while you start the upload process and then release reset when the upload starts. See the part of the linked answer headed "Watchdog timer problems".


body: The cheap Nano requires you to use the old bootloader. I use them without problems most of the time. When it fails to upload I first check tools and validate the bootloader it is running. If it is correct I then close the IDE, power down the Nano and then reopen and repower it, between the two it usually solves the problem.


message:
Using file.seek() with arduino ide

I have in my code in c, this function:
```c
    fseek(file, 0, SEEK_SET);
```
I need to use the same function with Arduino ide. Is this correct?
```c
    file.seek(file.size());
```
Or what is the alternative function in Arduino ide?

body:
According to <https://www.arduino.cc/reference/en/libraries/sd/seek/> :

### SD - seek()

Seek to a new position in the file, which must be between 0 and the size of the file (inclusive).

### Syntax

    file.seek(pos)

### Parameters

* file: an instance of the File class (returned by SD.open()).
* pos: the position to which to seek (unsigned long).

---

If you want to seek to the start of the file, therefore you should seek to zero, not `file.size()`. Using `file.size()` would seek to the end of the file.


message:
How to calibrate MMC5603 magnetometer

I just got a MMC5603 magnetometer from Adafruit however the measurements are unreliable. For example when I convert it to a heading it goes from 200° to 180° and then back to 200° if I move it radially.

body:
To calibrate a magnetometer you should perform hard-iron and soft-iron calibration. There's some guides online about how to do this but I found [this digikey guide][1] to be the most informative. Adafruit also has a guide [here][2]

I had some issues getting this to work however so here's some tricks

## Using an M1 macbook

Both guides recommend to use MotionCal but it hasn't been updated in several years. If you downloaded the macOS version it might not show any available ports. To fix this you need to compile it from source – you can find details in this [Github Issue][3] but the TL;DR is:

1. `git clone git@github.com:PaulStoffregen/MotionCal.git`
2. `brew install wxwidgets`
3. Open the `Makefile`
4. Comment the line `OS = LINUX`
5. Uncomment the line`OS = MACOSX_CLANG`
6. Under `else ifeq ($(OS), MACOSX)` add `-arch arm64` to the `CFLAGS`
7. Run `make` and it should build

I had some issues with it not building after this which was resolved by deleting the directory and then redoing these steps

## Using an Arduino UNO

Both guides say to use **Adafruit Sensor Lab** which is too large to fit onto an Arduino UNO's flash. Instead you can you use this code:

```c++
#include <Arduino.h>

#include <Adafruit_MMC56x3.h>

/* Assign a unique ID to this sensor at the same time */
Adafruit_MMC5603 mmc = Adafruit_MMC5603(12345);

int loopcount = 0;

// Hard-iron calibration settings
const float hard_iron[3] = {
    0, 0, 0
};

// Soft-iron calibration settings
const float soft_iron[3][3] = {
    { 1, 0, 0 },
    { 0, 1, 0 },
    { 0, 0, 1 }
};

void setup(void)
{
    Serial.begin(115200);
    while (!Serial)
        delay(10); // will pause Zero, Leonardo, etc until serial console opens

    Serial.println("Adafruit_MMC5603 Magnetometer Test");
    Serial.println("");

    /* Initialise the sensor */
    if (!mmc.begin(MMC56X3_DEFAULT_ADDRESS, &Wire)) { // I2C mode
        /* There was a problem detecting the MMC5603 ... check your connections */
        Serial.println("Ooops, no MMC5603 detected ... Check your wiring!");
        while (1)
            delay(10);
    }

    /* Display some basic information on this sensor */
    mmc.printSensorDetails();
}

void loop(void)
{
    static float hi_cal[3];
    // Get a new sensor event
    sensors_event_t event;
    mmc.getEvent(&event);

    // Put raw magnetometer readings into an array
    float mag_data[] = { event.magnetic.x,
        event.magnetic.y,
        event.magnetic.z };

    // Apply hard-iron offsets
    for (uint8_t i = 0; i < 3; i++) {
        hi_cal[i] = mag_data[i] - hard_iron[i];
    }

    // Apply soft-iron scaling
    for (uint8_t i = 0; i < 3; i++) {
        mag_data[i] = (soft_iron[i][0] * hi_cal[0]) + (soft_iron[i][1] * hi_cal[1]) + (soft_iron[i][2] * hi_cal[2]);
    }

    // 'Raw' values to match expectation of MOtionCal
    Serial.print("Raw:");
    Serial.print(0);
    Serial.print(",");
    Serial.print(0);
    Serial.print(",");
    Serial.print(0);
    Serial.print(",");
    Serial.print(0);
    Serial.print(",");
    Serial.print(0);
    Serial.print(",");
    Serial.print(0);
    Serial.print(",");
    Serial.print(int(mag_data[0] * 10));
    Serial.print(",");
    Serial.print(int(mag_data[1] * 10));
    Serial.print(",");
    Serial.print(int(mag_data[2] * 10));
    Serial.println("");

    // unified data
    Serial.print("Uni:");
    Serial.print(0);
    Serial.print(",");
    Serial.print(0);
    Serial.print(",");
    Serial.print(0);
    Serial.print(",");
    Serial.print(0);
    Serial.print(",");
    Serial.print(0);
    Serial.print(",");
    Serial.print(0);
    Serial.print(",");
    Serial.print(mag_data[0]);
    Serial.print(",");
    Serial.print(mag_data[1]);
    Serial.print(",");
    Serial.print(mag_data[2]);
    Serial.println("");

    delay(10);
}
```

which will output the magnetometer data correctly formatted at the correct baud rate. Then you just open up MotionCal, select the right port

  [1]: https://www.digikey.com/en/maker/projects/how-to-calibrate-a-magnetometer/50f6bc8f36454a03b664dca30cf33a8b
  [2]: https://learn.adafruit.com/adafruit-sensorlab-magnetometer-calibration/magnetic-calibration-with-motioncal
  [3]: https://github.com/PaulStoffregen/MotionCal/issues/11


message:
A peristaltic pump with pH sensor and web based output project

Good day to you all, I am asking here to confirm that my project is feasible. I have low knowledge of Arduino and other components. Please help me in achieving this project.

I already have the peristaltic pump and pH sensor working with Arduino uno. Now I want the output of the pH sensor to be displayed in a webpage or web app, In the webpage I will also make a formula on how much volume is released from the peristaltic pump.

So there are two things on my webpage output: the acidity of the liquid and the volume released. I want a wireless setup, so I guess I would use ESP32 (notsure)? Now I kind of getting hard on how to put it on a webpage and the important part is, how to pass the data from the arduino to the ESP32?. Any ideas? or things that I would do?

OR

I  would use the ESP32 alone since I have not so many components and I think the ESP32 can cater for the pHsensor (analog signal) and pwm (motor Peristaltic pump). Correct me if I'm wrong. By this, I won't be having problems about the communication to the arduino and esp32 (UART).

Additional Info:\
Current Set up-\
Arduino - controls the pump and pHsensor\
ESP32 - Webpage or webserver

Is there any way that I could do this with ESP32 alone? so that I won't be having problems with UART.

I want to thank you in advance for giving me insights.

Update:

by this I decided to use ESP32 alone for the whole project. I just need to rewire all. I'm hoping the ESP32 has PWM pins to control the pwm peristaltic pump and pHsensor(analog signal) pins. Please confirm if you know that ESP32 has these pins(for pwm and analog). By the way I'm using the ESP32S where the TXD0 is in pin 35 which is the GPIO1 and the RXD0 is in pin 34 which is the GPIO3. –
Johannes Remotigue
 2 days ago   Delete

body:
Yes. You will need to add a solid state switch or similar to power the motor. The ESP32 has the radio needed to connect to your wifi so that part is already there. The ESP can be configured as a client or server so take your pick. There is a lot published on the web about doing this with code even posted. The device also has a lot of computing power so it could become a stand alone device which reports the results to the web server or works in conjunction with it.

All you will need to add is mainly code.  This should get you started. Just be cautious as the Arduino is generally 5V and the ESP is 3.3 volt so some voltage translation may be needed and if using 5V modules and/or MOSFETS. If MOSFETs are involved be very careful of the Vgs ratings to be sure it is on with 3V.


message:
NodeMCU V3 GOT OVERHEATED AND DIED

My NodeMCU V3 got overheated and died. Please help me figure out what i did wrong.

Brief Desrip: Project is an RC Car on ESPNOW Protocol. Transmitter setup have an Arduino Nano to take values from Two analogue joysticks and sends to a NodeMCU through Tx & Rx Pins, which then Transmits the values to the NodeMCU V3 in my Receiver (An RC CAR) over ESPNOW Protocol. Transmitter side is working perfect.

But, the NodeMCU V3 in my Receiver setup has got overheated and Died during a full throttled action. Here I am attaching the wiring diagram of the receiver setup. Please help me figure out whether there is any issues with the wiring.

[![WIRING DIAGRAM ][1]][1]

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

body:
Based on https://lastminuteengineers.com/l298n-dc-stepper-driver-arduino-tutorial/, you have wired your servo incorrectly. The third pin on the bottom blue connector (VSS) is the second input, not the output.

[![Power wiring diagram of the L298N][1]][1]

I can only speculate what happened, but I suspect that the servo tried to draw power from the D4 pin which overloaded and fried some internal circuitry of the ESP8266.

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


message:
How to properly read ADC on an ATtiny85?

**What I want to do**: attach six buttons to a single input. Each button triggers a different action.

**How I want to do it**: Use an AD conversion and add a resistor with different values to each button so that you can distinguish between the different input signals
I use these values: 1k, 4.7k, 18k, 22k, 55k, 300k

Vcc is stable 3.3v but I also tried it on 5v. I use Vcc as reference value for the ADC.

**The problem I have**: no matter what I do I always read the same value on the ADC. Connected to  GND it reads 0 and on Vcc it reads a value that’s always the same regardless what resistor I actually use.

I tried a lot of things I’ve found on the internet but nothing really worked for me. I’m clearly doing something wrong

This is the method I call in `setup()` to initialize the converter on ADC2(pb4)

    void initADC()
    {
      // 8-bit resolution
      // set ADLAR to 1 to enable the Left-shift result (only bits ADC9..ADC2 are available)
      // then, only reading ADCH is sufficient for 8-bit results (256 values)

      ADMUX =
                (1 << ADLAR) |     // left shift result
                (0 << REFS1) |     // Sets ref. voltage to VCC, bit 1
                (0 << REFS0) |     // Sets ref. voltage to VCC, bit 0
                (0 << MUX3)  |     // use ADC2 for input (PB4), MUX bit 3
                (0 << MUX2)  |     // use ADC2 for input (PB4), MUX bit 2
                (1 << MUX1)  |     // use ADC2 for input (PB4), MUX bit 1
                (0 << MUX0);       // use ADC2 for input (PB4), MUX bit 0

      ADCSRA =
                (1 << ADEN)  |     // Enable ADC
                (1 << ADPS2) |     // set prescaler to 64, bit 2
                (1 << ADPS1) |     // set prescaler to 64, bit 1
                (0 << ADPS0);      // set prescaler to 64, bit 0
    }

The code is taken from here https://www.marcelpost.com/wiki/index.php/ATtiny85_ADC

The page seems to be down at the moment so here is an archived version of it
https://web.archive.org/web/20230128091128/https://www.marcelpost.com/wiki/index.php/ATtiny85_ADC

In the `loop()` method I do basically this: Read ADC and then blink an LED *n* times, based on the read value.

    ADCSRA |= (1 << ADSC);         // start ADC measurement
    while (ADCSRA & (1 << ADSC) ); // wait till conversion complete

    uint8_t adcValue = ADCH;

    if (adcValue >= 0 && adcValue < 32) {
      blink(1);
    } else if (adcValue >= 32 && adcValue < 126) {
      blink(2);
    } else if (adcValue >= 126 && adcValue < 193) {
      blink(3);
    } else if (adcValue >= 193 && adcValue < 227) {
      blink(4);
    } else if (adcValue >= 227 && adcValue < 245) {
      blink(5);
    } else if (adcValue >= 245 && adcValue <= 255) {
      blink(6);
    }
    delay(60000);

My breadboard has the resistors going from Vcc to an empty row and I connect a jumperwire from PB4 to one of these resistors and do an external reset of the microcontroller to test my setup. They share GND/Vcc

What am I doing wrong? What can I do to *debug* this?

Thanks

body:
Unfortunately [@jsotola][1] only posted their solution as a comment. But it was the correct answer. So I'll just post my solution here

I now use a voltage divider setup with these values:

Voltage divider formula `Vs * R2 / (R1 + R2)`

Vs: 3.3v
R2: 100k Ohm
R1: 10k (3.0v), 27k (2.8v), 38k (2.6v), 50k (2.2v), 65k (2.0v)

Using an 8-bit ADC, I came up with these *if* statements to distinguish between the inputs. I gave it some room for deviation

    if (adcValue >= 227 && adcValue <= 237)
    {
      // 10k ohm (3.0V -> adc 232)
    }
    else if (adcValue >= 212 && adcValue <= 223)
    {
      // 18k ohm (2.8V -> adc 217)
    }
    else if (adcValue >= 196 && adcValue <= 206)
    {
      // 27k ohm (2.6V -> adc 201)
    }
    else if (adcValue >= 181 && adcValue <= 191)
    {
      // 38k ohm (2.4V -> adc 186)
    }
    else if (adcValue >= 165 && adcValue <= 175)
    {
      // 50k ohm (2.2V -> adc 170)
    }
    else if (adcValue >= 150 && adcValue <= 160)
    {
      // 65k ohm (2.0V -> adc 155)
    }

Here is a picture of my breadboard. I know it's not a real schematic but I couldn't figure that out right now. But I hope it's good enough

[![enter image description here][2]][2]

  [1]: https://arduino.stackexchange.com/users/40318
  [2]: https://i.stack.imgur.com/xl81z.jpg


message:
SD Card Mount Failed with Waveshare ESP32 using Arduino IDE

I'm currently working on a project using an ESP32 (the [Waveshare ESP32 Driver Board][1]), and I am trying to read data from an SD card, but consistently getting a "SD Card Mount Failed" error. I am using the [Adafruit SD card reader breakout board][2] and the Arduino IDE.

Here's how I've wired the SD card reader to the ESP32

```
SD card     ESP32
-------     -----
3.3V        3.3V
GND         GND
CLK         pin 18 (SCK)
DO          pin 19 (MISO)
DI          pin 23 (MOSI)
CS          pin 5 (SS)
```

And here's the relevant code I'm using to setup and test the SD card:

    #define SCK  18
    #define MISO  19
    #define MOSI  23
    #define CS  5

    int setup_sd_card() {

      SPIClass spi = SPIClass(VSPI);
      spi.begin(SCK, MISO, MOSI, CS);

      if (!SD.begin(CS,spi,80000000)) {
        Serial.println("ERROR: SD Card Mount Failed");
        return -1;
      }
      uint8_t cardType = SD.cardType();

      if(cardType == CARD_NONE){
        Serial.println("ERROR: No SD card attached");
        return -1;
      }

      // Code to print out SD card details...

      return 1;
    }

I've triple-checked my wiring but the code always fails at `if (!SD.begin(CS,spi,80000000))`. I've tried 3 different SD cards of different sizes, all formatted to FAT32 (64GB, 256GB, 1024GB)

Could the issue be related to the ESP32 not being a stock one because it has some hardware for driving an e-paper screen? Here is the schematic: https://www.waveshare.com/w/upload/8/80/E-Paper_ESP32_Driver_Board_Schematic.pdf

[![Waveshare ESP32 Schematic][3]][3]

Can anyone suggest what might be the issue or what else I could try to debug this problem? Any help would be greatly appreciated.

  [1]: https://www.waveshare.com/e-paper-esp32-driver-board.htm
  [2]: https://www.adafruit.com/product/254
  [3]: https://i.stack.imgur.com/cQCu6.jpg

body:
The issue turned out to be a faulty SD card.

I had tried other SD cards but must have used incorrect wiring for them.

EDIT: Here is the updated code:

    #define CS        5
    #define SCK       18
    #define MOSI      23
    #define MISO      19

    SPIClass spi(VSPI);

    int setup_sd_card() {
      spi.begin(SCK, MISO, MOSI, CS);

      if (!SD.begin(CS,spi,4000000)) {
        Serial.println("ERROR: SD Card Mount Failed");
        delay(1000);
        return -1;
      }
      Serial.println("Finished initializing SD card. Getting card type...");

      uint8_t cardType = SD.cardType();

      if(cardType == CARD_NONE){
        Serial.println("ERROR: No SD card attached");
        delay(1000);
        return -1;
      }

      Serial.print("SD Card Type: ");
      if (cardType == CARD_MMC){
        Serial.println("MMC");
      } else if(cardType == CARD_SD){
        Serial.println("SDSC");
      } else if(cardType == CARD_SDHC){
        Serial.println("SDHC");
      } else {
        Serial.println("UNKNOWN");
      }
      Serial.printf("Total space: %lluMB\n", SD.totalBytes() / (1024 * 1024));
      Serial.printf("Used space: %lluMB\n", SD.usedBytes() / (1024 * 1024));

      Serial.println("SUCCESS! (SD CARD)");

      return 1;
    }


body:
There are at least two problems with your code.

First I think you have a typo in the frequency. Default frequency is 4 MHz, but your parameter in `begin` is 80 MHz, which I doubt will work.

You initialize the `spi` object on the stack in the function and then supply it to the SD instance. The `spi` object on stack will be removed when the function ends and the SD object will crash. It has to be an allocation on heap as `SPIClass* spi = new SPIClass(VSPI);` or a global variable `SPIClass spi(VSPI);`.

And since you use the default pins of VSPI you can use just `spi.begin()` without the pin numbers.


message:
Microcontroller freezes when triggering the gate of an N-channel MOSFET

**Disclaimer**: I have [asked][1] [questions][2] about this project before but this is yet another issue I'm facing.

**What I really want to do**: Build a battery powered device with 6 colored buttons. When you press one of the buttons the gadget should play a sound saying the name of the color.

It should not need an ON/OFF toggle to save battery capacity but rather have a very low idle current draw so that the battery will lasts for weeks (or even months) when it's not used.

Something like this
[![enter image description here][3]][3]

**Hardware**: ATtiny85 (low draw in general, very low draw in sleep), DfPlayer, 3.7v Battery (probably 18650)

The 6 buttons are attached to a single input pin. The microcontroller can distinguish them by reading the ADC value. The buttons have [different resistors attached][1] to them

**How I wanted to do it**: My initial plan was to press a button that wakes the microcontroller up. The mcu then wakes the dfplayer, plays a sound and goes back to sleep. If that would not be responsive enough add a delay to the sleep like: if no button was pressed within the last 30s go to sleep. That worked [after some initial problems][2] but it turned out that the DfPlayer "sleep mode" doesn't mean it goes to sleep as in it draws less current but much rather that it's just idling, not playing any sound.

**How I want to do it now**: Pretty much the same as above but instead of sending the DfPlayer to sleep just turn it on and off:
Press a button that wakes the microcontroller up. The mcu then turns the DfPlayer on by setting the gate of an n-channel mosfet ([IRF3708][4]) HIGH, waits a short period of time, plays a sound, turns the dfplayer off and goes back to sleep. If that's not responsive enough add a sleep delay like explained above.

**What I'm already able to do**:

- make the DfPlayer play a specific sound over serial communication
- distinguish between the 6 input buttons
- wake the microcontroller up with any of these buttons
- turn the DfPlayer on/off by using an n-channel mosfet

**The problem that I have**: The microcontroller *freezes* when I set the output pin attached to the mosfet gate to HIGH. Freeze means it just won't execute any code after the `digitalWrite(PIN_MOS, HIGH);` call. I tested it by turning an LED on a different pin on and off like so

    digitalWrite(PIN_LED, HIGH);
    digitalWrite(PIN_MOS, HIGH);
    digitalWrite(PIN_LED, LOW);

The LED turns on but won't ever turn off. When I use the external reset of the attiny the mosfet will turn off and code will execute again just fine. Until I try to set the mosfet pin to HIGH again.
The DfPlayer will turn on though, I can play sounds on it by shorting 2 pins on it. It doesn't seem to be unstable either. It's just that the attiny hangs up.
I use a cheap lab psu but it should be good enough to be not the problem. I've also tried a fully charged 18650 battery and a CR2032 battery. The 18650 worked the same as the psu and the CR2032 just couldn't handle the draw and the DfPlayer wouldn't properly turn on.
I tried it different voltages between 3.3v and 5v. In theory everything should work and in reality it didn't change anything either.

Here is the breadboard layout I use.
I also added an electrolytic and ceramic cap between Vcc/GND on the DfPlayer but that didn't help either

[![enter image description here][5]][5]

Here is the code I use
```c
    #include <Arduino.h>
    #include <avr/sleep.h>
    #include <DFMiniMp3.h>
    #include <avr/interrupt.h>
    #include <avr/power.h>
    #include "LemonSerial.h"
    #include "mp3notify.h"

    #define PIN_TX PB0
    #define PIN_RX PB1
    #define PIN_MOS PB2
    #define PIN_LED PB3
    #define PIN_A PB4

    LemonSerial secondarySerial(PIN_RX, PIN_TX);
    DfMp3 dfmp3(secondarySerial);

    void sleep();

    void initADC()
    {
      ADMUX =
          (1 << ADLAR) | // left shift result
          (0 << REFS1) | // Sets ref. voltage to VCC, bit 1
          (0 << REFS0) | // Sets ref. voltage to VCC, bit 0
          (0 << MUX3) |  // use ADC2 for input (PB4), MUX bit 3
          (0 << MUX2) |  // use ADC2 for input (PB4), MUX bit 2
          (1 << MUX1) |  // use ADC2 for input (PB4), MUX bit 1
          (0 << MUX0);   // use ADC2 for input (PB4), MUX bit 0

      ADCSRA =
          (1 << ADEN) |  // Enable ADC
          (1 << ADPS2) | // set prescaler to 128, bit 2
          (1 << ADPS1) | // set prescaler to 128, bit 1
          (1 << ADPS0);  // set prescaler to 128, bit 0
    }

    void setup()
    {
      initADC();

      pinMode(PB5, INPUT_PULLUP);
      pinMode(PIN_A, INPUT);
      pinMode(PIN_LED, OUTPUT);
      digitalWrite(PIN_LED, LOW);
      pinMode(PIN_MOS, OUTPUT);
      digitalWrite(PIN_MOS, LOW);
    }

    void play(uint16_t track)
    {
      if (digitalRead(PIN_MOS) == LOW)
      {
        digitalWrite(PIN_LED, HIGH);
        delay(500);
        digitalWrite(PIN_MOS, HIGH);
        digitalWrite(PIN_LED, LOW);

        delay(500); // wait for DfPlayer to turn on

        dfmp3.begin();
        dfmp3.reset();
        dfmp3.disableDac();
        dfmp3.setVolume(30);
        dfmp3.setPlaybackSource(DfMp3_PlaySource_Sd);
      }

      dfmp3.playGlobalTrack(track);
    }

    void loop()
    {
      ADCSRA |= (1 << ADSC); // start ADC measurement
      while (ADCSRA & (1 << ADSC))
      {
          // wait till conversion complete
      }

      uint8_t adcValue = ADCH;
      // actually calculate the parameter based off adcValue here. omitted for readability
      play(1);
    }

    // Interrupt Serviceroutine (Pin-Change-Interrupt)
    ISR(PCINT0_vect)
    {
      LemonSerial::handle_interrupt();
    }

    // ADC interrupt service routine
    ISR(ADC_vect)
    {
      ; // noop
    }
```

  [1]: https://arduino.stackexchange.com/questions/93980/how-to-properly-read-adc-on-an-attiny85
  [2]: https://arduino.stackexchange.com/questions/93902/attiny85-with-sleep-and-serial
  [3]: https://i.stack.imgur.com/l5xY8.png
  [4]: https://www.infineon.com/dgdl/Infineon-IRF3708-DataSheet-v01_01-EN.pdf?fileId=5546d462533600a4015355df7cf5193c
  [5]: https://i.stack.imgur.com/yaxSn.png

body:
[@6v6gt][1] was the one who figured out what was missing.

I had to increase the 1Ω resistor between the output pin and gate to 1kΩ and add a 100nF ceramic capacitor between GND and gate. Eventually it worked just as expected.

This is the full code I ended up using. I tried to add enough comments to make it clear what happens.

    #include <Arduino.h>
    #include <avr/sleep.h>
    #include <DFMiniMp3.h>
    #include <avr/interrupt.h>
    #include <avr/power.h>
    // this is just "SoftwareSerial" without blocking interrupts
    // thus you have to call handle_interrupt() from here
    #include "LemonSerial.h"
    #include "mp3notify.h"

    #define PIN_TX PB0
    #define PIN_RX PB1
    #define PIN_MOS PB2
    #define PIN_LED PB3
    #define PIN_A PB4
    // turning the player on and initializing it takes quite a while
    // thus do not go back to sleep immediately after each button press
    uint32_t timeoutMs = 30000;
    uint64_t started = 0;

    // dfplayer api
    LemonSerial secondarySerial(PIN_RX, PIN_TX);
    DfMp3 dfmp3(secondarySerial);

    void sleep();

    uint8_t readADC()
    {
      ADCSRA |= (1 << ADSC); // start ADC measurement
      while (ADCSRA & (1 << ADSC))
        ; // wait till conversion complete

      uint8_t adcValue = ADCH;
    }

    void initADC()
    {
      ADMUX =
          (1 << ADLAR) | // left shift result
          (0 << REFS1) | // Sets ref. voltage to VCC, bit 1
          (0 << REFS0) | // Sets ref. voltage to VCC, bit 0
          (0 << MUX3) |  // use ADC2 for input (PB4), MUX bit 3
          (0 << MUX2) |  // use ADC2 for input (PB4), MUX bit 2
          (1 << MUX1) |  // use ADC2 for input (PB4), MUX bit 1
          (0 << MUX0);   // use ADC2 for input (PB4), MUX bit 0

      ADCSRA =
          (1 << ADEN) |  // Enable ADC
          (1 << ADPS2) | // set prescaler to 128, bit 2
          (1 << ADPS1) | // set prescaler to 128, bit 1
          (1 << ADPS0);  // set prescaler to 128, bit 0
    }

    void setup()
    {
      initADC();

      // set INPUT_PULLUP to reduce current draw
      pinMode(PB5, INPUT_PULLUP); // PB5 is not assigned to any constant
      pinMode(PIN_LED, INPUT_PULLUP);

      pinMode(PIN_A, INPUT); // ADC pin is physically pulled low
      pinMode(PIN_MOS, OUTPUT);
      digitalWrite(PIN_MOS, LOW);

      started = millis();
    }

    /// @brief plays a track on the dfplayer. turns the player on if neccessary
    /// @param track track number to play
    void playTrack(uint16_t track)
    {
      started = millis();

      if (digitalRead(PIN_MOS) == LOW)
      {
        digitalWrite(PIN_MOS, HIGH);
        delay(50); // wait 50ms for DfPlayer to turn on

        // baud 4800 because the attiny runs at 16mhz (8mhz -> 9600)
        dfmp3.begin(4800);
        dfmp3.setVolume(30);
      }

      dfmp3.playGlobalTrack(track);
    }

    void loop()
    {
      uint8_t adcValue = readADC();

      if (adcValue >= 227 && adcValue <= 237)
      {
        // 10k ohm (3.0V -> adc 232)
        playTrack(1);
      }
      else if (adcValue >= 212 && adcValue <= 223)
      {
        // 18k ohm (2.8V -> adc 217)
        playTrack(2);
      }
      else if (adcValue >= 196 && adcValue <= 206)
      {
        // 27k ohm (2.6V -> adc 201)
        playTrack(3);
      }
      else if (adcValue >= 181 && adcValue <= 191)
      {
        // 38k ohm (2.4V -> adc 186)
        playTrack(4);
      }
      else if (adcValue >= 165 && adcValue <= 175)
      {
        // 50k ohm (2.2V -> adc 170)
        playTrack(5);
      }
      else if (adcValue >= 150 && adcValue <= 160)
      {
        // 65k ohm (2.0V -> adc 155)
        playTrack(6);
      }
      // ending up here every loop where no button was pressed. so basically 99.99% of the time
      else
      {
        // started gets set to millis() everytime a track is played
        if (millis() - started > timeoutMs)
        {
          // sleep if some time has passed without input (see timeoutMs)
          sleep();
        }
      }
    }

    // sets the device into POWER DOWN mode.you can probably tune it to be more efficient
    void sleep()
    {
      digitalWrite(PIN_MOS, LOW);

      // pin change interrupt
      PCMSK |= bit(PIN_A);
      GIFR |= bit(PCIF);  // clear any outstanding interrupts
      GIMSK |= bit(PCIE); // enable pin change interrupts

      set_sleep_mode(SLEEP_MODE_PWR_DOWN);
      power_all_disable(); // power off ADC, Timer 0 and 1, serial interface
      sleep_enable();
      sleep_cpu();
      sleep_disable();
      power_all_enable(); // power everything back on
    }

    // Interrupt Serviceroutine (Pin-Change-Interrupt)
    ISR(PCINT0_vect)
    {
      // the SoftwareSerial does not block any interrupt pins anymore and thats why we have to call it from here
      LemonSerial::handle_interrupt();
    }

    // ADC interrupt service routine
    ISR(ADC_vect)
    {
      ; // noop
    }

This is a schematic from how everything is set up now. This is the first time I drew a _real_ schematic so I hope it's clear whats going on

[![enter image description here][2]][2]

  [1]: https://arduino.stackexchange.com/users/31043
  [2]: https://i.stack.imgur.com/NMhOf.png


message:
Unable to control motor with ESP32 using logic level shifter

I am using an ESP32 a TB6600 micro stepper, and a Nema 23 stepper motor, I am trying to control the motor with the esp32 but the TB6600 requires a 5v signal, I tried to fix this by using a logic level converter (specifically [this](https://www.amazon.com/dp/B07LG646VS?psc=1&ref=ppx_yo2ov_dt_b_product_details)) but when I attempt to control the motor I get a very slight hum out of the motor and no movement.

The motor controller and motor both work as I tested it with an Arduino Uno.

```
void setup() {
  pinMode(15, OUTPUT);
  pinMode(16, OUTPUT);
  pinMode(17, OUTPUT);
  digitalWrite(16, HIGH);
}

void loop() {

  digitalWrite(15,LOW);
  digitalWrite(15,HIGH);
  digitalWrite(17, HIGH);
   delay(200);
}
```

Picture of Circuit
[![Arduino circuit][1]][1]

Circuit Diagram
[![Circuit Diagram ][2]][2]

  [1]: https://i.stack.imgur.com/3W6yZ.jpg
  [2]: https://i.stack.imgur.com/huZA4.jpg

body:
I haven't used this kind of system, so I'm just guessing. But in the Manual it says:

> When“EN”is in the valid state, the motor is in a free states (Off-line
  mode). In this mode, you can adjust the motor shaft position manually. When“EN”is
  in the invalid state, the motor will be in an automatic control mode.
([Source][1]).

It is not entirely clear what they mean by "manually". But you set pin 17 to HIGH and the result would fit the description. Maybe set 17 to LOW?

On another note: there is no delay/time between `digitalWrite(15,LOW);` and `digitalWrite(15,HIGH);`. This will create a very short pulse, which might be too short for the level shifting electronics to translate. Some delay() or equivalent non-blocking code between the two writes could help.

  [1]: https://www.makerguides.com/wp-content/uploads/2019/10/TB6600-Manual.pdf


body:
I figured out the problem, the logic level switcher I was using is meant for I2C  sensors, and thus was only capable of converting open-drain signals and cannot perform push/pull level translation meaning it was not able to provide a data signal to the micro stepper. I replaced the shifter with a shifter capable of push/pull translation specifically [This][1]

  [1]: https://www.sparkfun.com/products/12009