text:
Rotary Encoder with interrupts - erratic behaviour
I'm trying to change my working rotary encoder code (stolen from here) to an interrupt-based code on my Mega2560. The trouble is that the result behaves very erratically, even though the physical setup is exactly the same as the working code. The determined encoder incrementation is jumping back and forth, when monotonically turning in one direction.
The interrupt-based code currently looks like this:
const long int baudrate = 115200;

const int debounceTime = 5;  // time in ms, in which the interrupt is not reacting. Starting at the first trigger of the switch.

const int clk1Pin = 19; // clkpin (signal A)
const int dt1Pin = 18; // dt pin (signal B)
const int sw1Pin = 4; // switchbutton pin

volatile int encoder1Val = 1500;  // what i want
volatile int firstSwitchTime = 0; // helper variable for debouncing
volatile int cnt = 0; // counters for debugging
volatile int cnt2 = 0;
volatile int cnt3 = 0;
volatile int cnt4 = 0;

volatile bool switchlock = false; // flags for debouncing and readout flow control
volatile bool readoutflag = false;

int cycletime;

void setup() {

  // Set up pins
  pinMode(clk1Pin, INPUT_PULLUP);
  pinMode(dt1Pin, INPUT_PULLUP);
  pinMode(sw1Pin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(clk1Pin), encoder1Decoding, CHANGE);

  Serial.begin(baudrate);
}

void loop() {

  // only [print the data] and [release encoder1Val incrementing lock] after the debouncing period has passed
  cycletime = millis() - firstSwitchTime;
  if (cycletime > debounceTime) {
    readoutflag = true;
  }

  if (readoutflag == true && switchlock == true) {
    switchlock = false;
    readoutflag = false;
    Serial.print(encoder1Val);
    Serial.print(",");
    Serial.print(cnt4); // Total amount of interrupt calls between readouts
    Serial.print(",");
    Serial.print(cnt); // Amount of effective interrupts
    Serial.print(",");
    Serial.print(cnt2); // Amount of "increment branch" calls
    Serial.print(",");
    Serial.print(cnt3); // Amount of "decrement branch" calls
    Serial.println();
    detachInterrupt(digitalPinToInterrupt(clk1Pin)); //ensure atomic action
    cnt = 0;
    cnt2 = 0;
    cnt3 = 0;
    cnt4 = 0;
    attachInterrupt(digitalPinToInterrupt(clk1Pin), encoder1Decoding, CHANGE);
  }
}

void encoder1Decoding() {
  cnt4++;
  // if outside of debounceTime: change encoder1Val
  if (switchlock == false) {
    switchlock = true;
    firstSwitchTime = millis(); // remember the first time, the interrupt changed in a bouncing group
    cnt++;
    // .. decoding encoder ..
    if (digitalRead(clk1Pin) == digitalRead(dt1Pin)) {
      encoder1Val++;
      cnt2++;
    } else {
      encoder1Val--;
      cnt3++;
    }
  }
}

It is relatively complicated for debugging reasons, as will become clear in a moment. When turning the encoder counter-clockwise, the resulting output is this:

Value, Total Interrupts, Effective Interrupts, Increment Branch, Decrement Branch:
1501,2,1,1,0
1500,33,2,0,2
1499,0,0,0,0
1500,1,1,1,0
1499,19,2,0,2
1498,24,0,0,0
1499,5,2,2,0
1500,0,0,0,0
1501,15,1,1,0
1500,16,2,1,1
1501,43,0,0,0
1500,3,1,0,1
1501,1,1,1,0
1502,6,1,1,0
1503,3,1,1,0
1504,2,1,1,0
1505,1,1,1,0

The values should increase monotonically. They don't, so what's happening?

The first readout makes sense: One successful interrupt call, one increment branch run, one value increase.
The second readout is already strange: two decrements, but only one less value?
The third is completely inexplicable: a decrement without the interrupt even being called.

I'm completely puzzled. Anybody got an idea where to start?
What I tried so far:

