message:
Voltage reading problem in Arduino mega based 10 cannel battery capacity tester

I want to make a 10 channels Arduino mega-based battery capacity tester using 4.7 ohms 10w resistors controlling them with IRFZ44n MOSFETs with respected digital pins. An 8.4V battery powers the Arduino (do not consider the buck converter in the picture). I am debugging my project step by step. When I read voltages of individual batteries by corresponding analog pins without turning On 'MOSFET-Gate pins' then Arduino measures the voltages correctly but when I turn on the gate pins then Arduino measures voltage incorrectly. Meaning if I connect
a battery with an analog pin and a multimeter at the same time and the value is pretty much same. Like 3.70 volt for the multimeter and 3.72 for analog pin but when I turn On the gatepin of the MOSFET then Arduino value is like 3.07V and Multimeter value is 3.48V.
Thanks in advance.

Here is the Circuit Diagram of my project:
[![enter image description here][1]][1]

Simple version to understand:
[![enter image description here][2]][2]

  [1]: https://i.stack.imgur.com/0xeSN.jpg
  [2]: https://i.stack.imgur.com/ZidlV.jpg

Code:

```c++
long readVcc() {
   // Read 1.1V reference against AVcc
   // set the reference to Vcc and the measurement to the internal 1.1V reference
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
   ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
   ADMUX = _BV(MUX5) | _BV(MUX0) ;
#else
   ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#endif
   ADCSRB &= ~_BV(MUX5);
   delay(2); // Wait for Vref to settle
   ADCSRA |= _BV(ADSC); // Start conversion
   while (bit_is_set(ADCSRA,ADSC)); // measuring

   uint8_t low  = ADCL; // must read ADCL first - it then locks ADCH
   uint8_t high = ADCH; // unlocks both

   long result = (high<<8) | low;

   result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000   //1126400L internalRefVolt(1.1) * 1023 * 1000; code can more precse by calculating internalRefVolt(1.1)
   return result; // Vcc in millivolts
}

void setup() {
   Serial.begin(115200);
   delay(3000);
   pinMode(22,OUTPUT);//***Mosfet Gate Pins********
   pinMode(23,OUTPUT);
   pinMode(24,OUTPUT);
   pinMode(25,OUTPUT);
   pinMode(26,OUTPUT);
   pinMode(27,OUTPUT);
   pinMode(28,OUTPUT);
   pinMode(29,OUTPUT);
   pinMode(30,OUTPUT);
   pinMode(31,OUTPUT);

   digitalWrite(22,LOW);//***Initially low the Mosfet Gate Pins********
   digitalWrite(23,LOW);
   digitalWrite(24,LOW);
   digitalWrite(25,LOW);
   digitalWrite(26,LOW);
   digitalWrite(27,LOW);
   digitalWrite(28,LOW);
   digitalWrite(29,LOW);
   digitalWrite(30,LOW);
   digitalWrite(31,LOW);
}

/**********************************Void Loop******************************************************/
void loop() {
   float voltRef = readVcc() / 1000.0;

   digitalWrite(22,HIGH);//*** High the Mosfet Gate Pins********
   digitalWrite(23,HIGH);
   digitalWrite(24,HIGH);
   digitalWrite(25,HIGH);
   digitalWrite(26,HIGH);
   digitalWrite(27,HIGH);
   digitalWrite(28,HIGH);
   digitalWrite(29,HIGH);
   digitalWrite(30,HIGH);
   digitalWrite(31,HIGH);

   float volt0 = analogRead(A0)*(voltRef/1024);
   delay(10);
   volt0 = analogRead(A0)*(voltRef/1024);
   /* if(volt0>3.0){
      digitalWrite(22,HIGH); // High = Mosfet ON
      digitalWrite(36,HIGH); // High = LED Turn OFF

      }*/

   float volt1 = analogRead(A1)*(voltRef/1024);
   delay(10);
   volt1 = analogRead(A1)*(voltRef/1024);

   float volt2 = analogRead(A2)*(voltRef/1024);
   delay(10);
   volt2 = analogRead(A2)*(voltRef/1024);

   float volt3 = analogRead(A3)*(voltRef/1024);
   delay(10);
   volt3 = analogRead(A3)*(voltRef/1024);

   float volt4 = analogRead(A4)*(voltRef/1024);
   delay(10);
   volt4 = analogRead(A4)*(voltRef/1024);

   float volt5 = analogRead(A5)*(voltRef/1024);
   delay(10);
   volt5 = analogRead(A5)*(voltRef/1024);

   float volt6 = analogRead(A6)*(voltRef/1024);
   delay(10);
   volt6 = analogRead(A6)*(voltRef/1024);

   float volt7 = analogRead(A7)*(voltRef/1024);
   delay(10);
   volt7 = analogRead(A7)*(voltRef/1024);

   float volt8 = analogRead(A8)*(voltRef/1024);
   delay(10);
   volt8 = analogRead(A8)*(voltRef/1024);

   float volt9 = analogRead(A9)*(4.95/1024);
   delay(10);
   volt9 = analogRead(A9)*(4.95/1024);

   //*****************************************************************************
   Serial.print("B0= ");
   Serial.println(volt0);

   Serial.print("B1= ");
   Serial.println(volt1);

   Serial.print("B2= ");
   Serial.println(volt2);

   Serial.print("B3= ");
   Serial.println(volt3);

   Serial.print("B4= ");
   Serial.println(volt4);

   Serial.print("B5= ");
   Serial.println(volt5);

   Serial.print("B6= ");
   Serial.println(volt6);

   Serial.print("B7= ");
   Serial.println(volt7);

   Serial.print("B8= ");
   Serial.println(volt8);

   Serial.print("B9= ");
   Serial.println(volt9);

   Serial.println("");
   Serial.println("==========================");
   delay(500);
}
```

body:
Electric wires have resistance. Most of the time this resistance can be ignored, but this is not always the case. Specifically, if the wire is carrying a large amount of current, the voltage drop across it can be significant.

Consider this circuit:

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

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

<!-- End schematic -->

The red wires carry a high current, and experience a significant voltage drop. Wires in black carry almost no current, and are equi-potential. Both voltmeters on the left will measure the same voltage, which is affected by the voltage drops along AB and along DE. The voltmeter on the right measures a lower voltage, because it is also affected by the drops along BC and EF.

In your experiment the problem is compounded by the fact that the ground wire is carrying the current from _all_ the batteries. It is therefore responsible of most of the voltage drop you experience.

The takeaway is that you have to make sure the junction points between the current carrying wires and the measurement wires (points B and E for the voltmeters on the left) are as close as possible to the battery. Otherwise your measurement will be biased.


sender: user

sender: assistant

body: The main problem was the battery holder default wire, those wires were have high resistance. After changing those wire the problem was solved. Thank you everyone


message:
#define from main (.ino) not considered by comiler in own libaries

I have got the problem, that my #define from main (.ino) is not considered by the comiler in my own libaries. This #define MQTT_MODULE is only considered in the main (.ino) programm, but not in MyRemoteLib.cpp
This example works normally, if I compile it with gcc.

Code in my Test.ino :

    #define   MQTT_MODULE    1
    #include  "MyRemoteLib.h"
    loop() {
      my_test() ;
    }

Code in MyRemoteLib.h

    #define  MYREMOTELIB_H
    #define  MY_TEST   1
    #if   MQTT_MODULE
      #define  MQTT_MOD_R    1
    #endif

Code in MyRemoteLib.cpp :

    #include  "MyRemoteLib.h"
    void my_test() {
   #if MQTT_MOD_R
    test.... > nothing -> ignored by compiler
   #endif
   #if MQTT_MODULE
    test.... > nothing -> ignored by compiler
   #endif
   #if MYTEST
    test.... > error-> not ignored by compiler
   #endif
    }

body:
This is the expected behavior. The library and the main program are two
different compilation units: there are processed by the compiler
separately.

In the main program, the inclusion of the header file yields this:

```c++
#define         MQTT_MODULE             1
// Included from MyRemoteLib.h:
#define     MYREMOTELIB_H
#define     MY_TEST         1
#if         MQTT_MODULE
  #define       MQTT_MOD_R              1
#endif
// end of included code
loop() {
  my_test() ;
}
```

The remaining preprocessor code has no effect at all.

In the library, the same inclusion yields this:

```c++
// Included from MyRemoteLib.h:
#define     MYREMOTELIB_H
#define     MY_TEST         1
#if         MQTT_MODULE
  #define       MQTT_MOD_R              1
#endif
// end of included code
void my_test() {
  #if   MQTT_MOD_R
      test.... > nothing -> ignored by compiler
  #endif
  #if   MQTT_MODULE
      test.... > nothing -> ignored by compiler
  #endif
  #if   MYTEST
      test.... > error-> not ignored by compiler
  #endif
}
```

The conditional compilation gives an empty `my_test()` (that is, unless
by `MYTEST` you actually mean `MY_TEST`).

I do not know what you are trying to achieve, but you may look at ways
to put the code to be conditionally compiled in the header itself. You
may try using inline functions, or maybe templates.

**Edit**: about removing code using conditional compilation: this is not
always as useful as it may sound, for two reasons.

1. By default, the Arduino IDE compiles your code with the options
   `-ffunction-sections` and `-fdata-sections`, and links it with
   `-Wl,--gc-sections`. This means that any function or method that is
   never used, or any global variable that is never referenced, is not
   included in the final executable.

2. The code is also compiled with `-flto`, which enables [link-time
   (full program) optimizations][lto]. This means that code that depends
   on a condition that is always false (the conditional expression can
   be resolved as a compile-time constant) is also removed from the
   final executable.

[lto]: https://en.wikipedia.org/wiki/Interprocedural_optimization


message:
Can't upload sketch after overheating

I'm using an Arduino nano, after an unfortunate event, The mega chip heat up and when I tried touching it, it burned my finger. After that, I connected to my laptop's USB port and the computer recognized it. But after I hit the upload button, the RX light flash 3 times and stop, no Loader light and it just stop there, and the IDE says this:

    Arduino: 1.8.19 (Windows 10), Board: "Arduino Nano, ATmega328P (Old Bootloader)"

    Sketch uses 2806 bytes (9%) of program storage space. Maximum is 30720 bytes.

    variables use 44 bytes (2%) of dynamic memory, leaving 2004 bytes for local variables.
    Maximum is 2048 bytes.

    An error occurred while uploading the sketch

    avrdude: stk500_recv(): programmer is not responding

    avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x84

    avrdude: stk500_recv(): programmer is not responding

    avrdude: stk500_getsync() attempt 2 of 10: not in sync: resp=0x84

    avrdude: stk500_recv(): programmer is not responding

    avrdude: stk500_getsync() attempt 3 of 10: not in sync: resp=0x84

    avrdude: stk500_recv(): programmer is not responding

    avrdude: stk500_getsync() attempt 4 of 10: not in sync: resp=0x84

    avrdude: stk500_recv(): programmer is not responding

    avrdude: stk500_getsync() attempt 5 of 10: not in sync: resp=0x84

    avrdude: stk500_recv(): programmer is not responding

    avrdude: stk500_getsync() attempt 6 of 10: not in sync: resp=0x84

    avrdude: stk500_recv(): programmer is not responding

    avrdude: stk500_getsync() attempt 7 of 10: not in sync: resp=0x84

    avrdude: stk500_recv(): programmer is not responding

    avrdude: stk500_getsync() attempt 8 of 10: not in sync: resp=0x84

    avrdude: stk500_recv(): programmer is not responding

    avrdude: stk500_getsync() attempt 9 of 10: not in sync: resp=0x84

    avrdude: stk500_recv(): programmer is not responding

    avrdude: stk500_getsync() attempt 10 of 10: not in sync: resp=0x84

    This report would have more information with
    "Show verbose output during compilation"
    option enabled in File -> Preferences.
Any advice?

body: Not sure what you did but you probably either overvoltage it or connected it backwards. The odds are extremely high you fried the mega chip. Good news, it is not a total waste, you learned something not to do. It is still good for practicing troubleshooting, if you find what failed great or if you cannot fix it,  you will have learned something useful. Atthis point use it for practicing SMD soldering. In the end remove the parts and use the PCB for a template. The recommended solution is to purchase two more, that way if one fails the wate time will be shorter.


message:
Controlling the 5V pin on the Arduino nano 33 BLE

Following the guidance on [this post ](https://support.arduino.cc/hc/en-us/articles/360014779679-About-Nano-boards-with-disabled-5-V-pins?_gl=1*1yxmaf9*_ga*NjU4MDE0NTY2LjE2NjQyOTI4MjA.*_ga_NEXN8H46L5*MTY2NDI5MjgyMC4xLjEuMTY2NDI5NTc2NS4wLjAuMA..) I have enabled the 5V pin.  That same post suggests that I control that pin with D12, though I find it weird since there is already a D12 pin.  When I try and run some code the D12 pin is performing exactly as I expect, but the 5V pin is doing nothing.

Looking through the [tech specs](https://docs.arduino.cc/static/741bbe6b7ce4563049b3b662180471c3/ABX00030-datasheet.pdf) it says "**the 5V pin does NOT supply voltage but is rather connected, through a jumper, to the USB power input.**" which I find odd, since if its connected to the power input, should it not be supplying voltage?

Could someone clarify if its possible to use the 5V pin like a digital pin, and if so how?

body:
> Following the guidance on this post I have enabled the 5V pin. That same post suggests that I control that pin with D12, though I find it weird since there is already a D12 pin. When I try and run some code the D12 pin is performing exactly as I expect, but the 5V pin is doing nothing.

5 V pin is the the 12th pin of the PCB

> Looking through the tech specs it says "the 5V pin does NOT supply voltage but is rather connected, through a jumper, to the USB power input." which I find odd, since if its connected to the power input, should it not be supplying voltage?

it says that the 5V pin is connected to the USB power input through a jumper and the jumper is not connected from factory


message:
Why wont my custom Arduino-Micro-based board connect over USB?

I designed and printed a PCB for my MIDI controller project with a modified Arduino Micro microcontroller essentially built into the design. I swapped out the USB Micro for a USB-C type port (just using the 2.0 protocol). Although I can program the board via ICSP, including getting it to run my Arduino sketches (which I have tested by having it light up the LEDs in a certain pattern, which works as expected), and the fact that it receives power via USB, the problem is that I cannot get the device to connect to my PC over USB - it is not recognized as a USB device, and cannot seem to send or receive data over USB. I'm not sure if I've done something wrong in the design or if I am simply missing something, but could use some advice, as in order to function as intended, the board will need to be able to communicate over USB.

I have tested with various USB-A to USB-C cables and USB-A to Micro cables (tested with other Arduinos) and a Micro to USB-C adapter.

As per various instructions I found online, I connected pull-down resistors of 5.1k Ohms to CC1 and CC2, left SBU1 and SBU2 unconnected as I was planning to use 2.0 protocols to keep things simple (as a related question, can these actually be used to make use of 3.0+ protocols in a design like this with an ATMEGA32U4? Would this be considered better practice in this case and potentially bypass the error?), and wired up D- and D+ as shown in the schematic below; with a EZJZ0V500AA Varistor between each and GND and running through a 4D03WGJ0220T5E Resistor network (which I don't know much about, including whether this type of component has any polarity? I simply tried to follow how the same sort of component was used in the official Arduino Micro schematics) and finally into pins 3 and 4 of the ATMEGA32U4.

This is the original schematic of the board as it was assembled, but as a result of some power issues with this same board which I have since sorted out with help in a separate post https://arduino.stackexchange.com/questions/90839/why-wont-my-custom-arduino-micro-based-board-receive-power-via-usb, I had to bypass the 5V regulator and just use VUSB as +5V, so I will put the updated schematic reflecting these changes below the original (I wouldn't think it would affect this issue, but I'm not that experienced and want to err on the side of providing as many details as possible)

Original Schematic:
[![Original Schematic][1]][1]

Revised Schematic:
[![Revised Schematic][2]][2]

Components:

    | Designator                                             | Value                   | Component                |
    |:--------------------------------------------------------|:-------------------------|:--------------------------|
    | C_ARD_1, C_ARD_2, C_ARD_6, C_ARD_9, C_ARD_10, C_ARD_11 | 100n                    | CL05B104KO5NNNC          |
    | C_ARD_3, C_ARD_14                                      | 22u                     | RVT22UF16V67RV0017       |
    | C_ARD_4, C_ARD_5, C_ARD_7                              | 1uF                     | CL05A105KA5NQNC          |
    | C_ARD_12, C_ARD_13                                     | 22pF                    | 0402CG220J500NT          |
    | D_ARD_2                                                | CD1206-S01575           | CDSU4148-HF              |
    | F1                                                     | MF-MSMF050-2 500mA      | MF-MSMF050-2             |
    | J3                                                     | USB_C_Receptacle_USB2.0 | KH-TYPE-C-16P            |
    | L1                                                     | green                   | 19-217/GHC-YR1S2/3T      |
    | L2                                                     | MH2029-300Y             | BLM21PG300SN1D           |
    | ON1                                                    | blue                    | 19-217/BHC-ZL1M2RY/3T    |
    | R_ARD_1, R_ARD_2, R_ARD_4, R_ARD_9                     | 10K                     | 0402WGF1002TCE           |
    | R_ARD_5, R_ARD_6, R_ARD_7, R_ARD_8                     | 1K                      | 0402WGF1001TCE           |
    | R_ARD_10, R_ARD_11                                     | 5.1k                    | 0402WGF5101TCE           |
    | RP3                                                    | 22R                     | 4D03WGJ0220T5E           |
    | RX1, TX1                                               | yellow                  | 19-213/Y2C-CQ2R2L/3T(CY) |
    | T1                                                     | FDN340P/PMV48XP         | PMV48XP                  |
    | T2                                                     | PMV48XP                 | PMV48XP                  |
    | U1                                                     | ATMEGA32U4-XUMU         | ATMEGA32U4-MU            |
    | U2                                                     | NCP1117-5               | NCP1117ST50T3G           |
    | U4                                                     | LP2985-33DBVR           | LP2985-33DBVR            |
    | Y3                                                     | 16MHz KX-7              | 3225-16.00-10-10-10/A    |
    | Z1, Z2                                                 | CG0603MLC-05E           | EZJZ0V500AA              |

  [1]: https://i.stack.imgur.com/OEEKL.jpg
  [2]: https://i.stack.imgur.com/qgfHz.jpg

body:
Well I finally found the source of the problem, many thanks to everyone here who helped me narrow things down and kept pointing me in the right direction. After figuring out that D+ and D- were getting pulled appropriately by the chip I decided to desolder the USB port on the board, cut a USB-A 2.0 cable and solder the leads directly to the board and, suddenly, it worked. After this I realized the problem must have been with the USB port on the board and upon comparing the datasheet to my pcb file, I realized that the footprint I used and the one in the datasheet had the pins laid out in a different order.

I feel a bit embarrassed for taking up people's time on such a stupid error I made (and admittedly didn't even provide enough information for anyone to be able to figure out for me, despite all of your patience and helpful advice), but at the same time I am both relieved I figured out the problem and grateful for all the help I got on this post, I'm not sure how long it would have taken me to figure out without your suggestions. I learned a lot about the layout of arduino boards, the purposes of various components in said boards, the importance of double checking footprints, and about better practices for asking for assistance.

As a note on "post etiquette" or whatever you would call it, since everyone provided assistance in comments, I didn't see a way to close the post without answering my own question (I am new to posting here), so I hope that is an acceptable way to do so.


message:
Do these bit settings all mean the same?

```
ADMUX  = ADMUX | _BV(REFS);  // uncompounded bitwise OR
ADMUX |= _BV(REFS0);         // #define _BV(bit) (1 << (bit))
ADMUX |= bit(REFS0);         // #define bit(b) (1UL << (b))
bitSet(ADMUX, REFS0);        // #define bitSet(value, bit) ((value) |= (1UL << (bit)))
sbi(ADMUX, REFS0);           // deprecated assembly?
ADMUX |= (1 << REFS0);       // shift operator
ADMUX |= (1 << 7);           // bit 7 is named REFS0
ADMUX |= 0b10000000;         // bin
ADMUX |= 0x80;               // hex
ADMUX |= 128;                // dec
```
*under normal 8 bit Arduino circumstances?

body:
You already got an answer in the comments but, just to make double sure,
I tried compiling all these statements for an Uno, and they got all
translated into the _exact same machine code_. Well, almost: I had to do
some minor adjustments, which I believe are unrelated to the essence of
your question. Just for completeness, I changed the following:

1. I replaced REFS0 by REFS1: on an Uno, REFS0 is bit 6, and REFS1
   is bit 7.

2. I replaced REFS by REFS1, as the former is not defined.

3. I #included `<compat/deprecated.h>`, otherwise I get the error
   “'`sbi`' was not declared in this scope”.


message:
Do I need to connect a capacitor to AREF if using internal reference? _BV(REFS0)

[![enter image description here][1]][1]
This is from the Atmega328p datasheet. But I see no mention of it in practical examples.
So when I'm setting up the timer for ADC with:
```
ADMUX = _BV(REFS0);
```

Should I add the cap? Or might it be already there on the arduino's hardware? Also what value is advised? 100nF?
Thanks in advance!

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

body:
According to the datasheet:

> The voltage reference may be externally decoupled at the AREF pin by a capacitor for better noise performance.

So you *can* but you don't *have to*. It all depends on how good you want your ADC results to be. 99% of the time it's pointless since what you're reading isn't that accurate, but if you want to add a capacitor anyway then sure, go right ahead.

What value capacitor? Well that very much depends on what kind of noise you want to achieve more immunity from. The lower the value the higher the frequency it will help protect you from. You may want to combine multiple capacitors in parallel if you're in a very noisy environment, such as 1nF and 100nF.


message:
Compile Error Getting when i try to read firebase data using esp32 in Arduino IDE

I am trying to read the firebase data using esp32, when i try to read firebase data statically(string literal) no error is coming.

```
String board=Firebase.getString(fbdo, F("Device/board")) ? String(fbdo.to()).c_str() : fbdo.errorReason().c_str(); //getting data successfully
```

But when i try to read data dynamically using String object, i am getting compile error for given code

```
String string2 = "Device/board";
String board1=Firebase.get(fbdo, F(string2)) ? String(fbdo.to()).c_str() :
    fbdo.errorReason().c_str();

ERROR : #define F(string_literal) (FPSTR(PSTR(string_literal)))
```
How to solve this problem?

body:
The macro `F()` can only be used with string literals, not with variables.

A simple solution should be (I cannot test) to provide `string2` directly. (I hope that `Firebase.get()` is overloaded.) Try this:

```cpp
String board1 = Firebase.get(fbdo, string2) ? String(fbdo.to()).c_str() : fbdo.errorReason().c_str();
```

To save precious RAM, you might consider to use another data type for `string2`. To get a similar result, you could try:

```cpp
const __FlashStringHelper *string2 = F("Device/board");
String board1 = Firebase.get(fbdo, string2) ? String(fbdo.to()).c_str() : fbdo.errorReason().c_str();
```

---

To gain some more insight, you might like to read [this guide on PROGMEM][1].

  [1]: https://arduino-esp8266.readthedocs.io/en/latest/PROGMEM.html


message:
How to correctly set PWM to control servo angle in AVR?

I've stumbled upon timer configuration to handle my sg-90 servo and my Arduino UNO.

**What I did:**

 1. *Set the prescaler to 64 and mode to fast PWM of 16-bit timer.*
 2. *The frequency is 50hz so the ICR1 is set to 4999.*
 3. *And now I don't know what to do next to set the values of OCR1A without guessing them.*

From my understanding: **If the period is now set to 20ms then for sg-90 servo:**

From documentation: http://www.ee.ic.ac.uk/pcheung/teaching/DE1_EE/stores/sg90_datasheet.pdf

 - Angle 0 should be 1ms (1/20 = 0.05), so OCR1A = 4999 * 0.05 ~= 250
 - Angle 90 should be 1.5ms (1.5/20 = 0.075), so OCR1A = 4999 * 0.075 ~= 375
 - Angle 180 should be 2ms (2/20 = 0.1) so OCR1A = 4999 * 0.1 ~= 500

**But it doesn't work like that.** I've figured out that values are 125, 370, 615 - I've found these numbers in the internet (not in English language) but that guy didn't explain how he got them.

Could someone explain it to me where these numbers come from or where my calculations are incorrect.

It's not a problem with servo because with Arduino servo library everything works fine.

**Solution:**

**The document I've attached is incorrect the pulse range of miliseconds is not 1-2ms but 0.5-2.5ms and everything fits correctly.**

Below is my current code:

    #define F_CPU 16000000UL

    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <util/delay.h>
    #include <stdbool.h>

    #define PRESCALER_64 (1 << CS11) | (1 << CS10)
    #define FAST_PWM_A (1 << WGM11)
    #define FAST_PWM_B (1 << WGM13) | (1 << WGM12)

    int main(){

        TCCR1A = FAST_PWM_A | (1 << COM1A1);
        TCCR1B = FAST_PWM_B | PRESCALER_64;
        ICR1 = (F_CPU / 64 / 50) - 1;

        DDRB |= (1 << PB1);

        while(true){
            OCR1A = 125;
            _delay_ms(2000);
             OCR1A = 370;
            _delay_ms(2000);
            OCR1A = 615;
            _delay_ms(2000);
        }

    }

body:
OK, I figured it out.

The document I've attached is incorrect, the pulse range of milliseconds is not 1-2ms but 0.5-2.5ms and everything fits correctly.


message:
How to improve button turn on/off experience

I have simple circuit turning lights on and off on button click.
It is working quite fine but there is a small issue with button click itself, it is not fully reliable.
Turning lights on is pretty fine but turning them off is tricky.
Basically clicking once almost never works. I need to click in the right moment to turn them off or better keep pressing the button until right moment. If I hold too long it also doesn't work or work wrongly.
Here is the loop code:

    void loop() {
        int buttonState = digitalRead(BUTTON_PIN);
        if (buttonState == 1) active = not active;

        if (active) {

           ... led setup

          FastLED.show();
          FastLED.delay(1000 / UPDATES_PER_SECOND);
        } else {
          fill_solid( leds, NUM_LEDS, CRGB::Black);
          FastLED.show();
    //      FastLED.clear();
        }
    }

What do I need to do to make it working as expected which is:
- single click turn light on
- another click or hold for a while turns light off for good and they stay off until next click

body:
I think that you have a couple of things going on here. Debouncing has already been mentioned and I don’t want to discount that at all – there is a ton of information on that subject.

In your case, I think it would be helpful for you to consider 1) how you are defining a button press and 2) how much processing you are doing when you are not checking for a button press.