Searching the web. Seems to be a new problem.
Using the encoder without interrupts ("polling"). Works flawlessly, but is speed limited.
Explicitly analyzed the bouncing period of this rotary encoder using interrupts. Worked flawlessly. Result is: BouncingTime is mostly less than 5ms (very few outliers).
Plotted the data coming from clk and dt (x-ticks are 1ms, they're overlapping):

There is one bounce visible in the beginning, but the rest seems quite alright.
As I'm completely at a loss, any help is much appreciated!
Edit 2023-07-25:
The most important question is, why the ISR keeps on decrementing encoder1Val, even though i only turn in positive direction. This happens in all variants of the code. An absolutely stripped down version with the same behaviour can be found below:
void loop() {
  Serial.println(encoder1Val);
  delay(500);
}

void encoder1Decoding() {

  if (millis() - firstSwitchTime > debounceTime) {
    firstSwitchTime = millis();

    if (digitalRead(clk1Pin) == digitalRead(dt1Pin)) {
      encoder1Val++;

    } else {
      encoder1Val--;

    }
  }
}

Result:

1500
1494
1497
1502
1513
1515
1518
1515
1516

remove debounce code ... each bounce should produce a +1 followed by a -1  ... think about what happens if you ignore the +1

Your code seems to have lost some of  the basic simplicity of the original (non-interrupt version) which you linked but I guess it has grown during your debugging efforts. You haven't said if you are using a raw encoder or one with debouncing/filter circuitry such as here: https://www.aliexpress.com/item/1005002845325794.html. The one in your linked article appears only to have pullup resistors but no capacitors. Your software debouncing is handling only bounces from clk1Pin not dt1Pin.

@jsotola: I'm trying to prevent jitter in the output, as the signal will be transferred to servos.

@6v6gt: It is a simple one without debouncing afaik. I only use the pullup resistors of the Arduino. Do you suggest, I should add some capacitors? Only clk1 is debounced, as it is the only one with the interrupt attached. I will expand the code once using clk1 works.

@Malibu I'm trying to prevent jitter ... maybe something like this might work ... respond to A state change, then ignore any other A state changes until B changes ... basically, accept only the first clock pin transition for every data pin change

@jsotola: Thank you for the suggestion. Sadly it seems not to improve the situation. I have also added an edit to the question, because the most pressing question is: why does the code decrement the values, even though the encoder is only turned in one direction.

volatile int encoder1Val on a Mega is a 2 byte integer which you are updating in an ISR and reading in the loop() here Serial.println(encoder1Val);. This is a non-atomic operation and you could get unlucky in that the read operation is corrupted during a simultaneous interrupt. Temporarily suspend interrupts during which time you make a copy of encoder1Val then later print the copy.

Ok, thanks! I tried detachInterrupt(..); valuesafe = encoder1Val; attachInterrupt(..); Serial.println(valuesafe). The behaviour didn't change, though.


text:
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. and I tried this code:
#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:
#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?

Have you set the pins properly? Try doing:
  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.

source: Stack Exchange

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/

sort: votes


text:
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

You've mentioned SPI and ADC - where does serial come into this?

The DFPlayer uses Serial.  I'm not sure where SPI is coming into this.  Perhaps the poster is confused about what SPI is.

Are you getting stuff from dfplayer, or sending stuff to it? If you are sending it to the player, I don't see where the interrupts are needed.

@NickGammon I updated my post to answer your question. Thank you

@Delta_G I updated my post to clarify the situation. Thanks

SoftwareSerial takes over all of the PCINT interrupt vectors.  That's all the pin change interrupts.  Your sleep code is wanting to use one of those interrupt vectors as well, likely as a wake signal.  The answer is going to either be modifying SoftwareSerial to only use the one vector it needs in your particular case, or finding another soft serial library that doesn't take them all.  I don't know which library would fit that bill so I'll just leave this a comment and not an answer.  Perhaps if someone knows the right library here they can answer.

Thanks to @Delta_G I was able to figure out a solution.
I took the source files of the SoftwareSerial library from github 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.

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.

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/


text:
ESP32 - resetting BT(classic)-Discovery variables ends in memory chaos
I want to search for bt devices in each loop(), store them and query them one by one. This works fine so far. However, when I try to reset the corresponding variables, I get the following error: "Guru Meditation Error: Core  1 panic'ed (LoadProhibited). Exception was unhandled."
This is to ensure that new devices are found rather than iterating over old (no longer existing) devices.
// BT
#include "BluetoothSerial.h"
BluetoothSerial SerialBT;
#define BT_DISCOVER_TIME 10000

//BT_DEVICES
BTScanResults* pScanResults;
String** deviceNames;
int numDevices;

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

  //BT
  SerialBT.begin(DEVICE_NAME, true); // device is master
}

void loop() {
  btDiscover();
  requestData();
}

void btDiscover() {
  pScanResults = SerialBT.discover(BT_DISCOVER_TIME);

  if (pScanResults != nullptr && pScanResults->getCount() > 0) {
    for (int i = 0; i < pScanResults->getCount(); i++) {
      BTAdvertisedDevice* pDevice = pScanResults->getDevice(i);
      if (pDevice != nullptr) {
        String deviceName = pDevice->getName().c_str();
        if (deviceName.startsWith(SLAVE_NAME_PATTERN)) {
          addDeviceName(deviceName.c_str());
        }
      }
    }
  }
  SerialBT.discoverClear();

}

bool deviceNameExists(const String& name) {
  for (int i = 0; i < numDevices; i++) {
    if (deviceNames[i]->equals(name)) {
      return true;
    }
  }
  return false;
}

void addDeviceName(const String& name) {
  if (!deviceNameExists(name)) {
    deviceNames = (String**)realloc(deviceNames, (numDevices + 1) * sizeof(String*));
    deviceNames[numDevices] = new String(name);
    numDevices++;
  }
}
void requestData() {
  for (int i = 0; i < numDevices; i++) {
    SerialBT.connect(*deviceNames[i]);
    SerialBT.println("REQUEST");
    delay(100);
    String message = SerialBT.readStringUntil('\n');

    StaticJsonDocument<200> jsonDocument;
    DeserializationError error = deserializeJson(jsonDocument, message);
    if (error == DeserializationError::Ok) {
      serializeJson(jsonDocument, Serial);
      Serial.println();
    } else {
      // Fehler beim Parsen der JSON-Nachricht
      Serial.println("ERROR");
    }
    SerialBT.disconnect();
  }
}

i tried something similar to this:
delete pScanResults;
    pScanResults = nullptr;
  }

  delete[] deviceNames;
  deviceNames = nullptr;
  numDevices = 0;

how can i realize this? i tried vectors instead of String**, but that triggered the problem instantaneously (without the ressetting "function")
I have also tried the library "ListLib.h". When I use the Clear() function of this library, I get no messages after the first 2 lines. (hangs up?)
mh ok... if i use btDiscover() only (without arrays and so), it works as expected. but if i add my requestData() inside of btDiscover(), i get only once message from each client... idk
ok maybe discover and connect/disconnect dont work together?
mh when i use addDeviceName(deviceName.c_str()) with a variable, i get only one time the messages of clients. if replace the variable with a String, then it works as expected.

for now, i have moved the discover part to setup() and every 30minutes the esp is restarted... it's not the best approach, but it works... conclusion: discover and connect do not work together

Welcome to SE/Arduino! Please take the [tour] to learn how this site works, and read "[ask]". -- This sounds like a memory overflow problem. What exception is unhandled? Doesn't the ESP tell you more? Are you sure your memory management is correct? (I do not look through code without knowing the exact error message.) -- Please [edit] your question if you have new information, do not post comments. This is not a forum.

Hi @the busybee, sorry for that misguided post...I will do that again. I was a bit stumped and desperate. My troubleshooting started with the memory overflow (I "fixed" it with delay(XXX)) until I finally came to the conclusion that the discover() function is not usable after a connect(). Because of that i moved the discover()-function to setup() and for the moment I restart the ESP32 regularly. Not nice but it works. The memory overload was not the real problem.


text:
"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....
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

add a flag that signals that the function already ran ... it is unclear what the actual problem is ... if you have a real world example  then add it to your post

I guess that for a web browser application, when you register an event in a script, say a button press, that in a loop (hidden somewhere) that button object will be tested regularly and, if pressed, the event handler will be executed. With the Arduino there is no run time system to support such things directly so if you want to test a button regularly, you have to do so explicitly in a loop.

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:
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:
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:
// 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 Arduino tutorial shows how to handle
periodic events
Reading Serial on the Arduino is a tutorial showing how to
buffer serial input in order to handle one full message at a time
Bounce2 is an example of a button-debouncing library
The Finite State Machine 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

Edit: Regarding the example code you posted, I would like to rewrite
your loop() like this:
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.

Great answer, but I'd just make a modification in your periodic example. I think usually what you prefer when doing a periodic check is to have something periodic, not something guaranteed to be above the time. I mean, if the period is 1 second and the first cycle is 1.1s then I'd prefer the second to be 0.9s to "catch up" rather than 1s (so delays don't add up). So usually I prefer to write last_event_time += event_period;.

@frarugi87: Edited the answer, thanks.

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:
int main() {
    setup();
    for (;;) {
        loop();
    }
}

Therefore, your example can be:
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:
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.

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

@NeuberOliveira See my edit. It is always better to tell us your complete intent in the question. ;-)

You don't have to use their "setup" and "loop" paradigm, you know. This will work:
#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.


text:
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
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 ?

Where do you think those string literals are stored?

@KIIV in SRAM ?

SRAM is volatile, meaning it can't remember anything without being powered

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:
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:
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:
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.
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.
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.

Thanks for your contribution.

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.

That's why the F("macro") and overloaded methods in Arduino core exists to avoid this RAM "spam". However Atmega4809 doesn't need it as it has all memories mapped into single address space. Or ARM based boards doesn't need this.

@JRobert, Interesting behavior. So everything in the .data segment eats from the flash area, right?

@embeddedstack, the flash memory in MCU is the 'hard drive'

Yes - the .data segment contains the variables for which you have specified initial values. Those values have to be stored in non-volatile memory to initialize the variables in RAM before execution begins.


text:
ESP32 Shows Incorrect Input Voltage From Analog Pin
I have an esp32 WROOM-32 connected to a MQ9 gas sensor to GPIO35. Both are powered separately. measuring the output from the sensor directly using a multi-meter shows a constant reading of 0.145 V but the readings on esp32 shows 3.3V and if fluctuates too much.
The circuit:
MQ-9 AO -> voltage divider (using 1k and 2.2k ohm) -> ESP32 (GPIO35)
Sample Code:
void setup() {
  Serial.begin(9600);
  analogReadResolution(11);
  analogSetWidth(11);               // 11Bit resolution
  analogSetAttenuation(ADC_0db);
}
void loop() {
 int ADC = analogRead(35);
 float volt = (ADC * 3.3) / 2045;
 Serial.print("Volt : ");
 Serial.println(volt);
 Serial.print("Analog : ");
 Serial.println(ADC);
 Serial.println("");
 delay(1000);
}

Image of the error:

please do not post a picture of text ... post the text instead, same as the code

the circuit description does not say anything about a ground connection


text:
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.

as always, it is LED_BUILTIN

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.


text:
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

This sounds like homework and the point of the homework is to learn parsing. And the delineation character is a semicolon.  Is that correct?

yes bro, using delimiter ; for command multiple condition. help me

You might want to get used to visit the Arduino library reference to learn what is possible and how to use it.
For your case, you are interested in the method readStringUntil().
The reading, understanding, experimenting, debugging, and finishing is left as an exercise to the user.

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.

There is a quicker way in C++ to parse through a string based on a given delineating character.  But it abstracts you from what is really going on.  Which is likely what is outlined in this answer.

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).


text:
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.

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?

Start with board with native USB and not UNO with USB-to-serial on different chip. Arduino leonardo for example

please do not post a picture of text ... post the text instead

Thank you @KIIV, great answer! I googled your guide and found that some types of Arduino haven't built-in USB communication. As new question, is any way to work with Uno, as well?

Thank you @jsotola for your hint about site's laws, I'm not so familiar with them. The question and its text has been edited.

I thought I answered this question.  Oh, I did... https://stackoverflow.com/questions/76755556/my-arduino-uno-ps-2-to-usb-works-only-in-serial-monitor-not-in-other-windows-app

I appreciate you @Delta_G, I sent a comment to your answer there.

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. This nice library uses bit-banging 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.

I learned new things from your answer, @the busybee. Thanks.

@Khabarkhaan You might want to take the [tour] to learn how this site works. For example, you are not supposed to comment "thanks!" but to mark an answer as accepted. This is the best way to help future visitors on the same issue.


text:
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.

how frequently?

perehaps you better first collect all bit changes and update the value only once.

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:
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.

Note: unprogrammed eeprom/flash values are 0xFF so if you left it unprogrammed it might not work as intended


text:
Confusing language on arduino docs about powering via 3V3/5V pins
I'm reading about powering alternatives for the arduino board, and I have run across two confusing sentences in Section 5, powering via 3V3/5V pin. First, it says:

3V3 and 5V pins can also be used as power inputs if no regulated power supply is connected through the other power inputs (USB port, barrel jack connector or VIN pin).

But then right afterwards, it says:

Although 3V3 and 5V pins can be used as power inputs, it is not recommended if no power supply is connected through the USB port, the barrel jack connector, or the VIN pin.

(emphasis mine)
Which is correct? When powering via the 3V3 or 5V pin, should I have a different power supply connected elsewhere, or not?

they are both correct ... one says you can do this ... the second one says but it is not recommended that you do this ... similar to  you can run across the street ... but it is not recommended that you run across the street .... they are basically saying don't use the arduino as a power supply if you can avoid it

The issue appears to be backfeeding the voltage regulator which is connected to the 3.3v or 5v pins. Some voltage regulators don't like it (see https://electronics.stackexchange.com/questions/110314/how-can-i-tell-if-my-power-supply-regulator-will-accept-backfed-current).


text:
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)

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.
#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 for ideas about doing that.

Reference
I got memdebug.h (and memdebug.c) from Andy's workshop - Debugging AVR dynamic memory allocation

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 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.

Very good. I was wondering why the overhead was only two bytes, since I thought you might need a length and a pointer, but only storing the length means you can deduce the address of the next chunk. Then when you free up chunks apparently there is a "free list", and they use the (now abandoned) part of memory to record where the next free chunk is. Presumably therefore the minimum amount that gets allocated is two bytes (plus the length).