[![switch configuration][1]][1]

To demonstrate, I used this simple set up with a switch:

Then I modified an example from the FastLED library to simply toggle one LED (from a 12 LED, generic, neopixel ring [no clock] and ran it on an UNO (I know you are using a nano, but I think it should still work) using this code.

    #include <FastLED.h>

    #define NUM_LEDS 1

    int LEDon = 0;
    #define DATA_PIN 6

    int switchPin = 8;

    CRGB leds[NUM_LEDS];

    void setup() {
      // ## Clockless types ##
      FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);  // GRB ordering is assumed
      pinMode(switchPin, INPUT);
      // start with LED off (not strictly needed)
      leds[0] = CRGB::Black;
      FastLED.show();
    }

    void loop() {
      if ( digitalRead(switchPin) == HIGH) { // switch is pressed
        if (LEDon == 0) {
          LEDon = 1;
          leds[0] = CRGB::Red;
          FastLED.show();
        }
        else {
          LEDon = 0;
          leds[0] = CRGB::Black;
          FastLED.show();
        }
        while (digitalRead(switchPin) == HIGH); // wait until switch is released
      }
    }

I don’t have much experience with this library (it does appear to be very powerful) and don’t know if you can read the state (on/off/color/intensity) of the LEDS – so I just kludged a variable (LEDon) for the example. It works fine. No missed presses and you have to release the button before you can press it again.

Note that I am doing only the minimum amount needed in between looking for a button press.

Libraries are great, but you need to understand a good deal about using them. I think that you are doing time-consuming processing that is causing you to miss presses, which is why you say “*I need to click in the right moment to turn them off or better keep pressing the button until right moment*”.

I also think that you are ill-defining a press. In the code, I am specifically looking for the button to be released. Because some time is spent processing after the button press is detected, I don’t have to explicitly debounce the switch – for this example. That does not mean that you can always get away with that.

Think about how functionally vague your definition of a press is,
*• single click turn light on
• another click or hold for a while turns light off for good and they stay off until next click*

I would respectfully recommend that you:

Learn as much as you can about the library. Take a look, for example, at this discussion FastLED.delay()  https://github.com/FastLED/FastLED/issues/1206

Do as much as you possibly can in setup().

Do as little as you need to in-between checking for a press (or think about using interrupt).

Hope it helps.

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


message:
CRC8 code not working properly

I need to send a string followed by its CRC8, 0x31 polynomial (= X^8 + X^5 + X^4 + 1), I've coded this successfully after some troubles, but it doesn't seem to work properly when I check the results.
I used some online CRC calulators so check if my results are fine, but I don't get the same results, no matter what I try.

In fact, differents CRC calculators are not giving me the same results, which troubles me...
Here are my trials on online CRC calculators, always using :
CRC8, polynomial 0x31, data = TEMPS; (beginning of my string)

On http://www.sunshine2k.de/coding/javascript/crc/crc_js.html :
[![enter image description here][1]][1]

On https://www.lddgo.net/en/encrypt/crc :
[![enter image description here][2]][2]

On http://zorc.breitbandkatze.de/crc.html :
[![enter image description here][3]][3]

It doesn't seem normal to get different results when the entry parameters are the same, it confuses me a lot. Am I missing something ?

No matter what I try, I don't get any of these results with my own code.
Here is my code about CRC calculation, using RobTillaart's CRC library (https://github.com/RobTillaart/CRC):

       String crcData = "TEMPS;";
      int crcDataLength = crcData.length();
      char arrayForCrc[crcDataLength+1];
      crcData.toCharArray(arrayForCrc, crcDataLength+1);

      crcTrame = CRC8(0x31,0,0,false,false);
      crcTrame.add((uint8_t *)arrayForCrc, crcDataLength+1);
      String stringCrcNoHex = String(crcTrame.getCRC());
      String stringCrc = String(crcTrame.getCRC(), HEX);

The hex result of this code sample is 0xBA (186 decimal)
I verified every input parameters with gets and prints, they're all correct :

arrayForCrc = "TEMPS;"
polynomial = 0x31
StartXOR = 0
EndXOR=0
ReverseIn=false
ReverseOut=false

Help would be greatly appreciated as I'm stuck and don't know what to try anymore.
Thank you :)

  [1]: https://i.stack.imgur.com/ygMHx.png
  [2]: https://i.stack.imgur.com/dFMMm.png
  [3]: https://i.stack.imgur.com/zdomW.png

body:
> The hex result of this code sample is 0xBA (186 decimal)

Not so far as I can tell; it's 0xB5, which is expected for a simple reason that you'll see. And when modified slightly it matches the 0x49 value. I'm inclined to trust that your code is correct, so far as you've shown it, but your report of what's doing is not correct.

> I verified every input parameters with gets and prints, they're all correct

Well, no. As I mentioned in a comments on the question, I get the expected 0x49 on the first site you mentioned with the correct settings. I'm not sure why you're showing 0x6E. But guess what happen if I hit enter after "TEMPS;"? 0x6E. The newline character matters. Also, I _do_ get a 0xBA if I use the correct input but fail to set CRC8 to custom and change 0x07 to a 0x31 in the polynomial. So, maybe that's how you found that value.

If you switch to bytes mode the site expects a sequence of character code values and ignores whitespace (apart from treating it as a delimiter). You can put 0x54 0x45 0x4d 0x50 0x53 into it in bytes mode to see 0x49 result also. You can then add 0x0D (newline) to see it to result in a 0x6E from before.

Regarding the middle site, the settings *aren't* correct (the *reverse* setting is on for input and output) and I don't see how to make them correct; they don't seem to have a custom option. However, you can turn on the reflect options on the first site to get the same result as in the 2nd site in order to convince yourself that is what is going on. The third site's output is correct for what you've put into it. It just doesn't match what you're code is actually doing.

**Your basic problem is the `+1` in this line:**
```c++
crcTrame.add((uint8_t *)arrayForCrc, crcDataLength+1);
```
You've included the null terminator in the calculation. This is 7 bytes: 'T', 'E', 'M', 'P', 'S', ';', '\0'. These websites just aren't doing that; they are not automatically adding a null terminator at the end of whatever you type in string mode. Alternately, if you *wanted* the null terminator in the CRC calculation, your code is fine, but you're going to need to switch to HEX input mode on the website and enter a 0x00 into it after the hex values for the other characters in *TEMPS;* so as to match. And it will match, I've tested this. You can also: put the first site into bytes mode and put "0x54 0x45 0x4d 0x50 0x53 0x3b **0x00**" into it and you will see it now produces a 0xB5, like your current code.

Otherwise, you just need to **not** enter the null terminator into the calculation:

```c++
crcTrame.add((uint8_t *)arrayForCrc, crcDataLength);
```

This will result in `0x49` coming out of `crcTrame.getCRC()` instead of `0xB5`:

```c++
#include "CRC8.h"

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

void loop() {
  String crcData = "TEMPS;";
  int crcDataLength = crcData.length();
  char arrayForCrc[crcDataLength+1];
  crcData.toCharArray(arrayForCrc, crcDataLength+1);

  auto crcTrame = CRC8(0x31,0,0,false,false);
  crcTrame.add((uint8_t *)arrayForCrc, crcDataLength);
  String stringCrcNoHex = String(crcTrame.getCRC());
  String stringCrc = String(crcTrame.getCRC(), HEX);

  Serial.println(stringCrc);
}
```
If you also want to sanity check what happened with the 0x6E output earlier, you can then change `crcData` to `String crcData = "TEMPS;\n"` (adding the newline) and watch it start printing 6E.

---

There's a `.getBytes()` function in String that is pretty much what you have without needin the cast:
```c++
crcTrame.getBytes(arrayForCrc, crcDataLength);
```
I'm not sure if you have a good reason for "TEMPS;" to begin life in a `String` or then to have to get it into an character array. If you're only doing this so you can then call `crcTrame.add()`, well, you needn't:
```c++
#include "CRC8.h"

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

void loop() {
  String crcData = "TEMPS;";
  int crcDataLength = crcData.length();

  auto crcTrame = CRC8(0x31,0,0,false,false);
  crcTrame.add(
    (const uint8_t *)crcData.c_str(),
    crcData.length() // <- Does not count null terminator.
  );
  String stringCrcNoHex = String(crcTrame.getCRC());
  String stringCrc = String(crcTrame.getCRC(), HEX);

  Serial.println(stringCrc);
}
```