text:
Ability to connect 2 or more w5500 Modules and deal with them as objects
I wish to create a rudimentary ethernet in/out - switch/hub where I can (sort of) daisy chain my boards. (I don't wish to use a ethernet switch/router/hub)

One port would be acting as server
The other would be acting as a client
(and forward any messages received on the first port after some processing/modification)

I am using an STM32 Bluepill with 2 Mini w5500 Modules (adafruit) connected via SPI. Nothing else is connected to SPI. All the other GPIOs are connected to relay drivers.
I use the Ethernet library. I have made sure they are connected to different CS pins and I have tried to assign Ethernet.init(); before doing anything with specific Ethernet modules but that keeps disconnecting and is working very unreliably.
I understand that some modification in the library might be needed (I, by no means could figure out how and what).
References:
https://forum.arduino.cc/t/2-network-shields/111509
https://forum.arduino.cc/t/connect-multiple-ethernet-shields-to-arduino-uno-using-spi/284008/16
But no one seems to have gotten it to work. Please help.

it is not possible with the Arduino Ethernet library

Thanks @Juraj, I realized the same. Is there another way or has anyone modified this library to achieve this?

I would use a hub or Ethernet splitters. Ethernet wiring is a bus, but for practical reasons the bus was moved into hubs and  with that the topology looks like a start topology.  Then switches added optimized packets routing. https://en.wikipedia.org/wiki/Ethernet#Evolution

@Juraj Alright then, I feel it would be worth someone's while to modify the library for this, but for now I am convinced that the Arduino ethernet library isn't going to do it.


text:
Is there a way to use ESP8266 in promiscuous(monitor) mode and see the the wifi packets?
I didn't find much documentation about ESP promiscuous mode (just from the espressif sdk although I'm using ArduinoIDE https://docs.espressif.com/projects/esp8266-rtos-sdk/en/latest/api-reference/wifi/esp_wifi.html )
So from seeing some sample codes ( https://github.com/spacehuhn/ArduinoPcap/blob/master/examples/esp8266_pcap_serial/esp8266_pcap_serial.ino and https://www.youtube.com/watch?v=3Ac6X6ZBQ0g ) the esp8266 doesn't work properly for some people but for others (https://www.esp8266.com/viewtopic.php?t=12127) it seems to work properly, so I don't know if it's a hardware limitation.
I tried making a simple sketch to try it for my NodeMCU 0.9 and compared the packets from wireshark and I saw the majority of the packets come incomplete or with anomalies
#include <ESP8266WiFi.h>
#include <Arduino.h>

extern "C" {
#include <user_interface.h>
}

static void ICACHE_FLASH_ATTR handlePacket(unsigned char* buf, uint16_t len) {
  for (int c=0; c < len; c++){
    Serial.printf("%d:%d  ", c, (int)buf[c]);
  }
  Serial.println();
}

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

  wifi_set_opmode(STATION_MODE);
  wifi_promiscuous_enable(0);
  WiFi.disconnect();
  wifi_set_promiscuous_rx_cb(handlePacket);
  wifi_set_channel(6);
  wifi_promiscuous_enable(1);
}

void loop(){}

From the example code that works, the guy seems to use esp8266 sdk, is the ArduinoIDE a limitation for this monitor mode thing?
https://bbs.espressif.com/viewtopic.php?t=3072
https://github.com/kieransimkin/esp8266-freedom

Printing to serial from an interrupt is a very bad idea. Real time capture and output of network packets to serial is bound to run into the speed limits of the serial port, so incomplete and/or anomalous output is not unexpected.

Other than what @StarCat mentioned, I think you use the wrong macro ICACEH_FLASH_ATTR, it is supported to be ICACHE_RAM_ATTR.

@hcheung I was just following an example, I didnt really know what that mean, but from here ( https://stackoverflow.com/questions/58113937/esp8266-arduino-why-is-it-necessary-to-add-the-icache-ram-attr-macro-to-isrs-an ) it seems that the best for often called functions is to not have any cache at all


text:
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

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

it depends on the circuit that the digital pot is part of ... a question about incorporating a digital pot into an existing circuit is not related to the Arduino ... it belongs at https://electronics.stackexchange.com/questions

In addition to jsotola's comment, the data sheet of the digital pot will give you the answer, once you know what the operating conditions are, which depend on the specific circuit.

I don't know why you guys closed this question. It's about connecting a digital pot to an Arduino. Would you prefer questions about connecting nothing to an Arduino?

(Regarding the edit to the question) See my answer. You would need to connect +12V (on the right of your circuit) to V+ and RH. RW is just the wiper. It needs a voltage input somewhere.

@thebusybee Comments are for clarifying the question. Not to tell people to read the datasheet. If that's all you have to say, say nothing.

I'm not sure your circuit diagram makes sense. You have a pot symbol with nothing connected to the wiper.

Assume for the moment you are using a physical pot. They have three terminals, not two, because they are a voltage divider. So, your circuit should show three connections to the pot. See Potentiometer - Wikipedia.

@NickGammon Since this question is supposed to be asked on SE/EE, I refrained to write an answer and gave a constructive hint how to proceed, even to avoid to post a question at all. The question is clearly off-topic. I would be glad if such questions would not receive positive feedback by an answer.

@thebusybee They spot the word Arduino and migrate it to here. So it is a lose-lose situation.

@NickGammon Oh, dear. Reading skills are apparently being lost. Help vampires are sucking my blood.

your diagram shows a variable resistor, not a potentiometer ... how is the original circuit connected?

If you look at the datasheet 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.

Thank you for your answer. I have updated my circuit diagram. I am getting an open connection in place of pot.
I have not connected RH and V bias now. Is it because of that? I don't have much knowledge in circuits. Please spare me if I am wrong

Also A0 and A1 needs to be connected to Arduino to which pins of Arduino as I already connect the SDA and SCL of pot to A4 and A5 (I2C) of Arduino

Just connect A0 and A1 to Gnd.  They modify the I2C address, if zero (Gnd) it is the published address. The slave address is 1010xx where xx are A1 and A0. So if they are grounded the address will be 101000 in binary (40 in decimal).

What is V bias, that you refer to?

V+ of the digital pot is what I meant. Thanks a lot for your support. I am a beginner and I wasn't sure about the connections even. Thanks again for all the explanations.

@Teena If my answer has helped please tick the "Accept" arrow to indicate to other people that the answer has been accepted by you, and was helpful.


text:
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?

You can use sscanf

It would be easier to see you confusion if you actually showed some code.

Welcome to SE/Arduino! Please take the [tour] to learn how this site works, and read "[ask]". You are supposed to do a good part of research on your own. So please [edit] your question and add what your research revealed, and why it did not help you. Hint: a quick web search on "c++ convert string to integer" give a lot of good hits...

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).

Many thanks! Hopefully I can try it out within my code today, if not it's going to be next week :)

I have a question though: Why are you using globals in this case? Wouldn't it be better to have a pure function by removing the buffer from global scope and adding into the toMAC-function? That's what I changed anyways

@HaraldLesan: If you make MAC_buffer local to toMAC(), you have to make it static, otherwise you would be getting back a pointer to unallocated stack space, which you cannot dereference (it's undefined behavior). But then, toMAC() is not pure. If you really want it pure, make it return the array encapsulated inside a struct.

Thank you @EdgarBonet, as always your contributions are always a great addition :) never thought about encapsulating in structs, I'll have to dig a bit deeper

@HaraldLesan As Edgar said, putting it inside the function will remove it from memory when the function exits, so you won't be able to use it outside. If you really want to avoid that global, the solution I would use is to allocate it outside and pass it to the function: uint8_t* toMAC(String s, uint8_t *MAC_buffer, uint8_t MAC_length). But generally speaking I avoid dynamic memory on uC, so usually buffers are usually global in my code.

I might be nitpicking here, but charToHex should probably be called fromHexChar or similar. We're not converting anything to hex, we're converting from hex.

@tkausl honestly I had a similar thought when writing, then did not found any valid name (it is a char to an integer, but how to express that it needed to be in hex?). I did not think of naming it "from" something. I'm changing it :) thank you

@frarugi87: You can still allocate the buffer outside and pass it to the called function, without using heap. It merely has to have a lifetime longer than the called function. If the buffer is local to the calling function, a) it will still be invisible to other functions; b) will not use heap; and c) will be de-allocated when the calling function returns.

@JRobert Yes, the modification to allocate it outside and simply pass it to the function was what I wrote it in a comment above. Thank you for your comment :)

That was specifically to address "avoid dynamic memory".; that automatic memory is a another non-global option.


text:
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.

Did you update windoz or the Arduino IDE?

@VE7JRO No, one minute it was working fine and the next I try to upload and it doesn't work

are you saying that you were able to upload a sketch, and then a few minutes later, you were not able to upload a sketch? ... it could be caused by the sketch that uploaded successfully

@jsotola yes, that is exactly what happened, I am looking into issue with the watchdog timer but any other ideas would be helpful

You posted an answer saying it was a problem with the USB driver, which you then deleted. Was that the problem or not? Knowing this saves other people from trying to solve a problem which is already solved.

In short: fake CH340 + latest drivers stopped being compatible (but unlike FTDI few years ago they didn't brick the fakes, it's just not working)

See Have I bricked my Arduino Uno? Problems with uploading to board.
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".

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.


text:
Using file.seek() with arduino ide
I have in my code in c, this function:
    fseek(file, 0, SEEK_SET);

I need to use the same function with Arduino ide. Is this correct?
    file.seek(file.size());

Or what is the alternative function in Arduino ide?

https://www.arduino.cc/reference/en/libraries/sd/seek/

Just try it and see what happens.  That will be way faster than asking.

It can be faster to look up the documentation than wait hours for someone to answer.

OT, to clarify technical terms: The Arduino IDE is just that, an integrated development environment. It does not provide functions or classes, it just recognizes the names and therefore give you some support. The real thing you mean are the Arduino libraries, the reference of which you should bookmark in your browser. However, an installation puts all of this on your computer. (There is more, for example the compiler system...) You can use each without the other.

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.


text:
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.

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 to be the most informative. Adafruit also has a guide here
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 but the TL;DR is:

git clone git@github.com:PaulStoffregen/MotionCal.git
brew install wxwidgets
Open the Makefile
Comment the line OS = LINUX
Uncomment the lineOS = MACOSX_CLANG
Under else ifeq ($(OS), MACOSX) add -arch arm64 to the CFLAGS
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:
#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


text:
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

Not knowing what you have you first need to determine if it will be wired or wireless. Then narrow it down, wireless could be wifi, bluetooth, etc. After that you then need to determine if you want it on one arduino such as an ESP32 or use shields/modules..

start by learning how to display "Hello World" in a web page ... forget about the pump and the pH sensor for now

@Gil Thank you, my question is now updated.

@jsotola Thank you, I already know the html and css in making a web page. What else do I need to learn? like the backend, on how to get the data?

Is this web server going to be on the Arduino or ESP32?

@NickGammon you mean if it is going to be on the Arduino, I should have an ethernet shield right?
I'm actually adjusting my set up to which is more doable for me.

I was just asking. Where do you intend the web server to be? You could conceivably send data to a PC, and have the web server there. To do it on the Arduino, yes you would need an Ethernet shield. It has to accept incoming TCP/IP connections somehow.

Thank you @NickGammon, 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.

@JohannesRemotigue how to get the data? ... that's what I'm talking about ... learn how to send "Hello World" from arduino to webbrowser

This isn't a forum. Please edit your question to clarify what you are asking, don't ask additional things in comments.

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.


text:
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.

Which part died? The NodeMcu or the motor driver?

the wiring diagram is not enough ... please provide info about the motor driver module ... it is unclear how the motor driver is getting 5 V ... looks like the motor driver and the servo are pulling power from GPIO D3

Based on https://lastminuteengineers.com/l298n-dc-stepper-driver-arduino-tutorial/ I'd have (a) ensured that the jumper for the 5v regulator was in place and (b) powered the NodeMCU VIN through the +5v of the motor driver board instead of the 7.4 volts from the battery pack. Have you removed the ENB/+5V jumper ?  What part got hot ? The regulator or the ESP8266 module or what ? Did you simultaneously connect a USB cable to the NodeMCU ?

Hint: A Power Supply the Arduino is Not!