Note: I'm only creating `stringCrc` to mirror what you were doing. Here, it could just as easily be `Serial.println(crcTrame.getCRC(), HEX);` and potentially in whatever context you're doing it in. The cast can also be done in a more C++ approved (though uglier way with `crcTrame.add(reinterpret_cast<const uint8_t *>(crcData.c_str()), crcData.length());`

Any sequence of any number of `add()` calls that delivers the same data in the same order into calculation will yield the same CRC. There's also an overload of `add()` that [takes an individual character][1] without needing to involve a pointer at all. So your data doesn't need to come from a `String`, nor be a null-terminated string, or character array, nor fit entirely in memory.

  [1]: https://github.com/RobTillaart/CRC/blob/0.3.1/CRC8.h#L38


message:
PIR sensor is already high, even though it is not detecting any person

I made codes like this through tinkercad.
```
const int temperature = A0;

int pir = 7;

void setup()
{
  pinMode(pir, INPUT);

  Serial.begin(115200);
}

void loop()
{
  int pir_state = digitalRead(pir);

  int value_temp = analogRead(temperature);
  float volt = (value_temp * 5.0) / 1024.0;
  float tempC = (volt - 0.5)*100;

  if (tempC >= 22 && pir_state == 1)
  {
    Serial.print(tempC);
   Serial.println("C");
  }

  delay(1000);
}
```

And following picture is the picture of a circuit I made.

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

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

I simulated this circuit. Originally pir_state is gonna be zero when PIR sensor is not detecting any person or object, but pir_state is always high irrespective of detecting. I thought the value of pir went wrong, so I read pir out. Then, I found it out that pir's value is always 7 regardless of detecting.

I know this isn't a big deal to you guys, but actually I'm noob so I can't figure it out what's wrong. Please, could you help finding what's happening to this and tell me what is the problem?

Here, this is a link of the circuit I make.
https://www.tinkercad.com/things/luV81NLkWKo-engineering-designcapstone-design/editel?sharecode=qsYWcgpijodDbgIpsfluJ3yUJwuN-70doPT62QNTv1Q

body:
Update:

@jsotola commented that Tinkercad does have some capability simulate to the PIR's behavior. So my next step would be to temporarily replace the `if(){ ...` }' block in your loop() function with a few statements that print your inputs and calculated values once per second and run that while I tweaked the simulated PIR device and the thermo-sensor (if the simulation lets you do that).

The terminal output values should lead you to what ever isn't working the way you expected it to.

You are running your program in simulation, but the PIR sensor is an active device that responds to external physical inputs (changes in infrared illumination on it) modified by sensitivity settings on the device. It's hard to simulate a device's active environment. Unless the simulation offers you a way to simulate that, too, there really isn't a way to simulate the its inputs to your program, so a constant output (as seen by your simulated code) makes sense.

Without the simulator letting you pre-program the PIR's physical environment, the only way to see a its active behavior is to use a *real* PIR, and monitor it's real output while you change its actual environment - such as waving your hand in front of it - and watch response with an Arduino, an LED (and resistor) to ground, or a DVM.


message:
Permission denied on upload w/ IDE 2

Dealing with this very common issue on IDE v2.0.0., but not sure why.

I should be fine group-wise:

```bash
adm tty dialout cdrom sudo dip plugdev lpadmin lxd sambashare docker
```

I've also seen numerous suggestions to change the device's permissions directly via `chmod a+rw /dev/<device>`. This is terrible advice, but nothing is working so far, so I tried it anyway. It also doesn't work, as at some point during the upload process, the device is removed and recreated, resetting the permissions.

edit: I've also ensured that ModemManager is not running, and has been purged from the system.

Running the IDE as root always fails, including when the `--no-sandbox` argument is passed.

I'm using the AppImage download on Ubuntu 22.04, but I tried the zip download, with the same results.

edit: Previously in this spot was a note about this problem not occurring on IDE v. 1.8. That wasn't actually the case - I was just testing with a board that doesn't remove and re-create the device on upload. Using a board where that does occur (Arduino Micro in this case), the error occurs in 1.8 as well.

Using `avrdude` directly (as my normal user account) also works just fine.

Additional observation - when the device is recreated by the OS after plugging the Arduino board in, it's first created with `crw------- 1 root root` permissions, and remains in that state for a very short period of time before switching to `crw-rw----+ 1 root dialout` permissions, at which point uploads work as expected.

body:
After a [long debugging session in chat](https://chat.stackexchange.com/rooms/139598/discussion-between-timemage-and-x1a4), we've determined that a udev entry installed by the `apt` package [laptop-mode-tools](https://github.com/rickysarraf/laptop-mode-tools) takes a long time to run, leading to the permissions not settling on the USB device until after the IDE has attempted to upload.

This problem happens even when laptop-mode isn't enabled because you're e.g. using AC. You don't need to be actually using a laptop for this problem to occur, as laptop-mode-tools is a generic power-saving package that can be installed anywhere.

The udev rule in question is `ACTION=="add", SUBSYSTEM=="usb", RUN+="lmt-udev force"` in the file  `/lib/udev/rules.d/99-laptop-mode.rules`.

Commenting out that udev rule, or changing `force` to `auto` resolves the problem for me (without needing to restart udev, or anything else).

Larger hammers that can be used to resolve this include setting `ENABLE_LAPTOP_MODE_TOOLS` to `0` in `/etc/laptop-mode/laptop-mode.conf`, or simply removing `laptop-mode-tools` from the system entirely.

@timemage gets the credit for this fix.


message:
I need help with code for my automated garbage bin compressor

Here is my problem, I'm working on an automated garbage bin compressor. When the garbage is near the sensor, the compressor mechanism will trigger. I'm using Arduino Uno as the controller, a 12v AC window motor, an L298N motor driver, a 12v AC battery, an ultrasonic sensor, and 2 led indicators. The flow chart is as follows the sensor will detect if there is garbage in the garbage bin, if there is no garbage then the motor will not spin. If there is garbage then the motor will start spinning for 20-30 seconds and after the motor stops spinning then it will stop for 5 seconds before returning to its original position. There are 2 LED indicators, the green indicator will indicate if the motor doesn't spin and the red LED will indicate if the motor is in use. So far I'm able to program the motor to spin in 1 direction without a command to stop.

```
const int trigpin = 11;
const int echopin = 10;
int enA = 4;
int SPEED = 250;
int motordirection1 = 3;
int motordirection2 = 2;
int duration = 0;
int distance = 0;

void setup(){
  pinMode (trigpin, OUTPUT);
  pinMode (echopin, OUTPUT);
  pinMode (enA, OUTPUT);
  pinMode (motordirection1, OUTPUT);
  pinMode (motordirection2, OUTPUT);
  pinMode (trigpin, OUTPUT);
  pinMode (echopin, INPUT);

}

void loop(){
  digitalWrite (trigpin, LOW);
  delayMicroseconds (2);
  digitalWrite (trigpin, HIGH);
  delayMicroseconds (10);
  digitalWrite (trigpin, LOW);

  duration = pulseIn (echopin, HIGH);
  distance = duration*0.034/2;

  if (distance < 1){
  digitalWrite (enA, 0);
  digitalWrite (motordirection1, LOW);
  digitalWrite (motordirection2, LOW);
  }
  else if (distance > 2 && distance <25){
  digitalWrite (enA, SPEED);
  digitalWrite (motordirection1, HIGH);
  delay (10);
  digitalWrite (motordirection2, LOW);
  delay (50);
  digitalWrite (motordirection1, LOW);
  digitalWrite (motordirection2, LOW);
  }
  else if (distance > 15){
  digitalWrite (enA, SPEED);
  digitalWrite (motordirection1, LOW);
  delay (10);
  digitalWrite (motordirection2, HIGH);
  delay (50);
  digitalWrite (motordirection1, LOW);
  digitalWrite (motordirection2, LOW);
  }
}
```
Here is the program that I have. I'm not sure if it's good or not.

EDIT: I made the adjustment in the code and it works but now the problem is the motor only moves in 1 direction when the sensor detects something but after it's out of range the motor doesn't spin back.

body:
You wrote:
> The flow chart is as follows [...]

Rather than a flow chart, you should think of your system as a [finite
state machine][fsm], and draw its [state diagram][diagram].
Superficially, a state diagram may look like a flow chart, but it has
some specific properties:

* Within the states represented in the diagram, the machine does nothing
  but wait for some event to happen.
* Events trigger transitions between states.
* Whatever actions the machine may perform can only happen on state
  transitions.

Here is a state diagram that may represent your system:

[![State diagram of an automated garbage bin compressor][pic1]][pic1]

In this diagram, the actions are implicit (because I am lazy), but you
may want to write them down explicitly. For example, on the transition
IDLE → MOVING\_FORWARD the motor should be started, and on the next
transition (MOVING\_FORWARD → WAITING) it should be stopped.

Note also that this only represents _my understanding_ of your
specifications. You will probably have to amend it in order for it to
reflect what you really want to do.

Once you have the state diagram, the next step is... to debug it! It is
essential that you do this debugging _before_ you start to write any
line of code. At this stage I can already spot a couple of issues:

* One transition is conditioned on the “compressor” reaching its home
  position. This means that you will need some means to detect this
  event, like an [endstop][].
* After compressing some garbage... there is still garbage in the bin.
  Then, after the transition MOVING\_BACK → IDLE, garbage will be
  detected, the system will immediately transition to MOVING\_FORWARD,
  and it will get stuck in an endless loop.

Once you are done debugging the state diagram, **and only then**, can
you start writing the code. I suggest you follow the steps of [Majenko's
tutorial on finite state machines][majenko]: translating the diagram to
code should be quite straight forward.

[fsm]: https://en.wikipedia.org/wiki/Finite-state_machine
[diagram]: https://en.wikipedia.org/wiki/State_diagram
[endstop]: https://reprap.org/wiki/Mechanical_Endstop
[majenko]: https://majenko.co.uk/blog/finite-state-machine
[pic1]: https://i.stack.imgur.com/68Ak0.png


message:
How to read and Serial.print the contents (current values) of an 8-bit register?

Currently I'm using:
```
  ADMUX = 0b01100000; //example
  for (int i = 7; i >= 0; i--) {
    Serial.print(bitRead(ADMUX, i));
  }
```
This correctly prints:
```
  01100000
```
But is there a simpler way?

Before coming up with above for loop I tried using just:
```
Serial.println(ADMUX);       //converts to integers: 96
Serial.println(ADMUX, BIN);  //leaves out leading zeros: 1100000
Serial.write(ADMUX);         //converts to ASCII char: `
```
Anything else I don't know of?

body:
Another option:
```
#include <LibPrintf.h>
printf("%.8b", ADMUX); //prints: 0110000
```
The LibPrintf.h library is standard included on ESP boards.
%b stands for binary. .8 for 8 decimal places, which adds leading zero's to all truncated (binary) numbers.

It becomes *simpler if you wanted to print the variable name along with it like:
```
printf("ADMUX: %.8b", ADMUX);
```
Results in:
```
ADMUX: 01100000
```
*Simpler in the way it now only occupies a single line of code.


message:
Odd characters in serial monitor

I have been recently working on a website that takes input from the arduino ie- temperature and humidity. But there is a fatal problem that I've encountered, the serial monitor spews out some garbage with some actual readings. Is there a way to eliminate this?
```
 ╰─λ cat /dev/ttyACM0
T0°C
Humidity: 39.00%
00%
Temperature: 32.70°C
Humidity: 39.00%
Temperature: 32.70°C
Humidity: 39.00%
Temperature: 32.70°C
Humidity: 39.00%
00%
Temperature: 32.70°C
Humidity: 39.00%
Temperature: 32.70°C
Humidity: 39.00%
Temperature: 32.70°C
Humidity: 39.00%
idit9.00Tempure:70°Humi: 39
emperatu32.7
Huty: 0%
idit9.00Tempure:70°umidity.00%Tratu32.7
idit9.00Tempture.70�Humi: 39
empere: 0°Cmidi39.0
atur°C
Hum9.00

```
code-
```
#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <DHT_U.h>

#define DHTPIN 4

#define DHTTYPE    DHT11
DHT_Unified dht(DHTPIN, DHTTYPE);

uint32_t delayMS;

void setup() {
  Serial.begin(9600);
  sensor_t sensor;
  dht.begin();
  delayMS = sensor.min_delay / 1000;
}

void loop() {
  delay(delayMS);
  sensors_event_t event;
  dht.temperature().getEvent(&event);
  if (isnan(event.temperature)) {
    Serial.println(F("Error reading temperature!"));
  }
  else {
    Serial.print(F("Temperature: "));
    Serial.print(event.temperature);
    Serial.println(F("°C"));
  }
  dht.humidity().getEvent(&event);
  if (isnan(event.relative_humidity)) {
    Serial.println(F("Error reading humidity!"));
  }
  else {
    Serial.print(F("Humidity: "));
    Serial.print(event.relative_humidity);
    Serial.println(F("%"));
  }
}
```
board - Arduino Uno (R3)

body:
As has been noted in the comments, you are trying to read the sensor at a rate that is too fast.

Try changing this line:

    delayMS = sensor.min_delay / 1000;

to:

    delayMS = sensor.min_delay = 1000;

or:

    delayMS = sensor.min_delay = 3000;

This will read the sensor at a slower rate and should give you clean output.


message:
Why does "Get Board Info" not work, but I can still program my Arduino Nano?

Dear Stack Exchangers,

I have been working with Arduinos for probably 10 years, and as a habit the first thing I do when I connect a device to the USB port is run the "Tools > Get Board Info" in the Arduino IDE just to make sure I've got the correct port selected, USB cable is good, etc.

Well tonight when I connected a Nano, the "Get Board Info" didn't work at all. So after spending hours rebooting, trying different cables, etc. I eventually just tried uploading a sketch, and that worked fine! But the "Get Board Info" still does not work.

Anybody have any ideas what is going on? Thanks!

Sincerely,
Ramblin' Wreck

body:
The classic Arduino Nano uses an FTDI chip as USB to TTL Serial adapter. Many Nano (and Uno and Mega) clones use the CH340 as USB adapter. These USB chips present themselves with id set by the USB chip manufacturer. This doesn't provide a way to identify the specific board.

Original Uno and Mega Rev 3 and some clones use ATmega16u2 as USB adapter with a firmware by Arduino. Arduino sets the USB id in the firmware so it can identify as specific board type. (People reported Mega clones which presented itself as Uno).

The boards with MCU with native USB like Leonardo, Micro and ARM boards (Zero, MKR, Nano IoT, Nano BLE) provide the USB id set in boards.txt so they can be identified too.


message:
text section exceeds available space in board

When I compile this code it gives the error mentioned above.
I saw online a way to resolve this: `Serial.println(F("..."));`

For fixed string literal I changed it but still didn't work.
I'm compiling this for ESP32 board.

    #include "RMaker.h"
    #include "WiFi.h"
    #include "WiFiProv.h"
    #include <DHT.h>
    #include <SimpleTimer.h>

    const char *service_name = "PROV_SmartHome";
    const char *pop = "1234";

    // define the Chip Id
    uint32_t espChipId = 5;

    // define the Node Name
    char nodeName[] = "ESP32_Smarthome";

    // define the Device Names
    char deviceName_1[] = "Switch1";
    char deviceName_2[] = "Switch2";
    char deviceName_3[] = "Switch3";
    char deviceName_4[] = "Switch4";

    // define the GPIO connected with Relays and switches
    static uint8_t RelayPin1 = 23;  //D23
    static uint8_t RelayPin2 = 22;  //D22
    static uint8_t RelayPin3 = 21;  //D21
    static uint8_t RelayPin4 = 19;  //D19

    static uint8_t SwitchPin1 = 13;  //D13
    static uint8_t SwitchPin2 = 12;  //D12
    static uint8_t SwitchPin3 = 14;  //D14
    static uint8_t SwitchPin4 = 27;  //D27

    static uint8_t wifiLed      = 2;   //D2
    static uint8_t gpio_reset   = 0;
    static uint8_t DHTPIN       = 18; // D18  pin connected with DHT
    static uint8_t LDR_PIN      = 39; // VN  pin connected with LDR

    /* Variable for reading pin status*/
    // Relay State
    bool toggleState_1 = LOW; //Define integer to remember the toggle state for relay 1
    bool toggleState_2 = LOW; //Define integer to remember the toggle state for relay 2
    bool toggleState_3 = LOW; //Define integer to remember the toggle state for relay 3
    bool toggleState_4 = LOW; //Define integer to remember the toggle state for relay 4

    // Switch State
    bool SwitchState_1 = LOW;
    bool SwitchState_2 = LOW;
    bool SwitchState_3 = LOW;
    bool SwitchState_4 = LOW;

    float temperature1 = 0;
    float humidity1   = 0;
    float ldrVal  = 0;

    DHT dht(DHTPIN, DHT11);  //For DHT 11
    //DHT dht(DHTPIN, DHT22);  //For DHT 22

    SimpleTimer Timer;

    //The framework provides some standard device types like switch, lightbulb, fan, temperature sensor.
    static Switch my_switch1(deviceName_1, &RelayPin1);
    static Switch my_switch2(deviceName_2, &RelayPin2);
    static Switch my_switch3(deviceName_3, &RelayPin3);
    static Switch my_switch4(deviceName_4, &RelayPin4);
    static TemperatureSensor temperature("Temperature");
    static TemperatureSensor humidity("Humidity");
    static TemperatureSensor ldr("LDR");

    void sysProvEvent(arduino_event_t *sys_event)
    {
      switch (sys_event->event_id) {
        case ARDUINO_EVENT_PROV_START:
    #if CONFIG_IDF_TARGET_ESP32
          Serial.printf("\nProvisioning Started with name \"%s\" and PoP \"%s\" on BLE\n", service_name, pop);
          printQR(service_name, pop, "ble");
    #else
          Serial.printf("\nProvisioning Started with name \"%s\" and PoP \"%s\" on SoftAP\n", service_name, pop);
          printQR(service_name, pop, "softap");
    #endif
          break;
        case ARDUINO_EVENT_WIFI_STA_CONNECTED:
          Serial.printf("\nConnected to Wi-Fi!\n");
          digitalWrite(wifiLed, true);
          break;
      }
    }

    void write_callback(Device *device, Param *param, const param_val_t val, void *priv_data, write_ctx_t *ctx)
    {
      const char *device_name = device->getDeviceName();
      const char *param_name = param->getParamName();

      if (strcmp(device_name, deviceName_1) == 0) {

        Serial.printf("Lightbulb = %s\n", val.val.b ? "true" : "false");

        if (strcmp(param_name, "Power") == 0) {
          Serial.printf("Received value = %s for %s - %s\n", val.val.b ? "true" : "false", device_name, param_name);
          toggleState_1 = val.val.b;
          (toggleState_1 == false) ? digitalWrite(RelayPin1, HIGH) : digitalWrite(RelayPin1, LOW);
          param->updateAndReport(val);
        }

      } else if (strcmp(device_name, deviceName_2) == 0) {

        Serial.printf("Switch value = %s\n", val.val.b ? "true" : "false");

        if (strcmp(param_name, "Power") == 0) {
          Serial.printf("Received value = %s for %s - %s\n", val.val.b ? "true" : "false", device_name, param_name);
          toggleState_2 = val.val.b;
          (toggleState_2 == false) ? digitalWrite(RelayPin2, HIGH) : digitalWrite(RelayPin2, LOW);
          param->updateAndReport(val);
        }

      } else if (strcmp(device_name, deviceName_3) == 0) {

        Serial.printf("Switch value = %s\n", val.val.b ? "true" : "false");

        if (strcmp(param_name, "Power") == 0) {
          Serial.printf("Received value = %s for %s - %s\n", val.val.b ? "true" : "false", device_name, param_name);
          toggleState_3 = val.val.b;
          (toggleState_3 == false) ? digitalWrite(RelayPin3, HIGH) : digitalWrite(RelayPin3, LOW);
          param->updateAndReport(val);
        }

      } else if (strcmp(device_name, deviceName_4) == 0) {

        Serial.printf("Switch value = %s\n", val.val.b ? "true" : "false");

        if (strcmp(param_name, "Power") == 0) {
          Serial.printf("Received value = %s for %s - %s\n", val.val.b ? "true" : "false", device_name, param_name);
          toggleState_4 = val.val.b;
          (toggleState_4 == false) ? digitalWrite(RelayPin4, HIGH) : digitalWrite(RelayPin4, LOW);
          param->updateAndReport(val);
        }

      }
    }

    void readSensor() {

      ldrVal = map(analogRead(LDR_PIN), 400, 4200, 0, 100);
      Serial.print("LDR - "); Serial.println(ldrVal);
      float h = dht.readHumidity();
      float t = dht.readTemperature(); // or dht.readTemperature(true) for Fahrenheit

      if (isnan(h) || isnan(t)) {
        Serial.println("Failed to read from DHT sensor!");
        return;
      }
      else {
        humidity1 = h;
        temperature1 = t;
        Serial.print("Temperature - "); Serial.println(t);
        Serial.print("Humidity - "); Serial.println(h);
      }
    }

    void sendSensor()
    {
      readSensor();
      temperature.updateAndReportParam("Temperature", temperature1);
      humidity.updateAndReportParam("Temperature", humidity1);
      ldr.updateAndReportParam("Temperature", ldrVal);
    }

    void manual_control()
    {
      if (digitalRead(SwitchPin1) == LOW && SwitchState_1 == LOW) {
        digitalWrite(RelayPin1, LOW);
        toggleState_1 = 1;
        SwitchState_1 = HIGH;
        my_switch1.updateAndReportParam(ESP_RMAKER_DEF_POWER_NAME, toggleState_1);
        Serial.println("Switch-1 on");
      }
      if (digitalRead(SwitchPin1) == HIGH && SwitchState_1 == HIGH) {
        digitalWrite(RelayPin1, HIGH);
        toggleState_1 = 0;
        SwitchState_1 = LOW;
        my_switch1.updateAndReportParam(ESP_RMAKER_DEF_POWER_NAME, toggleState_1);
        Serial.println("Switch-1 off");
      }
      if (digitalRead(SwitchPin2) == LOW && SwitchState_2 == LOW) {
        digitalWrite(RelayPin2, LOW);
        toggleState_2 = 1;
        SwitchState_2 = HIGH;
        my_switch2.updateAndReportParam(ESP_RMAKER_DEF_POWER_NAME, toggleState_2);
        Serial.println("Switch-2 on");
      }
      if (digitalRead(SwitchPin2) == HIGH && SwitchState_2 == HIGH) {
        digitalWrite(RelayPin2, HIGH);
        toggleState_2 = 0;
        SwitchState_2 = LOW;
        my_switch2.updateAndReportParam(ESP_RMAKER_DEF_POWER_NAME, toggleState_2);
        Serial.println("Switch-2 off");
      }
      if (digitalRead(SwitchPin3) == LOW && SwitchState_3 == LOW) {
        digitalWrite(RelayPin3, LOW);
        toggleState_3 = 1;
        SwitchState_3 = HIGH;
        my_switch3.updateAndReportParam(ESP_RMAKER_DEF_POWER_NAME, toggleState_3);
        Serial.println("Switch-3 on");
      }
      if (digitalRead(SwitchPin3) == HIGH && SwitchState_3 == HIGH) {
        digitalWrite(RelayPin3, HIGH);
        toggleState_3 = 0;
        SwitchState_3 = LOW;
        my_switch3.updateAndReportParam(ESP_RMAKER_DEF_POWER_NAME, toggleState_3);
        Serial.println("Switch-3 off");
      }
      if (digitalRead(SwitchPin4) == LOW && SwitchState_4 == LOW) {
        digitalWrite(RelayPin4, LOW);
        toggleState_4 = 1;
        SwitchState_4 = HIGH;
        my_switch4.updateAndReportParam(ESP_RMAKER_DEF_POWER_NAME, toggleState_4);
        Serial.println("Switch-4 on");
      }
      if (digitalRead(SwitchPin4) == HIGH && SwitchState_4 == HIGH) {
        digitalWrite(RelayPin4, HIGH);
        toggleState_4 = 0;
        SwitchState_4 = LOW;
        my_switch4.updateAndReportParam(ESP_RMAKER_DEF_POWER_NAME, toggleState_4);
        Serial.println("Switch-4 off");
      }
    }

    void setup()
    {

      Serial.begin(115200);

      // Set the Relays GPIOs as output mode
      pinMode(RelayPin1, OUTPUT);
      pinMode(RelayPin2, OUTPUT);
      pinMode(RelayPin3, OUTPUT);
      pinMode(RelayPin4, OUTPUT);
      pinMode(wifiLed, OUTPUT);

      // Configure the input GPIOs
      pinMode(SwitchPin1, INPUT_PULLUP);
      pinMode(SwitchPin2, INPUT_PULLUP);
      pinMode(SwitchPin3, INPUT_PULLUP);
      pinMode(SwitchPin4, INPUT_PULLUP);
      pinMode(gpio_reset, INPUT);

      // Write to the GPIOs the default state on booting
      digitalWrite(RelayPin1, !toggleState_1);
      digitalWrite(RelayPin2, !toggleState_2);
      digitalWrite(RelayPin3, !toggleState_3);
      digitalWrite(RelayPin4, !toggleState_4);
      digitalWrite(wifiLed, LOW);
      dht.begin();    // Enabling DHT sensor

      Node my_node;
      my_node = RMaker.initNode(nodeName);

      //Standard switch device
      my_switch1.addCb(write_callback);
      my_switch2.addCb(write_callback);
      my_switch3.addCb(write_callback);
      my_switch4.addCb(write_callback);

      //Add switch device to the node
      my_node.addDevice(my_switch1);
      my_node.addDevice(my_switch2);
      my_node.addDevice(my_switch3);
      my_node.addDevice(my_switch4);
      my_node.addDevice(temperature);
      my_node.addDevice(humidity);
      my_node.addDevice(ldr);

      Timer.setInterval(2000);

      //This is optional
      RMaker.enableOTA(OTA_USING_PARAMS);
      //If you want to enable scheduling, set time zone for your region using setTimeZone().
      //The list of available values are provided here https://rainmaker.espressif.com/docs/time-service.html
      // RMaker.setTimeZone("Asia/Shanghai");
      // Alternatively, enable the Timezone service and let the phone apps set the appropriate timezone
      RMaker.enableTZService();
      RMaker.enableSchedule();

      //Service Name
      for (int i = 0; i < 17; i = i + 8) {
        espChipId |= ((ESP.getEfuseMac() >> (40 - i)) & 0xff) << i;
      }

      Serial.printf("\nChip ID:  %d Service Name: %s\n", espChipId, service_name);

      Serial.printf("\nStarting ESP-RainMaker\n");
      RMaker.start();

      WiFi.onEvent(sysProvEvent);
    #if CONFIG_IDF_TARGET_ESP32
      WiFiProv.beginProvision(WIFI_PROV_SCHEME_BLE, WIFI_PROV_SCHEME_HANDLER_FREE_BTDM, WIFI_PROV_SECURITY_1, pop, service_name);
    #else
      WiFiProv.beginProvision(WIFI_PROV_SCHEME_SOFTAP, WIFI_PROV_SCHEME_HANDLER_NONE, WIFI_PROV_SECURITY_1, pop, service_name);
    #endif

      my_switch1.updateAndReportParam(ESP_RMAKER_DEF_POWER_NAME, false);
      my_switch2.updateAndReportParam(ESP_RMAKER_DEF_POWER_NAME, false);
      my_switch3.updateAndReportParam(ESP_RMAKER_DEF_POWER_NAME, false);
      my_switch4.updateAndReportParam(ESP_RMAKER_DEF_POWER_NAME, false);
    }

    void loop()
    {
      // Read GPIO0 (external button to reset device
      if (digitalRead(gpio_reset) == LOW) { //Push button pressed
        Serial.printf("Reset Button Pressed!\n");
        // Key debounce handling
        delay(100);
        int startTime = millis();
        while (digitalRead(gpio_reset) == LOW) delay(50);
        int endTime = millis();

        if ((endTime - startTime) > 10000) {
          // If key pressed for more than 10secs, reset all
          Serial.printf("Reset to factory.\n");
          RMakerFactoryReset(2);
        } else if ((endTime - startTime) > 3000) {
          Serial.printf("Reset Wi-Fi.\n");
          // If key pressed for more than 3secs, but less than 10, reset Wi-Fi
          RMakerWiFiReset(2);
        }
      }
      delay(100);

      if (WiFi.status() != WL_CONNECTED)
      {
        //Serial.println("WiFi Not Connected");
        digitalWrite(wifiLed, false);
      }
      else
      {
        //Serial.println("WiFi Connected");
        digitalWrite(wifiLed, true);
        if (Timer.isReady()) {
          //Serial.println("Sending Sensor Data");
          sendSensor();
          Timer.reset();      // Reset a second timer
        }
      }
      manual_control();
    }

ESP32 Board details here :

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

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

body:
You are programming for an embedded processor with limited memory.  Both program space and random access memory (RAM).  Every letter you put in quotes takes up a byte of memory. If you are only over the limit by a little consider abbreviating your text.  For example consider changing strings like:

> "Provisioning Started with name"

... to something along the lines of ...

> "Prov name"

If by a lot then consider changing your code.  Many times you quote similar text. For example consider changing the following code:

    // define the Device Names
    char deviceName_1[] = "Switch1";
    char deviceName_2[] = "Switch2";
    char deviceName_3[] = "Switch3";
    char deviceName_4[] = "Switch4";
    ...
    //The framework provides some standard device types like switch, lightbulb, fan, temperature sensor.
    static Switch my_switch1(deviceName_1, &RelayPin1);
    static Switch my_switch2(deviceName_2, &RelayPin2);
    static Switch my_switch3(deviceName_3, &RelayPin3);
    static Switch my_switch4(deviceName_4, &RelayPin4);

... to something along the lines of ...

    //The framework provides some standard device types like switch, lightbulb, fan, temperature sensor.
    String stringOne = "Switch";
    String stringTwo = "1"
    static Switch my_switch1(stringOne + stringTwo, &RelayPin1);
    stringTwo = "2"
    static Switch my_switch2(stringOne + stringTwo, &RelayPin2);
    stringTwo = "3"
    static Switch my_switch3(stringOne + stringTwo, &RelayPin3);
    stringTwo = "4"
    static Switch my_switch4(stringOne + stringTwo, &RelayPin4);

... the point here is to avoid using up program and random access memory with repeated strings.


body:
You could use enums to replace all the char strings (which take a lot of memory space) into integers behind the scene.
```
enum deviceNames {Switch1, Switch2, Switch3, Switch4};
deviceNames deviceName; //define variable of type deviceNames
```
for comparison you can use:
```
if (deviceName == Switch1); //Switch1 equals 0 for the compiler, Stich2 equals 1 etc etc.
```
Frist however, you should have a look at the functions getDeviceName() and getParamName(). Could you post them? Would need to see if you can make these changes there aswell.
Since you are getting the variable device_name from there, again as a string. Enums would do no good without additional changes to the functions.

*Also I noticed you still didn't use Serial.print(F());
Read up on storing strings and variables into PROGMEM if you're interested.

*EDIT:
As user Juraj noted in the comments: "the esp32 toolchain uses string literals from flash automatically. the F macro does nothing".

Perhaps you can benefit form newlib nano formatting for printf? I'm not sure as I don't know what difference it makes on your esp32 version. You'll have to check out.


body:
Maybe I've missed something, but the flash area is partitioned between usable app (roughly sketch code) space and usable filesystem space. I don't see any indication in your question that you're using a filesystem at all.

Keeping your current settings except for switching the partition setting to *"Huge APP (3MB No OTA/1MB SPIFFS)"* resulted in:

```txt
Sketch uses 1790473 bytes (56%) of program storage space. Maximum is 3145728 bytes.
Global variables use 53260 bytes (16%) of dynamic memory, leaving 274420 bytes for local variables. Maximum is 327680 bytes.
```

I'm not even sure "Huge APP" makes the _most_ sense. Only that 3MB is larger than 1.2MB and larger than your current 1.8(ish)MB build apparently needs. It says "no-OTA" but you don't seem to be using that either. So, this seems like something you can do irrespective of whatever contributions you can trim from the text segment by tweaking your code.


message:
Read Digital Input from Arduino Pin defined as OUTPUT

I'm working on a Home Automation Project.
I can turn on-off ESP32 pin from Alexa and Google Assistant Successfully now.

What I need help is with a way to read if the AC supply is ON/OFF on the Arduino pin.
Or if possible to save pins I would want to read it on the same pin which id defined as Digital output to control the relay.

Below attached image of what I have in mind.
1. Normal switch turns On/off supply to load without any requirement of WiFi.
2. Load is also connected to Relay NO, which is controlled by Arduino Pin D13.

What I want is instead of just reading the status of the D13 pin, I want to read the status of the Mechanical Switch which directly provide to Load.

So I'll actual status of the Load whether it's turned on by Switch or Relay with interrupting directly connected switch from load to supply.

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

Edited: As others suggested it is not possible to use the Same Pin to control the relay and read AC load status. So is there a way to read the AC supply through the GPIO pin of ESP32 maintaining galvanic isolation, (opposite working of Relay)?

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

body:
What you want to do is not possible, you'll need an extra pin. The reason is that the relay requires a lot of current (works like a very strong pulldown resistor). So, whatever (high impedance) sense signal you apply to the relay, it will just be "consumed" by the relay.

When reading the state of the switch, i.e. the voltage across it, galvanic isolation is absolutely mandatory (mains voltage can be deadly). This can be achieved with an opto coupler and some lines of code or additional hardware - as it's AC voltage, you can't simply read a steady voltage, so you'd either have to sample the AC signal or incorporate some kind of circuitry (software is simpler and cheaper).

Another issue with your circuit is that you must not drive the relay directly with the GPIO. The relay sinks way to much current, it'll fry the GPIO. Use a transistor to switch it.


body:
If you want to know the state of the load, I suggest to put the
mechanical switch on the low-voltage side of the relay:

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

The voltage divider R1/R2 is meant to lower the
voltage at the transistor's collector (up to one diode threshold above
Vcc) to a value suitable for the Arduino digital input.

Note that you still need two separate inputs for controlling and for
sensing the state.


message:
Is there a way to strip a library from all unused parts and defines, automatically?

Say you want to investigate part of the code you use from a rather large library, but it's buried between all kinds of #defines and classes etc, that you're never gonna use in your code.
Is there a tool for stripping those unused/unnecessary parts away (like the (pre-)compiler), without converting it to machine language? That would make it much easier to see what happens in the code, and what code does what. Would be a great learning tool imho.

body:
The compiler is called in optimization mode (it is even possible to specify how aggressive it will optimize). It will remove all variables and functions, that are not used in your code. Also it can replace variables that never change with literals to make the code smaller. That's already what is happening and you don't need to worry about that.

About the `#define`s: Everything with a # at the start is interpreted by the preprocessor. That means, that these things are done even before the compiler gets to see the code. Lets say you define a pin number via `#define pin 6`, then the preprocessor will replace any mentioning of `pin` with `6` in the code, before it hands the result over to the compiler. The compiler will never see any defines.

I'm not able to tell you, how the compiler optimizes the code. That's probably very complex. Though the avr-gcc compiler is opensource, so if you really want to learn what it does, you can always analyze its source code.

---

> I thought if a compiler can be smart enough to strip all unused variables and functions away and convert what's left in machine language

While I don't know much about how the optimization works, I don't think that it happens in that order. I find it very unlikely, that the compiler would optimize the C++ code. Though it might do that at the assembler level (since avr-gcc first converts the C++ code to assembler and then compiles to machine code). Searching in the assembler code equivalent of the C++ code isn't a real option either.

You are probably stuck with a full text search function of a program of your choice. Most OSs will also provide that function out of the box. I know, that you can search all files of a directory for a term from the Windows explorer. On systems like Ubuntu/Debian/CentOS and similar you can use the `grep` command in recursive mode to search for a term. On Mac you can probably also use `grep`.


body:
The compiler doesn't quite work like that. It compiles each individual .cpp file into an object file (the .ino file becomes a .cpp file after a bit of pre-processing). I have [an answer](https://arduino.stackexchange.com/questions/13178/classes-and-objects-how-many-and-which-file-types-do-i-actually-need-to-use-the/13182#13182) about the exact process the compiler uses there.

The libraries are also collections of .cpp files which also get turned into object files.

Optimization of unused variables would occur at that point. In other words, the compiler can optimize one compilation unit (one source file) because it can see what parts are used and what are not.

Then the linking phase commences which joins all the object files together, looking for places where a function in a library is called. So for example if you call `Serial.begin()` somewhere, then the linker will try to find an object file which implements that.

The linker is smart enough to not include code that is not required, so for example, if you never called `Serial.begin ()` then it would not copy in that part of the Serial library.

In the process of doing that it resolves "jumps" and subroutine calls, so that your calls to library functions end up pointing to the place in the program memory where it has put them.

Because this is done at a late stage (after the source has been compiled) you don't really ever have a copy of the source "as linked".

However what you **can** do is disassemble the object file which gives you the machine code that has actually made it to the final executable. Done properly it will also include the lines of source (C++) code that generated each batch of assembler lines.

If you turn on "verbose compiling" you should see near the end of the compilation output an "ELF" file, and you can then send that to avr-objdump to turn it back into assembler:

    avr-objdump -S xxx.elf

It's not great, if you aren't used to assembler, but it gives you a clue as to what made it into the executable file, and where. For a single line of C++ code you might see something like this:

     reg = portModeRegister(port);
     310: 90 e0        ldi r25, 0x00 ; 0
     312: 88 0f        add r24, r24
     314: 99 1f        adc r25, r25
     316: fc 01        movw r30, r24
     318: e8 59        subi r30, 0x98 ; 152
     31a: ff 4f        sbci r31, 0xFF ; 255
     31c: a5 91        lpm r26, Z+
     31e: b4 91        lpm r27, Z+


body:
The -E command for gcc generates preprocessed C and CPP source.

I didn't find a way to integrate it into the Arduino build process. Only thing I could do was edit platform.txt and change the compile command so it generates the preprocessed cpp of a compilation unit instated of .o files. Then linking failed of course.

The produced cpp was I think less readable than the original because it contained many generated comments and original line number instructions.

the changed cpp recipe in platform txt:
```
recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.cpp.extra_flags} {build.extra_flags} -E {includes} "{source_file}" -o "{object_file}.cpp"
```
I added the -E flag and .cpp file extension for the -o option value

You can see the result in the temporary build folder. You can get the location of that folder from the IDE console when you build the sketch with Verify. (you may need to turn on the verbose compile in Preferences).


message:
MFRC522 board not detected. Red LED lighting

Mega 2560.
I can't get the RFID board detected. The code is below, and outputs "Didn't find MFRC522 board.". I also tested some other library and test code with success.

I triple checked the wires (3,3V pin, gnd, and PWM pin 8 and 9).

I have some questions:

1. All tutorials shows that MOSI, MISO, SCK needs to be hooked up to digital pin 50, 51, 52. But I don't understand why these matter, because they are not referenced in any code I've found? Are they really necessary? And if so, does it have to be 50,51,52? Can't it be any other digital pin?

2. I accidentally connected it to 5V at first, for maybe 1 minute. Could it be burnt? The LED still lights RED when connected with power.

3. If the problem was the (correct) library was not loaded, wouldn't I get a compile error?

I'm running this code:

    #include <MFRC522.h>
    #include <SPI.h>

    #define SAD 9
    #define RST 8

    MFRC522 nfc(SAD, RST);

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

      Serial.println("Looking for MFRC522.");
      nfc.begin();

      uint8_t version = nfc.getFirmwareVersion();
      if (! version) {
        Serial.print("Didn't find MFRC522 board.");
        while(1); //halt
      }

      Serial.print("Found chip MFRC522 ");
      Serial.print("Firmware ver. 0x");
      Serial.print(version, HEX);
      Serial.println(".");

      if (nfc.digitalSelfTestPass()) {
          Serial.print("Digital self test by MFRC522 passed.");
      } else {
          Serial.print("Digital self test by MFRC522 failed.");
      }
    }

    void loop() {

    }

body:
Welcome, hopefully we can help you. You do not have to connect MOSI, MISO, SCK, CS if you do not want to however without them connected properly it will not work. Note you did not mention the CS pin, that is also needed as that is what tells the MFRC522 it has been selected. Those pins are what is used to communicate with the device. The pins may be different for different boards but you need to check the data sheet for that. The numbers appear correct for the Mega.

The LED tells you that there is power there, it in no way tells you if the board is good. Did you fry it, probably probably as the MFRC522 is a 3V3 device but that is not a given as I do not know what pin you connected the 5V to. More than a few nanoseconds on a voltage higher than rated tends to fry things, but you could be lucky I have no way of knowing. The Mega is 5V so that would probably be OK.

You ask: "If the problem was the (correct) library was not loaded, wouldn't I get a compile error?", again no not necessarily. The compiler does not know your design or what you are connecting to. If the library happens to have functions etc appropriately named it will compile with errors but the odds are very slim your code will work.


message:
Why doesn't my mcp23s17 interrupts work anymore?

I'm using a teensy 4.0 with two mcp23s17 gpio expanders where #1 has 16 buttons wired to it, and #2 has 4 buttons and six rotary encoders. To run everything I'm using majenkos mcp23s17 library. Recently, I refactored my code, and suddenly I'm unable to setup the mcp's to have interrupts working properly.

I've tried to narrow the problem down by commenting out code, and it appears that as soon as I call         ```gpioExpander.enableInterrupt(pin, CHANGE);``` in ```gpioSetup()``` the problem occurs. In detail, ```loop()``` runs fine, but as soon as I press a button, the teensy hangs. Also, to restore the teensy I have to upload the code with the call to ```gpioExpander.enableInterrupt(pin, CHANGE);``` commented out in order to have the teensy up and running again.

I've been staring myself blind on the code, and I suspect I'm missing something obvious. Your help is appreciated.

```c++ [code]
//main.cpp
#include <Arduino.h>

#include "GPIO.h"
#include "MCP23S17.h"

extern MCP23S17 gpioExpander1;
extern MCP23S17 gpioExpander2;

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

void loop() {
    GPIOtest(gpioExpander1, gpioExpander2);
}

//GPIO.h
#ifndef GPIO_H
#define GPIO_H

#include <Arduino.h>

#include "MCP23S17.h"

constexpr uint8_t address = 0;
constexpr uint8_t interruptPin1 = 8;
constexpr uint8_t interruptPin2 = 22;
constexpr uint8_t chipSelectPin1 = 7;
constexpr uint8_t chipSelectPin2 = 21;

void setGPIO1Pins(MCP23S17 &gpioExpander);
void setGPIO2Pins(MCP23S17 &gpioExpander);
void gpioSetup();
void GPIO1interrupt();
void GPIO2interrupt();
void GPIOtest(MCP23S17 &gpioExpander1, MCP23S17 &gpioExpander2);

#endif

//GPIO.cpp
#include "GPIO.h"

#include <Arduino.h>
#include <MCP23S17.h>

volatile bool interruptFlag1 = false;
volatile bool interruptFlag2 = false;

MCP23S17 gpioExpander1(&SPI, chipSelectPin1, address);
MCP23S17 gpioExpander2(&SPI, chipSelectPin2, address);

//  Set all Port Expander pins to desired mode INPUT_PULLUP
//  Set all Port Expander input pins interrupts
void setGPIOPins(MCP23S17& gpioExpander) {
    for (uint8_t pin = 0; pin <= 15; ++pin) {
        gpioExpander.pinMode(pin, INPUT_PULLUP);
        gpioExpander.enableInterrupt(pin, CHANGE);
    }

    // set Port Expander Interrupt configuratons
    gpioExpander.setMirror(true);
    gpioExpander.setInterruptOD(false);
    gpioExpander.setInterruptLevel(LOW);
}

void gpioSetup() {
    gpioExpander1.begin();
    gpioExpander2.begin();
    digitalWrite(chipSelectPin1, HIGH);
    digitalWrite(chipSelectPin2, HIGH);

    pinMode(interruptPin1, INPUT_PULLUP);
    pinMode(interruptPin2, INPUT_PULLUP);

    attachInterrupt(digitalPinToInterrupt(interruptPin1), GPIO1interrupt, LOW);
    attachInterrupt(digitalPinToInterrupt(interruptPin2), GPIO2interrupt, LOW);

    setGPIOPins(gpioExpander1);
    setGPIOPins(gpioExpander2);

    // GPIO registers are read to be cleared
    gpioExpander1.getInterruptValue();
    gpioExpander2.getInterruptValue();
}

void GPIO1interrupt() {
    interruptFlag1 = true;
}

void GPIO2interrupt() {
    interruptFlag2 = true;
}

void GPIOtest(MCP23S17& gpioExpander1, MCP23S17& gpioExpander2) {
    if (interruptFlag1 == true) {
        Serial.println("interrupt 1 = true");
        interruptFlag1 = false;
    }

    if (interruptFlag2 == true) {
        Serial.println("interrupt 2 = true");
        interruptFlag2 = false;
    }
}
```

body:
### Short version, try:

```c++
attachInterrupt(digitalPinToInterrupt(interruptPin1), GPIO1interrupt, FALLING);
attachInterrupt(digitalPinToInterrupt(interruptPin2), GPIO2interrupt, FALLING);
```

**`FALLING`** (instead of `LOW`) being the [active ingredient][1]. I'm assuming `FALLING` is supported. If not you can try synthesizing this with `CHANGE` and reading the port to see whether or not it is currently `LOW`.

And then call `.getInterruptValue();` to clear the MCP23S17's interrupt condition where you clear the global volatile flags:

```c++
void GPIOtest(MCP23S17& gpioExpander1, MCP23S17& gpioExpander2) {
    if (interruptFlag1 == true) {
        Serial.println("interrupt 1 = true");
        interruptFlag1 = false;
        gpioExpander1.getInterruptValue(); // <------
    }

    if (interruptFlag2 == true) {
        Serial.println("interrupt 2 = true");
        interruptFlag2 = false;
        gpioExpander2.getInterruptValue(); // <------
    }
}
```

---

### Long version:

This a guess, since I'm unable to test. But this is maybe not a bad guess:

You have configured the MCP23S17 device to **drive** active **low** on/during an MCP23S17 interrupt condition:
```c++
    gpioExpander.setMirror(true);
    gpioExpander.setInterruptOD(false);
    gpioExpander.setInterruptLevel(LOW);
```

So, were an MCP23S17 interrupt to occur (`gpioExpander.enableInterrupt(pin, CHANGE);`), the interrupt flag within the MCP23S17 would be set, and INTA/INTB of the MCP23S17 would become active low.

The MCP23S17 datasheet says:

> The interrupt condition is cleared after the LSb of the data is
> clocked out during a read command of GPIO or INTCAP

You have configured your interrupt pins for interrupting on a LOW **level** interrupt:
```c++
attachInterrupt(digitalPinToInterrupt(interruptPin1), GPIO1interrupt, LOW);
```

So, if I understand this correctly, your Teensy continually re-enter the `GPIO#interrupt()` functions until something read causes the interrupt condition to be cleared. You are not clearing the interrupt condition **inside** the ISR, you're setting a flag to do that later in the main line of execution, which is reasonable by itself. One thing I can guess is that had you'd previous had something to clear the interrupt condition **inside** the interrupt and it is now outside the interrupt, namely your call to `.getInterruptValue()`, which [reads the INTCAP register][2] mentioned above. Or perhaps you'd be using [one of the functions][3] that reads a pin/port that would have cleared the interrupt condition. Clearing the global variable alone will not clear the interrupt condition, and so you're going to go right back into ISR which will reassign the global variable.

An AVR will execute a single instruction outside of the ISR before reentering the ISR. So the effect of remaining in the interrupt condition is to make your code slow, potentially **very** slow. I don't know off the top of my head what the Teensy 4.x core will do in this case. Either way, it _would_ lock up or possibly _look_ locked up.

*If* you were reading/getting-interrupt-value inside the ISR it would have cleared it and so it would not re-entered the ISR repeatedly. Or rather, it wouldn't do that in definitely (or just for long). *It possible that the Teensy is so much faster that it might re-enter a few times until the MCP23S17 got around to acknowledging that the interrupt condition had be cleared. I'm not advocating for this so, so I'll leave it at that.*

I believe ultimately what you want is to set a `FALLING` edge interrupt:
```c++
attachInterrupt(digitalPinToInterrupt(interruptPin1), GPIO1interrupt, FALLING);
```

Anyway, with `FALLING` the initial falling edge of the INTA/INTB line sets the interrupt condition in the Teensy (not MCP23S17) but it is cleared when your ISR executes.  So you will not keep re-entering the ISR. So your ISR will enter _once_ to set the global `volatile` flag. Later when you pick up on the set value of your global `volatile` flag(s), you need to call `.getInterruptValue()` (or otherwise read a pin) to clear the interrupt condition in your MCP23S17 (not Teensy) which will de-assert/raise INTA/INTB, at which point the ISR in the Teensy is ready for to get trigger by another falling edge of INTA/INTB.

It's also probably possible to do this with a `LOW`-level interrupt, but you'd have keep un-configuring them in the ISR and re-configuring them after you clear the MCP23S17's condition. Not sure that would be recommended. But, I think it's possible.

  [1]: https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/
  [2]: https://github.com/MajenkoLibraries/MCP23S17/blob/6f6bac/src/MCP23S17.cpp#L503-L505
  [3]: https://github.com/MajenkoLibraries/MCP23S17/blob/6f6bac/src/MCP23S17.cpp#L348-L352


message:
How to count steps of a stepper motor with AccelStepper?

I want to turn on my motor and count how many total rounds it has until my limit switch is switched on. After that, I want to count rounds counterclockwise until another limit switch is pushed. For this, I'm using [AccelStepper][1] and ezButton lib.

Here is my code:
```C++
      if ((limitSwitch_XV.getState() == LOW) && (limitSwitch_XE.getState() == LOW) && rightDirectionX) {
        while (1) {
          stepper1.step(-1);
          stageSizeX++;
        }
      }
```

But here I've got an error which says that I can't use `int` in `step()`: `'virtual void AccelStepper::step(long int)' is protected within this context stepper1.step(1);`

So how can I count the steps and go step by step to the given direction until I reach the limit switch with AccelStepper?

  [1]: https://www.airspayce.com/mikem/arduino/AccelStepper/classAccelStepper.html#aa4a6bdf99f698284faaeb5542b0b7514

body:
You get that error, because the `step()` method is protected in the AccelStepper class. It is not meant for calling by the user. AccelStepper instead wants you to state, what kind of movement you want (moving a specific distance/to a specific point/with a specific speed) and then frequently call the `AccelStepper.run()` method (or `AccelStepper.runSpeed()`), which will then execute the steps, when it is time to do so based on your planned movement.

---

If you want to solve your problem you have basically two ways to do this:

- With AccelStepper: Set the stepper to run at a specific speed in the correct direction, then in a loop calling `stepper1.runSpped()` and testing your limitswitch with `digitalRead()`. So something along the lines of:

        stepper1.setCurrentPosition(0);
        stepper1.setSpeed(20); // Change speed according to your needs, negative values let the motor rotate in the other direction
        while(limitSwitch_XV.getState() == HIGH){ // Assuming, that limit switch is not pressed when HIGH
            stepper1.runSpeed();
        }
        int revolutions = stepper1.currentPosition() / steps_per_revolution;

- or without AccelStepper: Depending on your stepper driver you can use a less sophisticated stepper library (like Arduinos `Stepper` library) or just control the stepper directly with `digitalWrite()` calls (to the Dir pin and to the Pulse pin). In that case you can do each step yourself, after each checking for the limit switch with `digitalRead()`. Something along the lines (I assume a stepper driver with dir pin and pulse pin, not one with multiple phase pins):

        digitalWrite(dir_pin, direction); // provide HIGH or LOW here depending on wanted direction
        int pos = 0;
        while(limitSwitch_XV.getState() == HIGH){
            digitalWrite(pulse_pin, HIGH);
            delayMicroseconds(10);
            digitalWrite(pulse_pin, LOW);
            pos++;
            delayMicroseconds(50); // Change this value according to the wanted speed
        }
        int revolutions = pos / steps_per_revolution;

Note, that both code snippets are totally untested and you need to build the surrounding code yourself. They only highlight the principle.


message:
Can i use SCL, SDA pin for I2C

I read [this article][1]. In the article, it uses A4 and A5 for I2C. But can I just use SCL and SDA pin directly in the Arduino UNO R3? And do I need a put-up resistor for SCL and SDA pin?

  [1]: https://playground.arduino.cc/Main/I2CBi-directionalLevelShifter/

body:
Pins A4/A5 and the SCL/SDA pins are *the exact same pins* on the Arduino UNO R3. Not just "they perform the same function", but they are physically the same pins. It is one solid piece of metal from one pin to the other.

You don't *need* pullup resistors on the I2C pins because the `Wire` library turns on the internal pullups by default. However those internal pullups are about a tenth of the strength that I2C pullups *should* be, so I would recommend that you *do* add pullups, certainly for anything more than a couple of inches of wire.


message:
On Linux Min21, unable to access tools/port (grayed out)

I have dual boot laptop, Windows 11 & Linux Mint 21 (default boot).  when running Arduino IDE 1.8.19 using Linux the port not accessible [from tools/port], but if I boot as windows, I can access the port from the Arduino IDE.

Other applications running in Linux can access the USB drive without issue (eg FreeCAD, PrusaSlicer). Arduino IDE is the only app so far with this USB issue.

"dialout" is in my list of groups

Arduino IDE was installed using apt

If I run lsusb when the nano is connected, i see the following extra entry

    Bus 003 Device 009: ID 1a86:7523 QinHeng Electronics CH340 serial converter

On another post it suggested running ls -l /dev/ttyUSB* and ls -l /dev/ttyACM*. For both I get the response "No such file or directory". The following files starting with tty* are in the /dev directory

```
tty    tty11  tty15  tty19  tty22  tty26  tty3   tty33  tty37  tty40  tty44  tty48  tty51  tty55  tty59  tty62  tty9       ttyS10  ttyS14  ttyS18  ttyS21  ttyS25  ttyS29  ttyS4  ttyS8
tty0   tty12  tty16  tty2   tty23  tty27  tty30  tty34  tty38  tty41  tty45  tty49  tty52  tty56  tty6   tty63  ttyprintk  ttyS11  ttyS15  ttyS19  ttyS22  ttyS26  ttyS3   ttyS5  ttyS9
tty1   tty13  tty17  tty20  tty24  tty28  tty31  tty35  tty39  tty42  tty46  tty5   tty53  tty57  tty60  tty7   ttyS0      ttyS12  ttyS16  ttyS2   ttyS23  ttyS27  ttyS30  ttyS6
tty10  tty14  tty18  tty21  tty25  tty29  tty32  tty36  tty4   tty43  tty47  tty50  tty54  tty58  tty61  tty8   ttyS1      ttyS13  ttyS17  ttyS20  ttyS24  ttyS28  ttyS31  ttyS7

```

If I tail the system log and plug the nano into the usb drive I get the following (the answer my be here but I cant see it).

```
Oct  7 17:17:14 HP-Envyl kernel: [ 8949.381626] usb 3-4: new full-speed USB device number 14 using xhci_hcd
Oct  7 17:17:14 HP-Envyl kernel: [ 8949.599105] usb 3-4: New USB device found, idVendor=1a86, idProduct=7523, bcdDevice= 2.64
Oct  7 17:17:14 HP-Envyl kernel: [ 8949.599107] usb 3-4: New USB device strings: Mfr=0, Product=2, SerialNumber=0
Oct  7 17:17:14 HP-Envyl kernel: [ 8949.599108] usb 3-4: Product: USB Serial
Oct  7 17:17:14 HP-Envyl kernel: [ 8949.601365] ch341 3-4:1.0: ch341-uart converter detected
Oct  7 17:17:14 HP-Envyl mtp-probe: checking bus 3, device 14: "/sys/devices/pci0000:00/0000:00:14.0/usb3/3-4"
Oct  7 17:17:14 HP-Envyl mtp-probe: bus: 3, device: 14 was not an MTP device
Oct  7 17:17:14 HP-Envyl kernel: [ 8949.601888] usb 3-4: ch341-uart converter now attached to ttyUSB0
Oct  7 17:17:14 HP-Envyl systemd[1]: Starting Braille Device Support...
Oct  7 17:17:14 HP-Envyl brltty[12613]: BRLTTY 6.4 rev BRLTTY-6.4 [https://brltty.app/]
Oct  7 17:17:14 HP-Envyl brltty[12613]: BRLTTY 6.4 rev BRLTTY-6.4 [https://brltty.app/]
Oct  7 17:17:14 HP-Envyl brltty[12613]: executing as the invoking user: root
Oct  7 17:17:14 HP-Envyl brltty[12613]: brltty: executing as the invoking user: root
Oct  7 17:17:14 HP-Envyl mtp-probe: checking bus 3, device 14: "/sys/devices/pci0000:00/0000:00:14.0/usb3/3-4"
Oct  7 17:17:14 HP-Envyl mtp-probe: bus: 3, device: 14 was not an MTP device
Oct  7 17:17:14 HP-Envyl brltty[12613]: CLDR open error: No such file or directory: /usr/share/unicode/cldr/common/annotations/en.xml
Oct  7 17:17:14 HP-Envyl brltty[12613]: brltty: CLDR open error: No such file or directory: /usr/share/unicode/cldr/common/annotations/en.xml
Oct  7 17:17:14 HP-Envyl brltty[12613]: brltty: possible cause: the package that defines the CLDR annotations directory is not installed
Oct  7 17:17:14 HP-Envyl brltty[12613]: brltty: emoji substitutiion won't be performed
Oct  7 17:17:14 HP-Envyl brltty[12613]: brltty: BrlAPI Server: release 0.8.3
Oct  7 17:17:14 HP-Envyl brltty[12613]: possible cause: the package that defines the CLDR annotations directory is not installed
Oct  7 17:17:14 HP-Envyl systemd[1]: Started Braille Device Support.
Oct  7 17:17:14 HP-Envyl brltty[12613]: emoji substitutiion won't be performed
Oct  7 17:17:14 HP-Envyl brltty[12613]: BrlAPI Server: release 0.8.3
Oct  7 17:17:14 HP-Envyl brltty[12613]: Linux Screen Driver:
Oct  7 17:17:14 HP-Envyl brltty[12613]: brltty: Linux Screen Driver:
Oct  7 17:17:14 HP-Envyl kernel: [ 8950.123164] input: BRLTTY 6.4 Linux Screen Driver Keyboard as /devices/virtual/input/input49
Oct  7 17:17:15 HP-Envyl brltty[12613]: USB configuration set error 16: Device or resource busy
Oct  7 17:17:15 HP-Envyl brltty[12613]: brltty: USB configuration set error 16: Device or resource busy
Oct  7 17:17:15 HP-Envyl brltty[12613]: USB interface in use: 0 (ch341)
Oct  7 17:17:15 HP-Envyl brltty[12613]: brltty: USB interface in use: 0 (ch341)
Oct  7 17:17:15 HP-Envyl ModemManager[1013]: <info>  [base-manager] port ttyUSB0 released by device '/sys/devices/pci0000:00/0000:00:14.0/usb3/3-4'
Oct  7 17:17:15 HP-Envyl ModemManager[1013]: <info>  [base-manager] couldn't check support for device '/sys/devices/pci0000:00/0000:00:14.0/usb3/3-4': Operation was cancelled
Oct  7 17:17:15 HP-Envyl kernel: [ 8950.239032] usb 3-4: usbfs: interface 0 claimed by ch341 while 'brltty' sets config #1
Oct  7 17:17:15 HP-Envyl kernel: [ 8950.239683] ch341-uart ttyUSB0: ch341-uart converter now disconnected from ttyUSB0
Oct  7 17:17:15 HP-Envyl kernel: [ 8950.239693] ch341 3-4:1.0: device disconnected
Oct  7 17:17:15 HP-Envyl brltty[12613]: NoSpeech Speech Driver:
Oct  7 17:17:15 HP-Envyl brltty[12613]: brltty: NoSpeech Speech Driver:
Oct  7 17:17:18 HP-Envyl rtkit-daemon[3252]: Supervising 10 threads of 3 processes of 1 users.
```

Does anyone have any idea what can cause this issue?

body:
OK, i can close this. brtty was the problem. I disabled it (found instructions below on another post)
```
systemctl stop brltty-udev.service
sudo systemctl mask brltty-udev.service
systemctl stop brltty.service
systemctl disable brltty.service
```
After logout and login, it works now.

Thanks for the help. I did not have this issue on Mint 20, so i am guessing that brtty was automatic in Mint 21