@jsotola Motor Driver module is L298N. and D3 is the ENA pin for Speed regulation.

@PMF The nodeMCU. it got really hot and stopped working. It still gets detected by the pc, but cant upload code, and ESP8266 Module in it gets extremely hot.

@6v6gt Yes, the 5v reg. jumper is in place. previously i used a buck converter to supply 5v to arduino, but the car's motor was not working with its full potential. Now the car's performance was really good. Why this has happeded? from the information i got, the nodemcu is capable of handling a voltage upto 12v. ... :( i have removed the enb 5v jumper for speed regulation. The nodemcu esp8266 has got hot and died. No didn't connect Usb cable along with other power supply.

@NonTechGuyinTech  the L298N is one of the components in the motor driver module ... L298N is not the module itself

@jsotola Could you please tell me what you call an L298N Based motor control module ???

you just did in your comment ... L298N Based motor control module ... the point to my previous comment is that saying it's an L298N module does not specify which actual module it is ... a person cannot expect all of the L298N based modules to be the same ... information is needed, about the module you are using

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.

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.

The Arduino Cookbook is a good reference to have. First skim it then zero in on sections that are pertinent to your project.


text:
Emulator for Arduino Nano 33 BLE Sense and TinyML
I am learning to work with TinyML, and I have Arduino Nano 33 BLE Sense board connected to my desktop.
I would like to continue working from my laptop(s) even when I don't have a board with me.
Do you know if there is an emulator for this board that I could use to dome basic programming and exercises?


text:
Uno R4 WiFi board is online but no OTA option for upload
I have followed these instructions to start using my new Uno R4 WiFi with the Arduino IoT Cloud. Everything works fine (even though sometimes the example screens do not exactly correspond with the actual screens). My Uno R4 WiFi is online and the online dashboard can switch the LED on and off even with the board powered from a battery and not physically connected via USB. The only problem is that I still cannot upload a sketch via WiFi. The instructions say:

Once in the sketch tab, let’s open the board's drop down menu. There,
a new option to connect our board should be available. The name of the
board configured for the cloud will appear, followed by the
Over-the-Air option.

But that drop down menu is not available and if I disconnect the USB I get No associated device found even though in Things-Setup the board is shown as being online.
Can someone explain what I am missing here? Or perhaps the Uno R4 WiFi is not compatible with the IoT cloud or the online IDE but that seems unlikely for a heavily advertised new WiFi product from Arduino.

it is not implemented yet for Uno R4

Where did you get the information that it is simply not implemented? It just seems odd to me as Arduino are adverising this device and its WiFi capabilities heavily yet I have not seen any mention that uploading per OTA is not implemented

@Juraj The Uno R4 WiFi is selectable in both the IoT Cloud and online editor, and sketches can be uploaded to it via USB. Only the OTA port appears to be a problem.

I looked into the library https://github.com/arduino-libraries/ArduinoIoTCloud/tree/master/src/utility/ota


text:
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

you forgot to connect a resistor between analog input and ground ... research voltage divider

Are you using an Arduino core which does not support analogRead() or is there another reason why you are directly reading ADC registers ? The ADC is 10bit  so can read analog values up to 1023. Does your application allow for pressing two or more buttons simultaneously? If you have a multimeter you could check the voltage between the analog pin and ground when a button is pressed.

Funnily enough, someone else also wanted to connect six buttons to an ATtiny85 to "Connect 6 buttons with 6 different resistors to a single ADC pin of the controller". It's an amazing coincidence!

@NickGammon I unfortunately can’t tell if you’re trying to be funny or sarcastic. It’s the same project but a different question.

Adding a schematic to your question, showing at least everything connected to the A/D pin, would help!

"I unfortunately can’t tell if you’re trying to be funny or sarcastic . . . ". This does not help. Please focus your efforts on providing responses to the followup questions you have been asked and are, as yet, unanswered. It is, incidentally, in the nature of school assignments that multiple instances of the same question can appear in various guises.

@6v6gt It wasn't my intention to be sassy. I was just confused by nicks comment so I tried to explain me

there is no schematic diagram in the question ... it is impossible to determine how the OP connected everything ... voting to close for being unclear

TBH I was indeed wondering if it was an assignment. Also maybe the previous question about the same thing may have helped, so it was a pointer to check it out.

@NickGammon I guess this is going too far here but it's meant to become a toy for my daughter. Not an assignment

OK, sorry for doubting you.

Unfortunately @jsotola 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

a comment is the only thing that was appropriate ... only a guess could be provided because of lack of information in the question

I don't see six buttons here. Is this a work in progress?

@NickGammon I just inserted different resistors to test each of them one by one. That was easier than setting up 6 buttons and was good enough. Just needed to know if it works in general

There seem to be some gaps in your ranges. For example, what if adcValue is 238? But perhaps that is deliberate. You could probably rewrite as only doing greater-than tests. For example, >= 227, then if it fails that, >= 212 and so on. Testing the other limit seems redundant.

It is not clear if it matters in this use case but a 65k resistor in parallel with a 50k resistor is effectively a 28.2k resistor. This is very close, allowing for tolerances, to the 27k resistor you are also using meaning that it could be difficult to distinguish between a single button press and at least some combinations of multiple button presses.


text:
Slow I2C communication
To collect temperature and BPM, I connected a max30101 in my Heltec WiFi kit V3 with ESP32. The data collected are stored in arrays to extract statistical features from signals which an algorithm will process to predict anxiety or baseline (with two other additional libraries).
The problem is that I see a very slow communication on the serial which increase if I add u8x8 library to print values on my builtin OLED. Thus, BPM are always very slow reaching a maximum of 20 BPM.
This is my code:
#include <PlaquetteLib.h> // --> Smoothing and scaling operations [https://sofapirate.github.io/Plaquette/]
using namespace pq; // --> use plaquette library as "pq"
Smoother smoother3(3.0f); // --> third moving mean of 3 seconds for ST values
Smoother smoother2(3.0f); // --> second moving mean of 3 seconds for HR values
#include <Wire.h> // --> I2C connection
#include "MAX30105.h" // --> Sparkfun library for MAX30101 sensor [https://github.com/sparkfun/SparkFun_MAX3010x_Sensor_Library]
MAX30105 particleSensor; // --> used for BPM and ST
#include "Scaler.h" // --> Feature extraction library [https://github.com/eloquentarduino/everywhereml]
#include "Classifier.h" // --> Classification library containing Logistic Regression algorithm [https://github.com/eloquentarduino/micromlgen]
Eloquent::ML::Port::LogisticRegression clf; // --> declare classifier library
#include "heartRate.h" // --> Optical Heart Rate Detection (PBA Algorithm) [https://github.com/sparkfun/SparkFun_MAX3010x_Sensor_Library/blob/master/src/heartRate.h]
#include <Arduino.h>
#include <U8x8lib.h>
U8X8_SSD1306_128X64_NONAME_SW_I2C u8x8(18, 17, 21);

//____________________________________________________________________________________________________________________________________________________________________________
//DEFINING GLOBAL VARIABLES
//hr
const byte RATE_SIZE = 3; //Averaging
byte rates[RATE_SIZE]; //Array of heart rates
byte rateSpot = 0;
long lastBeat = 0; //Time at which the last beat occurred
float beatsPerMinute;
int beatAvg;
//st
float degree; // --> raw peripheral skin temperature in °C
float st; // averaged peripheral skin temperature in °C
unsigned long time_printing = 0; // --> variables for millis delay (1Hz)
const byte WINDOW_SIZE = 60;
byte signal1[WINDOW_SIZE];
byte signal2[WINDOW_SIZE];
byte signal1Index = 0;
byte signal2Index = 0;

//_________________________________________________________________________________________________________________________________________________________________________
void setup() {

  //instrumental initialization
  //Serial.begin(9600);
  Plaquette.begin();
  Wire.begin(41, 42);
  u8x8.begin();

  //hr sensor
  particleSensor.begin(Wire, I2C_SPEED_FAST);
  byte ledBrightness = 0x1F;
  byte sampleAverage = 1;
  byte ledMode = 3;
  byte sampleRate = 100;
  int pulseWidth = 411;
  int adcRange = 4096;
  particleSensor.setup(ledBrightness, sampleAverage, ledMode, sampleRate, pulseWidth, adcRange);
  particleSensor.setPulseAmplitudeRed(0); //0 mA
  particleSensor.setPulseAmplitudeIR(0);  // 0 mA
  particleSensor.setPulseAmplitudeGreen(0x19); // 1 mA

  //st sensor
  particleSensor.enableDIETEMPRDY();

  //u8x8.setFont(u8x8_font_8x13B_1x2_r);
  //u8x8.drawString(0, 4, "Initializing...");
  //delay(2000);
  //u8x8.clearDisplay();
  //u8x8.setFont(u8x8_font_open_iconic_check_4x4);
  //u8x8.drawGlyph(6, 2, 0x40);
  //delay(2000);
  //u8x8.clearDisplay();

  }

//_________________________________________________________________________________________________________________________________________________________________________
// BPM values with MAX30101 sensor 1Hz
void hrCollection() {
/**
* The particle sensor capture the green led emission from the inner wrist. When a blood pulse happen, the photodiode capture a pulse of light which corresponds to a heart beat.
* In order to be able to capture peaks throw the wrist, the green led has been accurately set up in the setup() section, following the instructions published by the authors
* on page 22 of the paper. [https://pdfserv.maximintegrated.com/en/an/AN6409.pdf]
* The peaks, corresponding to the BPM, are computed throw a PBA algorithm, then, they are averaged with a moving window of size 3.
*/
  long irValue = particleSensor.getGreen();

  if (checkForBeat(irValue) == true)
  {
    //We sensed a beat!
    long delta = millis() - lastBeat;
    lastBeat = millis();

    beatsPerMinute = 60 / (delta / 1000.0);

    if (beatsPerMinute < 255 && beatsPerMinute > 20)
    {
      rates[rateSpot++] = (byte)beatsPerMinute; //Store this reading in the array
      rateSpot %= RATE_SIZE; //Wrap variable

      //Take average of readings
      beatAvg = 0;
      for (byte x = 0 ; x < RATE_SIZE ; x++)
        beatAvg += rates[x];
      beatAvg /= RATE_SIZE;

    }
  }

  // Add beatAvg to signal1
  signal1[signal1Index] = beatAvg;
  signal1Index = (signal1Index + 1) % WINDOW_SIZE;

}

//_________________________________________________________________________________________________________________________________________________________________-
// ST values with the particle sensor 1Hz.
void stCollection() {
/**
* Peripheral skin Temperature has been measured in degree Celsius thanks to an InfraRed thermophile that capture the emissivity of the human skin.
*/

  degree = particleSensor.readTemperature();

  st = degree >> smoother3;

  // Add st to signal2
  signal2[signal2Index] = st;
  signal2Index = (signal2Index + 1) % WINDOW_SIZE;

}
//____________________________________________________________________________________________________________________________________________________________________________
// Feature Extraction
void extraction(float* features) {
  // Calculate minimum, maximum, mean, median, standard deviation, variance, skewness, and kurtosis for signal1 (beatAvg)
  int beatMin = INT_MAX;
  int beatMax = INT_MIN;
  float beatSum = 0.0;
  float beatSumSquares = 0.0;
  float beatSkewness = 0.0;
  float beatKurtosis = 0.0;
  byte sortedSignal1[WINDOW_SIZE];

  for (byte i = 0; i < WINDOW_SIZE; i++) {
    if (signal1[i] < beatMin) {
      beatMin = signal1[i];
    }
    if (signal1[i] > beatMax) {
      beatMax = signal1[i];
    }
    beatSum += signal1[i];
    beatSumSquares += pow(signal1[i], 2);
    sortedSignal1[i] = signal1[i];
  }

  float beatMean = beatSum / WINDOW_SIZE;

  std::sort(sortedSignal1, sortedSignal1 + WINDOW_SIZE);

  byte middle = WINDOW_SIZE / 2;
  byte beatMedian;
  if (WINDOW_SIZE % 2 == 0) {
    beatMedian = (sortedSignal1[middle - 1] + sortedSignal1[middle]) / 2;
  } else {
    beatMedian = sortedSignal1[middle];
  }

  float beatStdDeviation = sqrt((beatSumSquares / WINDOW_SIZE) - pow(beatMean, 2));
  float beatVariance = pow(beatStdDeviation, 2);

  for (byte i = 0; i < WINDOW_SIZE; i++) {
    float deviation = signal1[i] - beatMean;
    beatSkewness += pow(deviation, 3);
    beatKurtosis += pow(deviation, 4);
  }
  beatSkewness /= (WINDOW_SIZE * pow(beatStdDeviation, 3));
  beatKurtosis /= (WINDOW_SIZE * pow(beatStdDeviation, 4));

  // Calculate minimum, maximum, mean, median, standard deviation, variance, skewness, and kurtosis for signal2 (st)
  float stMin = FLT_MAX;
  float stMax = FLT_MIN;
  float stSum = 0.0;
  float stSumSquares = 0.0;
  float stSkewness = 0.0;
  float stKurtosis = 0.0;
  float sortedSignal2[WINDOW_SIZE];

  for (byte i = 0; i < WINDOW_SIZE; i++) {
    if (signal2[i] < stMin) {
      stMin = signal2[i];
    }
    if (signal2[i] > stMax) {
      stMax = signal2[i];
    }
    stSum += signal2[i];
    stSumSquares += pow(signal2[i], 2);
    sortedSignal2[i] = signal2[i];
  }

  float stMean = stSum / WINDOW_SIZE;

  std::sort(sortedSignal2, sortedSignal2 + WINDOW_SIZE);

  middle = WINDOW_SIZE / 2;
  byte stMedian;
  if (WINDOW_SIZE % 2 == 0) {
    stMedian = (sortedSignal2[middle - 1] + sortedSignal2[middle]) / 2;
  } else {
    stMedian = sortedSignal2[middle];
  }

  float stStdDeviation = sqrt((stSumSquares / WINDOW_SIZE) - pow(stMean, 2));
  float stVariance = pow(stStdDeviation, 2);

  for (byte i = 0; i < WINDOW_SIZE; i++) {
    float deviation = signal2[i] - stMean;
    stSkewness += pow(deviation, 3);
    stKurtosis += pow(deviation, 4);
  }
  stSkewness /= (WINDOW_SIZE * pow(stStdDeviation, 3));
  stKurtosis /= (WINDOW_SIZE * pow(stStdDeviation, 4));

  // Store the calculated features in the features array
  features[0] = beatMin;
  features[1] = beatMax;
  features[2] = beatMean;
  features[3] = beatMedian;
  features[4] = beatStdDeviation;
  features[5] = beatVariance;
  features[6] = beatSkewness;
  features[7] = beatKurtosis;
  features[8] = stMin;
  features[9] = stMax;
  features[10] = stMean;
  features[11] = stMedian;
  features[12] = stStdDeviation;
  features[13] = stVariance;
  features[14] = stSkewness;
  features[15] = stKurtosis;
}
//_____________________________________________________________________________________________________________________________________________________________________________

//_____________________________________________________________________________________________________________________________________________________________________________
void loop() {

  Plaquette.step();

  hrCollection();
  stCollection();

  float features[16]; // Create the features array
  extraction(features);

  if (!processor.transform(features))
  return;

  //Serial.print(beatsPerMinute); Serial.print(","); Serial.print(st); Serial.print(","); Serial.println(clf.predictLabel(processor.X));

  char heart[3];
  char temperature[2];
  u8x8.setFont(u8x8_font_open_iconic_embedded_2x2);
  u8x8.drawGlyph(4, 1, 0x46);
  u8x8.setFont(u8x8_font_lucasarts_scumm_subtitle_r_2x2_f);
  itoa(beatsPerMinute, heart, 10);
  u8x8.drawString(7, 1, heart);
  itoa(st, temperature, 10);
  u8x8.drawString(7, 3, temperature);
  u8x8.drawString(0, 5, clf.predictLabel(processor.X));
}

When I print on 9600 without u8x8 the printing is normal even if the problem with BPM persists, when I add u8x8 I see on the serial a very slow printing. 115200 baud rate doesn't show anything but empty squares. I am wondering if the problem could be the bad quality wires or I am making some mistake inside the code.

Discovered that esp32, Heltec in my case, have some conflicts problem when using the builtin OLED. The conflicts depend on the I2C communication: by applying an I2C scanner with on the OLED bus only, I noticed that the address changes randomly, and I didn't understand the reason why. As not having the possibility to test another esp32 board, everything worked with a Wemos esp8266 D1 mini pro.


text:
How to fix UnicodeDecodeError when using Serial.println
I am using an Arduino Uno R3 to send instructions to a serial monitor in a Python program with Serial.println.  But when I send a specific line, I get a a UnicodeDecodeError.
The line in the Arduino code that causes this error is:
Serial.println("Press '1,2,3,4,5' to run motor at 10%, 20%, 30%, 40%, 50% for 2 seconds");

My Python code to read the serial data is:
def get_serial_data(self):
        while 1:
            try:
                serial_data = self.serial_connection.readline().decode('Ascii')
                filtered_serial_data = serial_data.strip('\r\n')
                self.serial_monitor.insert(END, filtered_serial_data)
            except TypeError:
                pass

and is called from a thread:
thread1 = threading.Thread(target=self.get_serial_data)
        thread1.daemon = True
        thread1.start()

But I get the following error:
UnicodeDecodeError: 'ascii' codec can't decode byte 0x85 in position 36: ordinal not in range(128)

Can anyone help why this is happening or how to fix, I saw a stackoverflow post to use a try, except block to get it to ignore this line, but I want to print it out, and I want to understand why I get this error.

As a newcomer to the Arduino community, it would be good to know why this and my answer got downvoted.  It was a genuine issue that took me a while to solve, and wasn't obvious from the docs.  Without any reasoning for the downvotes makes this community come across as unfriendly

I solved the issue.  It was a memory issue not a decoding issue.  Because the dynamic memory was mostly used up, it affected the encoding of the data.  Reducing the amount of memory my code was using resolved the issue.
I also discovered, that Serial.println("some text") uses a lot of dynamic memory.  So by reducing the amount of text I was encoding helped, but also by wrapping the the text in F(), like this:
Serial.println(F("some text"))

Which stores the string in flash memory not sram.  Heres a helpful link on the F function:
https://arduinogetstarted.com/faq/what-is-serial.println-f