message:
Why are my thermistor readings backward?

I'm trying to build a thermistor that will flash an LED when the temperature is above 30 C. My set-up appeared to be reporting the room temperature correctly to the Serial Monitor, but then I noticed that exposing the thermistor to a hot object causes the reported temperature to drop, whereas exposing it to a cold object causes the reported temperature to rise.

I'd built a simpler thermistor circuit earlier with a similar approach and everything seemed to function correctly. I'm not sure what I broke here:

```
const int WarningLED = 7;
const int Thermistor = 0;

/* Thermistor information:
 * P/N: BC2301-ND
 * MFG P/n: NTCLE100E3103JB0
 * DESC: THERMISTOR NTC 10KOHM 3977K BEAD, IDX: 1 */

int Vo; // voltage between thermistor and R1
float R1 = 10000; //10 KOHM resistor used for voltage divider
float TR; // resistance of negative temperature coefficient (NTC) thermistor
float beta;  //beta will later equal ln( TR / Rref )
float Tk, Tc, Tf;

/* Steinhart-Hart equation coefficients via data table at
 * http://www.vishay.com/docs/29049/ntcle100.pdf
 * Bead used: 3977K (refer to #9 values on Nominal R table) */
float A = 3.354016e-03,B = 2.569850e-04;
float C = 2.620131e-06,D = 6.383091e-08;

void setup() {
  pinMode(WarningLED, OUTPUT); //sets the warning LED pin as a digital output
  Serial.begin(9600);          //  setup a serial port to enable comms with the computer.
 }

void loop() {

  Vo = analogRead(Thermistor);
  Serial.print("Vo: ");
  Serial.print(Vo);
  Serial.println(" mV");

  //Voltage divider equation: R2 = R1 * [Vo / (Vi - Vo)]
  //where R2 = TR, Vi = 1023.0 :
  TR = R1 * ((float)Vo / (1023.0 - (float)Vo));
  Serial.print("Thermistor resistance: ");
  Serial.print(TR);
  Serial.println(" ohms");

  beta = log(TR/10000); // As per extended Steinhart-Hart equation,
  //  where Rref = 10,000 (refer to page 10 of the PDF linked above)
  Tk = (1.0 / (A + B*beta + C*beta*beta + D*beta*beta*beta));
  Tc = Tk - 273.15;
  Tf = (Tc * 9.0)/ 5.0 + 32.0;

  Serial.print("Temperature: ");
  Serial.print(Tk);
  Serial.print(" K; ");
  Serial.print(Tf);
  Serial.print(" F; ");
  Serial.print(Tc);
  Serial.println(" C");
  Serial.println();

  if (Tc > 30.0) digitalWrite(WarningLED, HIGH);
  else if (Tc < 30.0) digitalWrite(WarningLED, LOW);
  delay(1000);
}
```
On the Serial Monitor, this reports:
```
Vo: 550 mV
Thermistor resistance: 11627.91 ohms
Temperature: 294.74 K; 70.86 F; 21.59 C
```

Exposing this to a warmer temperature incorrectly reports:
```
Vo: 597 mV
Thermistor resistance: 14014.08 ohms
Temperature: 290.61 K; 63.43 F; 17.46 C
```

I notice that, among other issues, this is reporting increased resistance in the thermistor despite that I'm using an NTC, but I'm not sure why this is occurring.

Notable parts used in this circuit:

 - Thermistor: NTCLE100E3103JB0
 - R1: 10 KOHM
 - R2: 1 KOHM
 - C1 & C2: 33 nf

[![circuit diagram][1]][1]

[![arduino][2]][2]

  [1]: https://i.stack.imgur.com/ooxHA.jpg
  [2]: https://i.stack.imgur.com/3Vx7b.jpg

body:
The voltage Vo is not the voltage over the thermistor, it is the voltage over R1! Switch the place of the thermistor and R1.
/Mikael


sender: user

sender: assistant

body:
In addition, note that the Vo is definitely not expressed in mV (millivolts), but in ADC steps , i.e. 1024th of the Vref, that is here 5V (default). And the reference is there that it should be 512 for 25deg.

Also, don't be fooled with the precision of the numbers given. Tolerance is 2% to 5% on the R25 value, which means up to ~25 "steps" (Vo). Assuming that reversing the R1 and TR gives you 450 at 22 deg, it means that your real threshold of 30 deg could be anywhere between 28 and 32 (roughly).

You can get better results by calibrating your TR: at 25deg, measuring its real resistance and using that instead of 10000 in your calculation is a first option. Calibrating for other temperatures is already way more complicated.


message:
find out the pin numbers for the Arduino IDE for a certain board - the esp 32

I followed the tutorial I found here https://techtutorialsx.com/2019/03/29/esp32-arduino-controlling-a-dc-motor/
On the very interesting topic controlling a DC motor with the esp32 and Arduino I have some questions:

The first one: Where in the world did the guy find out the pin numbers for the Arduino IDE for this board? I have no idea how to find them!?

> Taking in consideration that the digital IO pins of the ESP32 can only
> source a maximum current of 40 mA [1], we cannot directly use them to
> control a DC motor.
>
> Instead, we are going to use a ULN2803A integrated circuit to actually
> provide the current to the motor, while the ESP32 will simply control
> if the motor is running or stopped.
>
> The connection diagram to control a DC motor from the ESP32 using an
> ULN2803A can be seen below at figure 1. for controlling a DC motor
> with the ESP32, using a ULN2803A integrated circuit
>
> The controlling of the DC motor with the ESP32 and a ULN2803A IC. In
> short, the ULN2803A will act as a switch, which will turn on / off the
> connection of the motor to GND, depending on the state of the input
> pin labeled as In 1. So, when the GPIO of the ESP32 is at a digital
> high value (VCC), the ULN2803A will connect the motor to GND, and thus
> the motor will be on. When the GPIO is at a digital low value (GND),
> then the motor will be disconnected from GND, and thus it will be off.
> Furthermore, the ULN2803A can be controlled by 3.3 V inputs and
> provide higher voltages, allowing us to control a 5 V DC motor with
> the ESP32.
>
> The code
>
> The code for this tutorial will be very simple, since we basically
> only need to control the status (high or low) of a digital pin of the
> ESP32.
>
> So, we will start by declaring as a global variable the number of the
> pin that will be connected to the DC motor.
>
> In my case I’ll be using GPIO 13. Note that for the Beetle ESP32
> board, which is the one I’m using, this maps to the pin labeled as D7.
>
>     int motorPin = 13;
>
> After that, we need to initialize the pin as output, in the Arduino
> setup function. To do that, we simply need to call the pinMode
> function.
>
> This function receives as first argument the number of the pin and as
> second argument a constant indicating the operating mode. So, we will
> pass the as first argument the value of the pin stored in our
> previously declared global variable and as second argument the
> constant OUTPUT.
>
>
>     void setup() {
>
>       pinMode(motorPin, OUTPUT);
>
>     }
>
> We will write the rest of our code in the Arduino main loop. We will
> first turn on the motor, wait some seconds, turn it off, wait some
> more seconds and then repeat.
>
> So, to turn the motor on, we simply need to set the value of the ESP32
> digital pin to high, which will make the motor run at full speed. We
> can set the digital level of a pin with a call to the digitalWrite
> function.
>
> This function receives as first argument the number of the pin and as
> second argument a constant indicating the digital level to which the
> pin should be set.

body:
An Arduino boards package with configuration for your board has constants for pins which correspond to labels on the PCB. The constants are defined in [pins_arduino.h file][1], which is applied only if you choose the corresponding board in Tools menu. In code you should use this constants as values for your constants, like for example `const uint8_t LED1_PIN = D2;`.

If the boards package doesn't have the board and you use generic settings, the you can study the schematics of the board to see which PCB pin goes to which MCU pin. Usually the logical pin numbers are labeled in schematics additionally to physical pin numbers of the chip.

Note: The linked pins_arduino.h is for FireBeetle ESP32. The Beetle ESP32 is not defined in ESP32 boards package yet.

The schematics is on [the Wiki page][2].

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

  [1]: https://github.com/espressif/arduino-esp32/blob/91e095f5a76ec35f06c86689a87892425395b8db/variants/firebeetle32/pins_arduino.h#L15
  [2]: https://wiki.dfrobot.com/Beetle_ESP32_SKU_DFR0575#target_4
  [3]: https://i.stack.imgur.com/ZVYzE.jpg


message:
expected primary-expression before ',' token

EDIT: have solved the problem. It was missing the quotation marks around each letter. Thanks for your help, st2000!

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

I am very new to Arduino and C++ (coding in general!). Have copied an example code, only modifying the notes to make my own tune. But when I click 'verify', I am getting the error above, and I can't for the life of me, work out what is wrong! I've searched and read several forums and FAQs, but am just coming up blank. This is the code I have, where the error is occuring:

      int melody[]={
        a,C,D,
        a,a,C,D,D,C,
        C,C,D,D,C,
        C,D,E,F,E,D,C};

Any help would be greatly appreciated!

body:
To answer your question we will assume your project is based on [the Melody example][1] at www.arduino.cc.

Likely you wanted to enter the [ASCII][2] values of these letters into an array of [type][3] char (type int would work as well.  But, in some cases, char would be more efficient).  To do this you need to place single quotes around each letter.  Specifically, you need to change your code:

    int melody[]={ a,C,D, a,a,C,D,D,C, C,C,D,D,C, C,D,E,F,E,D,C};

...so that your line of code look like this:

    int melody[]={'a','C','D','a','a','C','D','D','C','C','C','D','D','C','C','D','E','F','E','D','C'};

  [1]: https://www.arduino.cc/en/tutorial/melody
  [2]: https://en.wikipedia.org/wiki/ASCII
  [3]: https://en.wikipedia.org/wiki/C_data_types


message:
How to modify this code to simulate a binary encoder?

I have come across the following SPI slave code at [this][1] site:

    #include <SPI.h>

    char buf [100];
    volatile byte pos;
    volatile bool process_it;

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

      // turn on SPI in slave mode
      SPCR |= bit (SPE);

      // have to send on master in, *slave out*
      pinMode (MISO, OUTPUT);

      // get ready for an interrupt
      pos = 0;   // buffer empty
      process_it = false;

      // now turn on interrupts
      SPI.attachInterrupt();

    }  // end of setup

    // SPI interrupt routine
    ISR (SPI_STC_vect)
    {
    byte c = SPDR;  // grab byte from SPI Data Register

      // add to buffer if room
      if (pos < sizeof buf)
        {
        buf [pos++] = c;

        // example: newline means time to process buffer
        if (c == '\n')
          process_it = true;

        }  // end of room available
    }  // end of interrupt routine SPI_STC_vect

    // main loop - wait for flag set in interrupt routine
    void loop (void)
    {
      if (process_it)
        {
        buf [pos] = 0;
        Serial.println (buf);
        pos = 0;
        process_it = false;
        }  // end of flag set

    }  // end of loop

How to modify the above code so that it responds to input clock signal just like in [this][2] SSI protocol? Uno or Nano can be used.

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

Basically I want to let an arduino  act as an absolute encoder so that it will transmit 13-bit binary data(it can be any random fixed binary data) as shown in the above SSI protocol. So the Arduino will output 13-bit binary data along with with start bit and tm taken into account as shown in the document above without parity.

**The master's code I plan to use:**

    const int CLOCK_PIN = 2;
    const int DATA_PIN = 3;
    const int BIT_COUNT = 16;
    void setup() {
        pinMode(DATA_PIN, INPUT);
        pinMode(CLOCK_PIN, OUTPUT);
        digitalWrite(CLOCK_PIN, HIGH);
        Serial.begin(115200);
      }
    void loop() {
        float reading = readPosition();
        Serial.println(reading,2);
        delay(25);
      }

    //read the current angular position
    float readPosition() {
     unsigned long graysample = shiftIn(DATA_PIN, CLOCK_PIN, BIT_COUNT);
     delayMicroseconds(100); // Clock must be high for 20 microseconds before a new sample can be taken
    unsigned long binarysample = grayToBinary32(graysample);
     return ((binarysample * 360UL) / 65536.0); // ouptut value from 0 to 360 with two point percision
    }
    //read in a byte of data from the digital input of the board.
    unsigned long shiftIn(const int data_pin, const int clock_pin, const int bit_count) {
     unsigned long data = 0;
     for (int i=0; i<bit_count; i++) {
     data <<= 1; // shift all read data left one bit.

     //digitalWrite(clock_pin,LOW);
     PORTD &= ~(1 << 5); // clock pin goes low
     delayMicroseconds(1);
     //digitalWrite(clock_pin,HIGH);
     PORTD |= (1 << 5); // lock pin goes high
     delayMicroseconds(1);
     data |= digitalRead(data_pin); // cat the new read bit to the whole read data.
     }
     return data;
    }
    unsigned int grayToBinary32(unsigned int num)
    {
     num = num ^ (num >> 16);
     num = num ^ (num >> 8);
     num = num ^ (num >> 4);
     num = num ^ (num >> 2);
     num = num ^ (num >> 1);
     return num;
    }

  [1]: http://www.gammon.com.au/spi
  [2]: https://www.posital.com/media/posital_media/documents/AbsoluteEncoders_Context_Technology_SSI_AppNote.pdf
  [3]: https://i.stack.imgur.com/3bQ9c.png

body:
You may try to bit-bang the protocol using [direct port access][]. This
is less convenient, but way faster than `digitalWrite()`. Below is an
example, untested program. I am assuming the pinout is

* data = PB0 = digital 8
* clock = PB1 = digital 9
* pins PB2 – PB5 (10 – 13) are unused

**Edit**: This updated program uses the clock as an input, and the data
as an output. The previous version used both lines as outputs, which was
due to a misunderstanding of mine.

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

int main(void)
{
    uint16_t data = 0x155;

    DDRB  |= _BV(PB0);
    PORTB |= _BV(PB0);
    TCCR1B = _BV(CS10);  // start timer 1 @ F_CPU
    loop_until_bit_is_clear(PINB, PB1);

    for (;;) {
        loop_until_bit_is_set(PINB, PB1);
        PORTB = data & 1;
        data >>= 1;
        TCNT1 = -304;        // 20 us * 16 MHz - 16 cycles
        TIFR1 |= _BV(TOV1);  // clear overflow flag
        while (bit_is_set(PINB, PB1)) {
            if (bit_is_set(TIFR1, TOV1)) {  // timer overflowed
                PORTB = 1;  // data high
                data = 0x155;
                loop_until_bit_is_clear(PINB, PB1);
                break;
            }
        }
    }
}
```

This should be able to operate at frequencies up to about
200 – 250 kHz. There is a delay of about 0.5 µs
between the rising edges of the clock and the data been sent out, with a
jitter of 3 clock cycles.

The data word is sent least significant bit first, contrary to what the
protocol diagram shows. However, if you send arbitrary data, this should
not be an issue.

Note that this is a pure avr-libc program, which does not use the
Arduino core. It uses polling to check the inputs and the timer. The
interrupts are never enabled.

[direct port access]: https://www.arduino.cc/en/Reference/PortManipulation


message:
OLED display hectic behavior - interference with other parts of the code?

Disclaimer: I'm a total novice to Arduino so please forgive me if the question may seem trivial, I'm trying my best to learn :)

I'm working on a small project where I have a fingerprint sensor, a servo and an OLED display. The goal is to be able to register a fingerprint and then use the fingerprint to move the servo, whilst the OLED display gives instruction / messages to the user.

I noticed a few days ago an issue whereby my OLED wouldn't simply stop working if I had some Serial.println in my code. Without understanding the root cause, by trial and error I got to the conclusion that the issue was with that specific function, so I proceeded to remove it and everything went ok.

Then I noticed that the display stopped working also by adding extremely simple pieces of code that should not be related in ANY way to how the OLED works (at least to the best of my very limited knowledge).

The code below works as expected, each and every call to the oledPrint function yields the expected result on the OLED itself.

    #include <EEPROM.h>
    #include <Wire.h>
    #include <Adafruit_GFX.h>
    #include <Adafruit_SSD1306.h>
    #define OLED_RESET -1
    Adafruit_SSD1306 display(OLED_RESET);

    #include <Adafruit_Fingerprint.h>
    #include <SoftwareSerial.h>

    #define ISPRESSED LOW
    #define BASE_MAX 200
    #define MASTER_MAX 200

    SoftwareSerial mySerial(2, 3);

    Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);

    uint8_t id;

    const int buttonRegisterPin = 8; // the number of the pushbutton pin - NOTE: RED BUTTON
    const int buttonRegisterMasterPin = 7; // the number of the pushbutton pin - NOTE: GREEN BUTTON
    const int buttonClearPin = 6; // the number of the pushbutton pin - NOTE: BLACK BUTTON
    const int buttonClearMasterPin = 12; // the number of the pushbutton pin - NOTE: YELLOW BUTTON

    const int baseState = HIGH;
    int ledStatus = HIGH;

    int baseCount;
    int masterCount;

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

      //initialize counters
      initializeCounters();

      //initialize buttons
      initializeButton(buttonRegisterPin);
      initializeButton(buttonRegisterMasterPin);
      initializeButton(buttonClearPin);
      initializeButton(buttonClearMasterPin);

      //initialize the fingerprint sensor
      initializeFingerPrintSensor();

      //initialize the OLED display
      initializeOledDisplay();

    }

    void loop() {

      bool skip = false;
      oledPrint("Welcome to your fingerprint locker");
      //base registration case
      if(digitalRead(buttonRegisterPin) == ISPRESSED && skip == false){

        while(!baseRegistration());
        skip = true;
      }

      //master registration case
      if(digitalRead(buttonRegisterMasterPin) == ISPRESSED && skip == false){

        while(!masterRegistration());
        skip = true;
      }

      //base clear case
      if(digitalRead(buttonClearPin) == ISPRESSED && skip == false){
        clearRegistrations(false);
        //do stuff for base clear
        skip = true;
      }

      //master clear case
      if(digitalRead(buttonClearMasterPin) == ISPRESSED && skip == false){

        //do stuff for master clear
        skip = true;
      }
    }

    /**
     * Initializes a button
     * @Param: buttonPin = number of the pin used by the button
     */
    void initializeButton(int buttonPin){
      pinMode(buttonPin, INPUT_PULLUP);
    }

    /**
     * Initializes the OLED display
     */
    void initializeOledDisplay(){
      Wire.begin();
      if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64
        Serial.println(F("SSD1306 allocation failed"));
        for(;;);
      }
      delay(2000);
      display.clearDisplay();

      display.setTextSize(2);
      display.setTextColor(WHITE);
      display.setCursor(0, 10);
    }

    /**
     * initializes the fingerprint sensor
     */
    void initializeFingerPrintSensor(){
      finger.begin(57600);

      if (finger.verifyPassword()) {
        Serial.println("Found fingerprint sensor!");
      }
      else {
        Serial.println("Did not find fingerprint sensor :(");
        while (1) { delay(1); }
      }
    }

    boolean baseRegistration(){
      boolean check = false;
      int tempBaseCount = baseCount + 1;
    /*
      if(tempBaseCount > BASE_MAX){
        oledPrint("Too many users already registered");
        return true;
      }*/
      oledPrint("Starting registration");
      while(check == false){

        oledPrint("Please put your finger on the reader");

        id = tempBaseCount;
        if (id == 0) {// ID #0 not allowed, try again!
           return;
        }

        if(getFingerprintEnroll(tempBaseCount, false)){
          check = true;
        }
      }
      return check;
    }

    boolean masterRegistration(){
      boolean check = false;
      int tempMasterCount = baseCount + 1;
    /*
      if(tempMasterCount > MASTER_MAX){
        oledPrint("Too many master keys already registered");
        return true;
      }
      */
      oledPrint("Starting master key registration");

      while(check == false){

        oledPrint("Please put your finger on the reader");

        id = tempMasterCount;
        if (id == 0) {// ID #0 not allowed, try again!
           return;
        }

        if(getFingerprintEnroll(tempMasterCount, true)){
          check = true;
        }
      }
      return check;
    }

    boolean clearRegistrations(bool master){
      if(master){
        //to do
      }
      else{
        //increaseBaseCounter(0);
        id = 900;
        int p = finger.deleteModel(id);
        if(p == FINGERPRINT_OK){
         // Serial.println("success");
         // Serial.println(p);
          return true;
        }
       // Serial.println("FAIL");
       // Serial.println(p);
        return false;
      }
    }

    // returns -1 if failed, otherwise returns ID #
    int getFingerprintIDez() {
      uint8_t p = finger.getImage();
      if (p != FINGERPRINT_OK)  return -1;

      p = finger.image2Tz();
      if (p != FINGERPRINT_OK)  return -1;

      p = finger.fingerFastSearch();
      if (p != FINGERPRINT_OK)  return -1;

      // found a match!
      oledPrint2Lines("Match found, ID #", finger.fingerID);
     /* Serial.print("Found ID #");
      Serial.print(finger.fingerID);
      Serial.print(" with confidence of ");
      Serial.println(finger.confidence);*/
      return finger.fingerID;
    }

    uint8_t getFingerprintEnroll(int count, bool master) {
      int p = -1;
      while (p != FINGERPRINT_OK) {
        p = finger.getImage();
        switch (p) {
        case FINGERPRINT_OK:
          //oledPrint("Image taken");
          break;
        case FINGERPRINT_NOFINGER:
          break;
        case FINGERPRINT_PACKETRECIEVEERR:
          oledPrint("Communication error");
          break;
        case FINGERPRINT_IMAGEFAIL:
          oledPrint("Imaging error");
          break;
        default:
          oledPrint("Unknown error");
          break;
        }
      }

      // OK success!

      p = finger.image2Tz(1);
      switch (p) {
        case FINGERPRINT_OK:
          //oledPrint("Image converted");
          break;
        case FINGERPRINT_IMAGEMESS:
          oledPrint("Image too messy");
          return p;
        case FINGERPRINT_PACKETRECIEVEERR:
          oledPrint("Communication error");
          return p;
        case FINGERPRINT_FEATUREFAIL:
          oledPrint("Could not find fingerprint features");
          return p;
        case FINGERPRINT_INVALIDIMAGE:
          oledPrint("Could not find fingerprint features");
          return p;
        default:
          oledPrint("Unknown error");
          return p;
      }

      oledPrint("Remove finger");
      delay(2000);
      p = 0;
      while (p != FINGERPRINT_NOFINGER) {
        p = finger.getImage();
      }
      p = -1;
      oledPrint("Place the same finger again");
      while (p != FINGERPRINT_OK) {
        p = finger.getImage();
        switch (p) {
        case FINGERPRINT_OK:
          //oledPrint("Image taken");
          break;
        case FINGERPRINT_NOFINGER:
          break;
        case FINGERPRINT_PACKETRECIEVEERR:
          oledPrint("Comunication error");
          break;
        case FINGERPRINT_IMAGEFAIL:
          oledPrint("Imaging error");
          break;
        default:
          oledPrint("Unknown error");
          break;
        }
      }

      // OK success!

      p = finger.image2Tz(2);
      switch (p) {
        case FINGERPRINT_OK:
          //oledPrint("Image converted");
          break;
        case FINGERPRINT_IMAGEMESS:
          oledPrint("Image too messy");
          return p;
        case FINGERPRINT_PACKETRECIEVEERR:
          oledPrint("Communication error");
          return p;
        case FINGERPRINT_FEATUREFAIL:
          oledPrint("Could not find fingerprint features");
          return p;
        case FINGERPRINT_INVALIDIMAGE:
          oledPrint("Could not find fingerprint features");
          return p;
        default:
          oledPrint("Unknown error");
          return p;
      }

      // OK converted!

      //oledPrint2Lines("Creating model number:", count);

      p = finger.createModel();
      if (p == FINGERPRINT_OK) {
        //oledPrint("Prints matched!");
      } else if (p == FINGERPRINT_PACKETRECIEVEERR) {
        oledPrint("Communication error");
        return p;
      } else if (p == FINGERPRINT_ENROLLMISMATCH) {
        oledPrint("Fingerprints did not match");
        return p;
      } else {
        oledPrint("Unknown errro");
        return p;
      }

      p = finger.storeModel(id);
      if (p == FINGERPRINT_OK) {
        if(master == false){
          oledPrint2Lines("Registered with id number:", count);
          increaseBaseCounter(count);
        }
        else{
          oledPrint2Lines("Registered master key number:", count - 50);
          increaseMasterCounter(count);
        }
        return 1;
      } else if (p == FINGERPRINT_PACKETRECIEVEERR) {
        oledPrint("Communication error");
        return p;
      } else if (p == FINGERPRINT_BADLOCATION) {
        oledPrint("Could not store in that location");
        return p;
      } else if (p == FINGERPRINT_FLASHERR) {
        oledPrint("Error writing to flash");
        return p;
      } else {
        oledPrint("Unknown error");
        return p;
      }
    }

    uint8_t readnumber(void) {
      uint8_t num = 0;

      while (num == 0) {
        while (! Serial.available());
        num = Serial.parseInt();
      }
      return num;
    }

    void oledPrint(char* text){

      display.clearDisplay();
      display.setTextSize(1);
      display.setTextColor(WHITE);
      display.setCursor(0,0);
      display.println(text);
      display.display();
      delay(2000);
    }

    void oledPrint2Lines(char* text, int val){

      display.clearDisplay();
      display.setTextSize(1);
      display.setTextColor(WHITE);
      display.setCursor(0,0);
      display.print(text);
      display.print(val);
      display.display();
      delay(2000);
    }

    void initializeCounters(){
      //address 0 is BASE
      baseCount = EEPROM.read(0);
      Serial.println(baseCount);
      //address 1 is MASTER
      masterCount = EEPROM.read(1);
      if(masterCount < 50)
        masterCount = 50; //will get to 51 once first registered - 51 = master key #1
      Serial.println(masterCount);
    }

    void increaseBaseCounter(int count){
      baseCount = count;
      EEPROM.write(0, baseCount);
    }

    void increaseMasterCounter(int count){
      masterCount = count;
      EEPROM.write(1, masterCount);
    }

However, if I uncomment the code in the baseRegistration and/or masterRegistration functions (see code snippet below), the display starts to act up: some text is displayed, some other isn't, some other again is displayed partially. I just can't find a sensible explanation anywhere, and being used to work on much higher abstraction levels this is to me completely absurd :D

    boolean baseRegistration(){
      boolean check = false;
      int tempBaseCount = baseCount + 1;
    //PART THAT CAUSES ISSUES - STARRT
      if(tempBaseCount > BASE_MAX){
        oledPrint("Too many users already registered");
        return true;
      }
    //PART THAT CAUSES ISSUES - END
      oledPrint("Starting registration");
      while(check == false){

        oledPrint("Please put your finger on the reader");

        id = tempBaseCount;
        if (id == 0) {// ID #0 not allowed, try again!
           return;
        }

        if(getFingerprintEnroll(tempBaseCount, false)){
          check = true;
        }
      }
      return check;
    }

Even more oddly, if I remove the part above from those two functions and I had one more simple call to the fingerprint sensor in the loop function, the OLED just stops working altogether (and again, absolutely crazy for me :P).
See below the loop function with the addition of the line that breaks the OLED altogether:

    void loop() {

      bool skip = false;
      oledPrint("Welcome to your fingerprint locker");
      //base registration case
      if(digitalRead(buttonRegisterPin) == ISPRESSED && skip == false){

        while(!baseRegistration());
        skip = true;
      }

      //master registration case
      if(digitalRead(buttonRegisterMasterPin) == ISPRESSED && skip == false){

        while(!masterRegistration());
        skip = true;
      }

      //base clear case
      if(digitalRead(buttonClearPin) == ISPRESSED && skip == false){
        clearRegistrations(false);
        //do stuff for base clear
        skip = true;
      }

      //master clear case
      if(digitalRead(buttonClearMasterPin) == ISPRESSED && skip == false){

        //do stuff for master clear
        skip = true;
      }

      int fingerprintID = getFingerprintIDez(); //THIS IS THE LINE
      delay(50);

    }

I just don't know how to proceed, if any of you would be so kind to help a novice out I'd be extremely grateful!
Thanks in advance to anyone who could point me in the right direction!!

For the sake of completeness, I'm using the adafruit libraries for the fingerprint sensor as well as the oled.

body:
Your program seems to fit well inside the Arduino Uno memory. If your output is displaying correctly through the serial monitor, there also seems nothing wrong with your data sent to the display.
Have you tried connecting pull-up resistors to the SDA and SCL lines? Resistors around 3.9k work fine for me when using OLED displays.


message:
Arduino recognize specific sound?

I'm wondering if Arduino is able to not just measure sound and work based on hearing a sound that is "loud enough", but if it is able to identify a specific sound (say the first few seconds of a song). Is this possible, and how would one go about doing so?

If identifying the first few seconds of a song isn't really feasible, is it at least possible to do so with a consistent (but particular) pitch (rather than a general loudness threshold)?

body:
It sounds like you need to do Fourier analysis on the sound. (Breaking up the sound into its component frequencies.) Most Arduinos are based on AVR chips, which do not have hardware support for floating point math. They use software to do floating point, which makes them a poor choice for this sort of thing.

There are FFT libraries for Arduino, but they will be slow and fairly crude. You'd probably be better off using a board like a Raspberry Pi that has an ARM processor for signal processing like this.


body:
No, you cannot recognize a song with an Arduino. It doesn't have enough computing power. I think most solutions, that recognize a song, are based on some kind of machine learning or similar, which is totally out of scope for an Arduino. For this you need a real processor like on a Raspberry Pi or similar Single Board Computers.

Identifying a specific pitch/frequency in a sound signal is possible, but you shouldn't expect great accuracy. As Duncan already wrote in his answer, you need a Fourier transformation for this. It transforms the audio signal (voltage level dependent on time) into the frequency domain (amplitude dependent on frequency). So, if you do a fourier transformation on a short audio signal, you get data about, what frequencies are in that signal with which amplitudes. You can then wait for a peak in a specific frequency range.

Doing a FFT (Fast Fourier Transformation) on an Arduino is slow and not accurate. You also only have very limited memory. So your analysed audio signals will be rather short.

---

There is another way to detect a specific pitch/frequency, which is more a hardware task. You can feed the audio signal into an RC resonator circuit, which is tuned to the frequency, that you are interested in. The circuit will amplify the frequency, that it is tuned to, and dampen all other frequencies (of course it is not really one specific frequency, but a small range of frequencies). The resulting signal can then be checked for threshold values, since it only contains frequencies around the tuning frequency.


body:
As stated in other answers, sound recognition is completely out of the
realm of what an Arduino can do, but recognizing a specific pitch is
possible.

However, contrary to previous answers, I would recommend _against_ using
an FFT. The FFT is the right tool when you need to get _all_ the
frequency components. It is, however, overkill when you want to look at
a single frequency. Given the low processing power at your disposal, I
suggest you try instead an [homodyne detection][] scheme. An Arduino
Uno, or similar board, has enough resources to sample an input at
9.6 kHz, and extract in real time a specific frequency component.
See for example this [homodyne detection program][program].

[homodyne detection]: https://en.wikipedia.org/wiki/Homodyne_detection

[program]: https://gist.github.com/edgar-bonet/0b03735d70366bc05fc6


message:
Cannot write lock byte on Arduino Pro Micro

I have an Arduino Pro Micro, with atmega32u4 chip and a caterine bootloader. However, every time I (successfully) flash some program over the USB port, the `/dev/ttyACM0` device disappears, and I cannot flash it any more over USB.

So I connect it to my stk500v2-compatible ISP programmer (MISO/MOSI/SCK go to pins 14,16 and 15 on the board; VCC,GND,RST to their counterparts). With this setup, I can flash a new Caterina bootloader onto it. The problem with flashing over the board's USB port stays, though.

So I tried to set the lock byte with the ISP programmer, which writes successfully, but then fails at verification:
```
> avrdude -p m32u4 -P /dev/ttyUSB0 -c stk500v2 -b 115200 -U lock:w:0x0F:m
...
avrdude: verification error, first mismatch at byte 0x0000
         0xcf != 0x0f
```

Is my assumption correct that the disappearing bootloader is caused by the wrongly set (un-)lock bits? If yes, why can't I set the lock byte via ISP?

body:
Meanwhile, I managed to solve this problem.
The reason for the verification error is that the two most significant bits of the Lock Byte are read-only on my variant of the Arduino Pro Micro. Which means that, if you (try to) write a value of `0x00 = 0b0000 0000`, it will result in a value of `0b1100 0000 = 0xC0` on the hardware.
The solution, then, was to simply ignore those two bits.
```
> avrdude -p m32u4 -P /dev/ttyUSB0 -c stk500v2 -b 115200 -U lock:w:0xCF:m
```


message:
How can I make std::cout write to Serial?

I'm using an Arduino MKR WiFi 1010, a SAMD ARM Cortex M3 board. I rely on the standard library a lot, using things like `std::vector<>` and `std::string`. I also want to use `std::cout`. I've managed to do this on an UNO R3 using the ArduinoSTL library, but that library neither works nor is necessary on the MKR WiFi 1010, because it has all the standard library stuff built in to the platform.

However, on MKR WiFi 1010, I cannot get `std::cout` to produce any output. I'm guessing its not really hooked up to anything.

I want `std::cout` to write to `Serial` (which is aliased to `SerialUSB` which is of type `Serial_`).

Is there a way of making `std::cout` write to the `Serial` stream?

body:
The ARM gcc libraries offer a simple way to redirect standard outputs. It is enough to implement function `_write(int fd, char *ptr, int len)` and it will replace the default implementation used in library to direct the standard outputs to debugger semihosting. The function must be compiled as  C to match.

    #include <Arduino.h>
    #undef max
    #undef min
    #include <stdio.h>
    #include <iostream>

    using namespace std;

    extern "C" {
    int _write(int fd, char *ptr, int len) {
      (void) fd;
      return Serial.write(ptr, len);
    }
    }

    void setup() {

      Serial.begin(115200);
      while (!Serial);

      Serial.println("START");

      printf("HERE WE ARE\r\n");

      cout << "TEST COUT\r\n";
      cerr << "TEST ERR\r\n";
    }

    void loop() {

    }

the `#undefs` undefine the Arduino macros, which are in conflict with includes used in `<iostream>`


message:
ESP12E motorshield analogWrite issue when powering DC motor

I am relatively new to adruino and this whole space. I am currently trying to power a DC motor using an ESP12E motor shield and an ESP8266 Module

Motor Shield - https://www.amazon.com/gp/product/B078CPZDW1/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1

ESP8266 - https://www.amazon.com/gp/product/B010O1G1ES/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1

DC Motor - https://www.amazon.com/gp/product/B07MTT7B88/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1

Here is my code

    #define DIRA 0
    #define PWMA 5
    #define LED 2

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

      Serial.println("Preparing motor...");
      pinMode(DIRA, OUTPUT);
      pinMode(PWMA, OUTPUT);
      analogWrite(PWMA,0);
      digitalWrite(DIRA,1);
      delay(5000);

      Serial.println("Starting motor...");
      analogWrite(PWMA,5);
      delay(5000);

    }

    void loop() {
    }

Here is how I have wired it up

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

**Note: This setup is similar to what I have but not exactly, I have 4 AA batteries connected and only 2 motors**

I am expecting the motor to start once I upload this code but nothing is happening. If I change the analogWrite to digitalWrite, the motor runs but I want to be able to control the speed, rather than just having it run at one speed.

I have tested using analogWrite by changing the intensity of an LED and it was working, although the output pin was not the same as the one I use for the motor.

Would greatly appreciate any help as I have already gone through pages of google searches without any luck. I have been using this example as a reference, https://hackaday.io/project/8856-incubator-controller/log/29291-node-mcu-motor-shield.

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

body:
This answer is the summary of the comments of the question. The idea of the solution was originally mentioned by @Majenko.

You powered the shield with about 6 Volts. The statement `analogWrite(PWMA, 5);` gives you (5/1024) ~ 0.5% of this 6 Volts at the output pin PWMA. This 0.03V are not enough to drive the motor.

You should use at least 3 Volts to drive the motor (as of the specs).
This can be achieved by using a duty cycle of the PWM signal of about 50%.  `analogWrite(PWMA, 512);` should do the trick.


message:
Waterproofing Arduino

the project i'm working on is a weather station out door and for that i need to to give arduino at least some sort of protection from moisture.

https://www.instructables.com/id/Arduino-Weather-Station-AWS/

putting arduino in a box might work but the humidity where i live is very high it's rain a lot but the cold is not much. looking for ideas to waterproof arduino board please.

also can arduino work everyday of year without problem?

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

body: You can just solder everything you need to the Arduino (I would recommend using an Arduino Mini since it has no communication port) and coat it with Silicon Conformal Coating. It creates a silicon layer on top of the PCB that would not let any moisture through. Or you can just put it in a case and cover it with epoxy, that will be even more protection, but there will be no more access to the board unless you foresee it.


message:
Mosfet controlled motor runs while LOW

I am using a mosfet (IRFZ44N) to control a dc motor, and a separate one to control a led strip. Both are using the same circuit running to different pwm pins on the arduino.

The light strip is working fine (can be turned on an off as expected), but the motor runs at a low level when the pin sends a LOW state, and revs up when it is sent a HIGH state.

They are both receiving power from the VIN pin of the arduino which in turn in plugged into a 12v 6a dc adaptor.

Any ideas what could cause this behavior?

(Apologies if this is a messy schematic, I am a beginner)

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

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

body:
There are some mistakes in the provided schematic:

  - the nmos has to be connected to motor-

  - the freewheeling diode has to be the other way around

  - the resistor doesn't make sense. If it's meant to be a pulldown is has to connect the gate with ground and have a much higher value (~10kOhm). If it's meant to be an inrush limiter it has to be in series with the gate

Actually I don't trust you schematic at all, because I wonder why the motor runs at all without damaging your arduino. Have a look at the low-side transistor configuration [here][1] to see how it is done.

As I mentioned in a comment, this mosfet is a bad choice because it has a too high gate-source threshold voltage Vgs,th (that's the gate voltage at which the transistor **starts** to conduct. The voltage at which it has the specified on-resistance Rds,on is several times higher than this. Choose a device with a Vgs,th below 1V or go for a logic-level mosfet.

  [1]: https://www.baldengineer.com/low-side-vs-high-side-transistor-switch.html


message:
Cannot understand why this code work but this not

I've done a simple aurduino sketch, I have this code, and this don't work:

    #define voltageInput A0
    int qntR;
    float mr;
    float qr;
    float Distanza;
    void setup() {
      // put your setup code here, to run once:
      Serial.begin(9600);
      pinMode(voltageInput,INPUT);
      mr=(130-20)/float(1023-205);
      qr=20-mr*205;
      Serial.print(mr,4);
    }

    void loop() {
      // put your main code here, to run repeatedly:
      qntR=analogRead(voltageInput);
      Distanza=mr*qntR+qr;
      Serial.print("Distanza: ");
      Serial.print(Distanza);
      Serial.print(" cm");
      Serial.println("");
    }

And the I have this code:

    #define voltageInput A0
    int qntR;
    float mr;
    float qr;
    float Distanza;
    void setup() {
      // put your setup code here, to run once:
      Serial.begin(9600);
      pinMode(voltageInput,INPUT);
      mr=(130-20)/(1023-205);
      qr=20-mr*205;
      Serial.print(mr,4);
    }

    void loop() {
      // put your main code here, to run repeatedly:
      qntR=analogRead(voltageInput);
      Distanza=mr*qntR+qr;
      Serial.print("Distanza: ");
      Serial.print(Distanza);
      Serial.print(" cm");
      Serial.println("");
    }

In which I have delete the `float` from `mr=(130-20)/float(1023-205)`;,and if I delete the float the code stop working (`mr` is always equal to 0), why?

body:
Your problem is that you are doing integer maths.

    mr = (130-20)/(1023-205)

reduces to:

    mr = 110/818

Which normally equates to:

    mr = 0.135

But since all those numbers are integers the result is an integer, and is truncated at the decimal point, which means that `mr` is assigned:

    mr = 0

You can force floating point maths by either including a decimal point in one of the numbers, or adding the suffux `f`:

    mr = (130-20)/(1023-205.0)

or

    mr = (130-20)/(1023-205f)

Or casting a portion of the sum to a float as your other code does.


message:
ESP-01 + UNO won't detect gateway

Apparently, this combination of hardware won't accept anything other than WiFiEsp.h together with SoftwareSerial.h (if anyone knows something better/newer than these two, please let me know).
Thing is: I can connect to wifi, send and receive data (to an apache server inside my home network) just fine. After my project was almost done, I decided to connect it to a real server on the internet only to discover that ESP-01 couldn't detect my gateway.

    #include "WiFiEsp.h"
    #include "SoftwareSerial.h"

    int pinWifiRX = 6;
    int pinWifiTX = 7;

    char ssid[64]    = "*****";
    char pass[32]    = "************";

    SoftwareSerial Serial1(pinWifiRX, pinWifiTX);

    int wifi_status;

    void setup() {

      Serial.begin(9600);

      Serial1.begin(9600);
      while(!Serial1) (true);

      WiFi.init(&Serial1);

      if (WiFi.status() == WL_NO_SHIELD) {
        Serial.println(F("No shield"));
        while (true) {}
      }

      IPAddress localIp(192, 168, 1, 60);
      IPAddress subnetMask(255, 255, 255, 0);
      IPAddress gateway(192, 168, 1, 36);

      WiFi.config(localIp);  // <--- this line is accepted and works, but the other 3 gives compilation errors
    //  WiFi.config(localIp, gateway);
    //  WiFi.config(localIp, gateway, subnetMask);
    //  WiFi.config(localIp, gateway, subnetMask, gateway);

      wifi_status = WiFi.begin(ssid, pass);

      if (wifi_status == WL_CONNECTED) {

        IPAddress ip;

        ip = WiFi.localIP();
        Serial.print(F("[WiFiEsp] IP Address: "));
        Serial.println(ip);

        ip = WiFi.subnetMask();
        Serial.print(F("[WiFiEsp] Subnet Mask: "));
        Serial.println(ip);

        ip = WiFi.gatewayIP();
        Serial.print(F("[WiFiEsp] Gateway: "));
        Serial.println(ip);

    //    ip = WiFi.getDNS();  // <--- function doesn't exist
      }

    }

    void loop() {}

Results in:

    [WiFiEsp] Initializing ESP module
    [WiFiEsp] Initilization successful - 2.2.1
    [WiFiEsp] IP address set 192.168.1.60
    [WiFiEsp] Connected to *****
    [WiFiEsp] IP Address: 192.168.1.60
    [WiFiEsp] Subnet Mask: 255.255.255.0
    [WiFiEsp] Gateway: 192.168.1.0

As one can see, Subnet Mask is corret, but it "detects" Geteway **192.168.1.0** when it should be **192.168.1.36**. This way, I can connect to any device in LAN, but cannot access any address on the internet.

I even tried to send some AT commands directly to SoftwareSerial.h, but I don't get any response.

Will I have to start the whole project over from scratch (using another hardware combination), or is there a way to change gateway by hand? Better yet, is there a way to make it detect the gateway's address correctly?

EDIT: could it be related to the firmware I installed to the ESP-01? I followed [this tutorial][1] and got it from [this link][2].

Thanks in advance.

**EDIT: in this example, i used the WiFi.config(localIp) function to set a fix IP. I don't really need that, it was just an attempt to make it get the correct Gateway address. Even if I comment that line, the Gateway is still wrong.**

  [1]: https://blogmasterwalkershop.com.br/embarcados/esp8266/upgrade-de-firmware-do-wifi-esp8266-esp-01-atraves-do-arduino-e-conversor-usb-serial/
  [2]: https://blogmasterwalkershop.com.br/arquivos/firmware/Ai-Thinker_ESP8266_DOUT_8Mbit_v1.5.4.1-a_20171130.bin

body:
Using a static IP address with a gateway is not implemented (as you can see from [the source code](https://github.com/bportaluri/WiFiEsp/blob/master/src/WiFiEsp.h#L86)).

To get out to the internet with that library you can only use DHCP (by omitting the `WiFi.config(localIp)` call).


body:
I've had some progress in my researches towards this problem.

In fact, Arduino gets the correct gateway address from my DHCP server, but displays the wrong one. There must be a bug somewhere in WiFiEsp library somewhere.

To debug this, I made a few changes to the following files:

- WiFiEsp-Master/src/WiFiEsp.h

>     void config(IPAddress local_ip, IPAddress gateway);
>     void config(IPAddress local_ip, IPAddress gateway, IPAddress subnetMask);

- WiFiEsp-Master/src/WiFiEsp.c

>     void WiFiEspClass::config(IPAddress ip, IPAddress gateway)
>     {
>       EspDrv::config(ip, gateway);
>     }
>     void WiFiEspClass::config(IPAddress ip, IPAddress gateway, IPAddress subnetMask)
>     {
>       EspDrv::config(ip, gateway, subnetMask);
>     }

- WiFiEsp-Master/src/utility/EspDrv.h

>     static void config(IPAddress local_ip, IPAddress gateway);
>     static void config(IPAddress local_ip, IPAddress gateway, IPAddress subnetMask);

- WiFiEsp-Master/src/utility/EspDrv.cpp

>     void EspDrv::config(IPAddress ip, IPAddress gateway) {
>       LOGDEBUG(F("> config"));
>
>       // disable station DHCP
>       sendCmd(F("AT+CWDHCP_CUR=1,0"));
>
>       // it seems we need to wait here...
>       delay(500);
>
>       char buf_ip[16];
>       sprintf_P(buf_ip, PSTR("%d.%d.%d.%d"), ip[0], ip[1], ip[2], ip[3]);
>
>       char buf_gateway[16];
>       sprintf_P(buf_gateway, PSTR("%d.%d.%d.%d"), gateway[0], gateway[1], gateway[2], gateway[3]);
>
>       int ret = sendCmd(F("AT+CIPSTA_CUR=\"%s\",\"%s\""), 2000, buf_ip, buf_gateway);
>       delay(500);
>
>       if (ret==TAG_OK)
>       {
>         LOGINFO1(F("IP and gateway addresses set"), buf_ip);
>       }
>     }
>
>     void EspDrv::config(IPAddress ip, IPAddress gateway, IPAddress subnet)
>     {
>
>       LOGDEBUG(F("> config"));
>
>       // disable station DHCP
>       sendCmd(F("AT+CWDHCP_CUR=1,0"));
>
>       // it seems we need to wait here...
>       delay(500);
>
>       char buf_ip[16];
>       sprintf_P(buf_ip, PSTR("%d.%d.%d.%d"), ip[0], ip[1], ip[2], ip[3]);
>
>       char buf_gateway[16];
>       sprintf_P(buf_gateway, PSTR("%d.%d.%d.%d"), gateway[0], gateway[1], gateway[2], gateway[3]);
>
>       char buf_subnet[16];
>       sprintf_P(buf_subnet, PSTR("%d.%d.%d.%d"), subnet[0], subnet[1], subnet[2], subnet[3]);
>
>       int ret = sendCmd(F("AT+CIPSTA_CUR=\"%s\",\"%s\",\"%s\""), 4000, buf_ip, buf_gateway, buf_subnet);
>       delay(500);
>
>       if (ret==TAG_OK)
>       {
>         LOGINFO1(F("IP, gateway and subnet mask addresses set"), buf_ip);
>       }
>     }

These few changes should be enough to implement fix IP address and specify manual address for gateway and subnet mask (please feel free to correct me if I'm wrong).

But after doing this, I realized the gateway continued to be "192.168.1.**0**". Then I added this piece o code to the function EspDrv::readUntil, inside EspDrv.cpp:"

   ringBuf.push(c); // this line was already there
   Serial.print(c);

This way, I could see exactly all responses for the AT commands sent by WiFiEsp library. When asked, the results were:

    +CIPSTA:ip:"192.168.1.60"
    +CIPSTA:gateway:"192.168.1.36"
    +CIPSTA:netmask:"255.255.255.0"

Then I realized the problem wasn't the gateway, but the DNS. If the library sends command "AT+CIPSTART=3,"TCP","www.google.com",80", the result was:

    Not connected

    busy p...

And, if increased the timeout value to 15000 instead of 5000, the result was:

    DNS ERROR

Now my problem is partially solved. I can connect to an external server if I use an IP address, but I can't set a domain name because it won't be resolved by the DNS.

Apparently the firmware version of my ESP-01 won't accept "AT+CDNSCFG=?" required to set/retrive DNS address. I tried to set 8.8.8.8 as the DNS, but the result was "NOT OK".

I will stick to this "solution" for now, but would be glad to hear any comment about what I described here and a more final solution.

Thanks.


message:
Yet another basic and silly question about C++ strings

I made a sketch like this:

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

      char str1[64] = "test with spaces";
      char str2[32] = "test with spaces";

      Serial.println(str1);
      Serial.println(str2);

      if (str1 == str2) Serial.println("Equals");
      else Serial.println("Different");

      if (strcmp(str1, str2)) Serial.println("Equals");
      else Serial.println("Different");

    //  if (strcoll(str1, str2)) Serial.println("Equals"); // <-- this won't compile for Arduino UNO { why ??? }
    //  else Serial.println("Different");

      if (memcmp(str1, str2, sizeof(str2))) Serial.println("Equals");
      else Serial.println("Different");

      if (areEqual(str1, str2)) Serial.println("Equals");
      else Serial.println("Different");

      strcpy(str1, "test+with+spaces");
      strcpy(str2, "test with spaces");

      Serial.println();
      Serial.println(str1);
      Serial.println(str2);

      if (str1 == str2) Serial.println("Equals");
      else Serial.println("Different");

      if (strcmp(str1, str2)) Serial.println("Equals");
      else Serial.println("Different");

      if (memcmp(str1, str2, sizeof(str2))) Serial.println("Equals");
      else Serial.println("Different");

      if (areEqual(str1, str2)) Serial.println("Equals");
      else Serial.println("Different");

      strcpy(str1, "test+with++++++++++++++++++++++++++++++++++++spaces");
      strcpy(str2, "test with spaces");

      Serial.println();
      Serial.println(str1);
      Serial.println(str2);

      if (str1 == str2) Serial.println("Equals");
      else Serial.println("Different");

      if (strcmp(str1, str2)) Serial.println("Equals");
      else Serial.println("Different");

      if (memcmp(str1, str2, sizeof(str2))) Serial.println("Equals");
      else Serial.println("Different");

      if (areEqual(str1, str2)) Serial.println("Equals");
      else Serial.println("Different");

    }

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

    }

    bool areEqual(char* string1, char* string2) {
      return ((strlen(string1) == strlen(string2)) && (strstr(string1, string2)));
    }

Which produces this:

    test with spaces
    test with spaces
    Different
    Different
    Different
    Equals

    test+with+spaces
    test with spaces
    Different
    Equals
    Equals
    Different

    test+with++++++++++++++++++++++++++++++++++++spaces
    test with spaces
    Different
    Equals
    Equals
    Different

The first comparisson is silly (==), I know. It compares the address of the pointer, not of the string itself. I just put it there to show how hard it is for a programmer who comes from another language to understand such a thing.

The second comparison (strcmp), as the reference says "Compares the C string str1 to the C string str2.", NO, it doesn't. They are exactly the same, except for their pre-specified size. But the strings are equal to my eyes.

The third comparison (strcoll) uses locale to compare the two strings, but how come it says different when they are equal?

The fourth comparison (memcmp), given two pointers to the exact same sequence of characters, why does it say "different"?

The mind blowing part is the comparison "works" when you add as many "+" as you wish to only one of the strings. Isn't a "+" sign also a character?

It's obvious I must be missing something really basic about c++ style strings, but I dare to ask: what is it?

Thanks.

body:
The return value of `strcmp` does not have boolean semantics, as you seem to incorrectly assume.

`strcmp` is a *tri-state comparator*, which returns negative, zero or positive value. For equal strings it returns *zero*, which means that an equality comparison with `strcmp` should normally look as follows

    if (strcmp(str1, str2) == 0) Serial.println("Equals");
    else Serial.println("Different");

while your original code actually does the opposite.

There's a moderately widespread ugly habit of writing such comparisons as

    if (!strcmp(str1, str2)) Serial.println("Equals");
    else Serial.println("Different");

(note the application of `!` operator). It works properly, but it has poor readability. Avoid it. For tri-state comparators is a much better idea to spell out the comparison with `0` explicitly.

And you made exactly the same mistake with `memcmp`. `memcmp` is also a tri-state comparator, so it should be

    if (memcmp(str1, str2, sizeof str2) == 0) Serial.println("Equals");
    else Serial.println("Different");

The same applies to `strcoll`.

P.S. And in fact such zero-terminated strings represented by `char[]` arrays are called *C-style strings*, not C++-style strings.


message:
Arduino vs 12bit ADC

12bit ADC will give us about 1.2mV per step:

    5 / 4096 = 0.00122

But if we give Arduino a 1.2V voltage reference we get 1.1mV per step:

    1.2 / 1024 = 0.00117

Does that means Arduino can be more accurate than a 12 bit ADC?

body:
In a word, no.

The Arduino uses a rather crude 10-bit ADC. If you feed it a small voltage reference, you can divide that small voltage into 1024 steps. (as you say, about 1.1mV/step)

If you feed the same small 1.2V reference voltage into a 12-bit ADC, you'll get 4 times as many steps for the same range. (about 293μV/step)

And, as mentioned before, the ADC's in Arduinos are not very good. They're slow, and not very accurate.

(To be technical, precision is how exactly you DESCRIBE your answer. A decimal reading using more decimal places is more precise than a reading with less decimal places. Accuracy is how close the measured value is to the actual value. If you're sloppy with your measurements but use lots of decimal places to write it down, and the answer is very far off, you have a precise but inaccurate answer. (e.g you measure something as 1.0000001 millimeters, but it's really 2.5 mm.

A 12-bit ADC is more precise than a 10-bit ADC, but it may or may not be more accurate. Given the crude nature of the ADCs in Arduinos, a dedicated 12-bit ADC is likely to be more accurate than built-in one.)


message:
Can you use an Arduino UNO as an EEPROM programmer

Hi I have an Arduino UNO and a AT28c64B and a single shift register, is it possible to make an EEPROM programmer with it? I’m not too good with the Arduino to do a lot of trial and error... I would just like to know if it’s possible or not, not how to...

body:
You need 24 GPIO pins to control that EEPROM chip. The Arduino has 19, and a typical shift register has 8 outputs. It takes 3 or 4 (depending on the shift register) to drive the shift register.

That's `19 + 8 - 4 = 23` for a shift register that needs 4 pins, or `19 + 8 - 3 = 24` for one that needs 3 pins.

However I would assume that you want to communicate with your computer as well, and that means that pins 0 and 1 of the Arduino are out of bounds, since they are used for the PC communication.

That means, at best, you have 22 pins when you need 24.

So, no, with that combination you can't, due to a lack of pins.

However an IO expander, such as the MCP23017, would give you enough pins and need fewer pins to drive. They also work in both directions, so can be used for pins that want to be read as well as written (data pins).

Alternatively an SPI or I2C connected EEPROM would be the better option, since those are designed to be driven by a small microcontroller like an Arduino uses.


message:
Deep Sleep Reset with Shock Sensor

I am trying to design a circuit that wakes my ESP8266 (Wemos D1 Mini) from deep sleep using a shock sensor. I can achieve this using the reset pin but I need
it to ignore further requests to reset to give it time to run the code in my sketch. Provided there is still motion it will just continue to reset meaning the code only gets run after the 'shock' stops. I have tried all kinds of things with capacitors and transistors to delay subsequent resets but with very limited success. Can someone please point me in the right direction or suggest an easier way to do this? Many thanks in advance.

body:
This is actually somewhat more tricky than you would at first thing.

First off, the "shock sensor" is merely a spring inside a tube.  This will create *lots* of triggers while it's being "shocked", which really is messy.

Secondly, you only want those shocks to make it through to the ESP when you are in deep sleep.

Thirdly, you don't want whatever you connect to adversely affect, or be affected by, other circuitry that is connected to the reset pin.

So you first really need to "condition" the output of your sensor so that it gives a clean pulse that can reset the ESP8266. Then you need to "gate" that signal so it can only get through while the board is asleep.

For conditioning the shock sensor signal I would be inclined to use a 55 timer in monostable mode.  You can find a good circuit and description [here](https://www.element14.com/community/community/project14/diytestequipment/blog/2017/08/12/vintage-555-a-general-purpose-button-debouncer) which looks like this:

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

Now to gate that signal (which is active high) you need a signal to gate it with.  Since all the GPIOs of the ESP8266 are "dead" while it's asleep you need it to be in a "default on" state and have the ESP8266 drive an "I am awake" signal to disable the output.  So you'd have a pullup resistor on a GPIO to make it default HIGH (to match the trigger pulse for simplicity) and then use `pinMode()` and `digitalWrite()` as the first things after waking up (and at the start of `setup()`) to indicate it's awake by driving it LOW.  Then you combine those two signals:

* If the trigger is HIGH and
* If the gate signal is HIGH
* Then pull reset LOW
* Otherwise don't affect reset

So you make a truth table:

    Trig | Gate | Res
    -----------------
      L  |  L   |  HiZ
      L  |  H   |  HiZ
      H  |  L   |  HiZ
      H  |  H   |  L

The tricky one here is the "HiZ" - This means "High Impedance" - or in effect "Don't affect the reset pin at all".

Apart from that the truth table is that for a NAND gate - if both inputs are HIGH then the output is LOW - otherwise the output is HIGH.  Except we want HiZ not HIGH.

To make that HiZ there's two things you can do:

1. Use a NAND gate that has an "Open Collector" (or "Open Drain") output, or
2. Use an AND gate and create your own "Open Collector" that inverts the output by adding a transistor.

For option 1 you can use the 74AC01 which is a "Quad 2 input NAND gate Open Collector".  For option 2 you can use the 74AC08 and any NPN transistor (or N-channel MOSFET with a suitable threshold).

<!-- 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/fHFxE.png)

<!-- End schematic -->

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


message:
How could i synchronize 2 signals

unsigned long Htime;
    unsigned long Ltime;
    unsigned long Ttime;
    unsigned long f;
    int N;

    void setup() {
      // put your setup code here, to run once:
    cli();
      TCNT2 = 0;
      TCCR2A = 0;
      TCCR2B = 0;
      Serial.begin(9600);
      pinMode(5,INPUT);
      pinMode(3,OUTPUT);
      pinMode(11,OUTPUT);
      TCCR2A = (1 << COM0A1) | (1 << COM0B1) | (1 << WGM21) | (1 << WGM20);
      TCCR2B = (1 << WGM22) | (1 << CS22) | (1 << CS21) | (1 << CS20);
      TIMSK2 = (1 << OCIE2A);
    }

    void loop() {
      // put your main code here, to run repeatedly:
      Htime = pulseIn(5, HIGH);
      Ltime = pulseIn(5, LOW);
      Ttime = Htime + Ltime;
      f = 1000000 / Ttime;
      Serial.println(f);
      N = (16000000 / 1024 / f ) - 1;
      OCR2A = N;
      OCR2B = N/2;

    }

Hi this is what i have written. and i need output a square wave with timer, its frequency is measured from input signal in pin 5. After connecting the oscilloscope, i see the problem, there is phase shift between 2 signals. [![enter image description here][1]][1]How could i synchronize this 2 signals?(rising edge to rising edge, falling edge to falling edge) Thank u so much for your help!

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

body:
Given that only the falling edge of your input is sharp and well
defined, I suggest the following approach:

* Use the input-capture feature of Timer 1 to get a timestamp on the
  falling edge and trigger an interrupt.

* In the ISR, start by toggling the output in order to set it low. Then
  compute the period of the signal (timestamp of this falling edge minus
  timestamp of the previous one) and program a compare register to
  trigger a compare match event after half a period.

* The compare match would automatically toggle the output pin again, by
  using the “toggle on compare match” timer output mode.

The following program attempts to implement this approach. Note that it
is completely untested. Input is on pin 8 (i.e. PB0 and ICP1). Output is
on pin 9 (i.e. PB1 and OC1A). The timer is set to run at `F_CPU/8` in
order to accommodate frequencies as low as about 30.1 Hz. A
different prescaler should be used if lower frequencies are needed. The
program does not rely on the Arduino core, and thus defines its own
`main()` instead of `setup()` and `loop()`.

```c++
ISR(TIMER1_CAPT_vect)
{
    TCCR1C = _BV(FOC1A);  // force output compare -> toggle output
    static uint16_t last_capture;
    uint16_t capture = ICR1;
    uint16_t period = capture - last_capture;
    last_capture = capture;
    OCR1A = capture + period/2;  // compare match after 1/2 period

    // If output is high, toggle again.
    if (bit_is_set(PINB, PB0))
        TCCR1C = _BV(FOC1A);
}

int main()
{
    // Set OC1A = PB1 = digital 9 as output.
    DDRB = _BV(PB1);

    // Configure Timer 1.
    TCCR1A = _BV(COM1A0);  // toggle OC1A on compare match
    TCCR1B = _BV(CS11);    // clock at F_CPU/8
    TCCR1C = _BV(FOC1A);   // force output compare -> toggle output
    TIFR1  = _BV(ICF1);    // clear capture flag
    TIMSK1 = _BV(ICIE1);   // enable capture interrupt
    sei();

    for (;;) {}
}
```


message:
Error reading file

What should be done to solve it?
I have edited the `board.txt` file and none of my codes are getting verified
it shows this error:

> "Error reading file (C:\Program Files
> (x86)\Arduino\hardware\arduino\avr\boards.txt:0): Invalid line format,
> should be 'key=value' "

body:
You can either reinstall the Arduino IDE (it will replace the file), or copy the original code back in the file (if you have a copy somewhere).

See the link: https://code.google.com/archive/p/arduino/wikis/Platforms.wiki for more background in case you are interested.

(note: I cannot copy the content of the file in the answer since it is more than 30000 characters.)


message:
Spikes in CO2 and TVOC measurements with CJMCU-811 sensor

Firstly, I'm not sure if this is the right SE to ask this question. Please feel free to direct me somewhere else if needed.

I am observing large spikes in CO2 and TVOC measurements using the CJMCU-811 sensor. When plotted it looks like this:

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

Nothing particular is happening around the sensor at those moments of spikes, I'm not breathing on the sensor etc.

I use Arduino Uno with the following code:

```cpp
/******************************************************************************
  Read CO2 and TVOCs from CJMCU-811 sensor

  Arduino connection:
  3.3V to 3.3V
  ACC to 3.3V
  GND to GND
  WAK to GND
  SDA to A4
  SCL to A5

******************************************************************************/
#include <Wire.h>

#include "SparkFunCCS811.h"
#define CCS811_ADDR 0x5B

CCS811 mySensor(CCS811_ADDR);

void setup()
{
  Serial.begin(9600);
  Serial.println("CCS811 Basic Example");

  Wire.begin();

  CCS811Core::status returnCode = mySensor.begin();
  if (returnCode != CCS811Core::SENSOR_SUCCESS)
  {
    Serial.println(".begin() returned with an error.");
    while (1);
  }
}

void loop()
{

  if (mySensor.dataAvailable())
  {

    mySensor.readAlgorithmResults();

    delay(1);

    Serial.print("CO2 ");
    Serial.print(mySensor.getCO2());

    Serial.print(", tVOC ");
    Serial.print(mySensor.getTVOC());

    Serial.println();
  }

  delay(2000);
}
```

Of course I can filter and not worry about them, but I'm nevertheless curious what is causing it. Any suggestions what could be the reason for that?

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

body:
I have two of those sensors in a long term setup and I know those spikes very well. I once put lots of effort in debugging and I personally gave up on the ccs811 and use a different sensor now.

Back then I have already tried what Jaromanda suggests in his comment.
Both of my sensos showed the same behaviour while the spikes on both sensors did **not correlate** in any form.
Also, if I remember it right, those erronous readings appeared to be at dedicated values.
I tried several pullups, which also didn't make any difference and on the oscilloscope everything looked fine.
Printing the output of the I2C related functions revealed that communication was always stable. If it was I2C related I would expect those erronous readings to be completely random anyway (which they aren't from my experience).

My final (vague) theory was that maybe there exist race conditions between the computation and the I2C interface or maybe the adc and the approximation algorithm (that's all "inside" of the sensor). I once produced such a bug myself which resulted in a similar behaviour.

At least I'm pretty sure that there is nothing you can do in your sketch to fix this problem, because for the mentioned reasons it is very unlikely related to communication problems. You might want to work-around it or look for an updated firmware.
Or (my prefered solution) choose a sensor which does a **true CO2 measurement** (the ccs811 only returns a pseudo, calculated CO2-equivalent approximation).
Those higher-class sensors use NDIR technique and are only a bit more expensive (still under 50$) but you'll probably have much more reliable readings, less problems and a wider measurement range (up to 0-40000ppm vs 400-8192ppm).

Ps: did you follow the guidelines concerning the "burn-in time"? Because honestly, that was a mistake I did: I simply plugged it in of curiosity to test communication and read about this step afterwards. But I don't believe it has something to do with this problem, because there are physical reasons why one should do so, but those artifacts seem to be of digital nature.


body:
I saw similar behavior from 3 CJMCU-811 sensors that I bought (in one order, so probably the same manufacturing lot) in mid 2019. Two gave readings with steady, spikey, but uncorrelated upward growth. The third periodically spiked into the 2000-3000 ppm zone and then popped back to ~450 ppm (in an empty room with decent airflow). A logic analyzer on the I2C lines didn't show issues (or I missed them).

I went as far as adding a line to reset the sensors every few minutes. Replacing the sensors with what I assume was a different manufacturing lot resolved the issue.

I'm using the AdaFruit ccs811 library on ESP8266s (Wemos D1 minis).

**Months later:** The replacements have gone haywire, occasionally giving readings in the 3000ppm range until reset, at which point they're back to the 400-600ppm range for a while until drifting higher. I recommend avoiding the ccs811.


body:
There is a [CCS811 library](https://github.com/maarten-pennings/CCS811) which supports querying the internal firmware version of the sensor, and flashing a new firmware (latest is 2.0.1). Older firmware versions used to have burn-in compensation which apparently caused more harm than good (instead, new firmware requires sensors to be burned-in during 48 hours), and also relied on an external sensor for temperature compensation, which is simply missing on most cheap breakout boards. Ironically many cheap boards come with CCS811 flashed with an older firmware, which periodically samples the voltage on a floating pin and uses that value to correct CO2/TVOC calculations.

Unless your board features a thermistor, consider upgrading the sensor firmware to 2.0.1. Even or boards with a thermistor (e.g. original Adafruit), new firmware might give better results.


message:
Program for counting days

I need a program to count days, from day 1 to day 21 for my project.

I'm making an artificial incubator and I need to show the days on an LCD.

body:
You can do that easily using Real Time Clock IC. ds1307/ds3231 ic will do the job. Adafruit has Arduino library for that. easy to interface.

I don't supprt using millis() function. you will lose your time if the system power downs or mcu resets. Using RTC chip is safe option as it has backup battery for time keeping.


message:
double to char* conversion. Weird results from dtostrf

**Here’s the code:**
```
void setup()
{
 Serial.begin(9600);
 delay(300);

 double lat = 1111.11;
 double lon = 4444.44;

 const byte len{10};

 char sLat[len];
 char sLon[len];

 dtostrf(lat, len, 2, sLat);
 Serial.println(sLat);

 Serial.println("---");

 dtostrf(lon, len, 2, sLon);
 Serial.println(sLon);
 Serial.println(sLat); // <-- prints nothing!

 Serial.println("---");

 dtostrf(lat, len, 2, sLat);
 Serial.println(sLat);
 Serial.println(sLon); // <-- prints nothing!
}

void loop()
{
}
```

**Here’s the output:**
```
   1111.11
---
   4444.44

---
   1111.11
   4444.44   1111.11
```

As you see. Every next call for `dtostrf` ruins the previous results, in a weird way.

What’s the problem?

body:
If `len` is the text array size, you need space there for the terminating '\0'.
So the second paramater to `dtostrf` has to be smaller than `len`.


message:
Floating power supply for Arduino - Is it still connected to the USB ground?

I am trying to power my Arduino Mega 2560 from a benchtop power supply. I plan to essentially feed in a 9V supply directly on the Vin pin and connect the GND pin to the floating ground pin on the power supply. I noticed on the schematic that the UGND is connected to GND through this jumper. On the Arduino that I have these two pins are tied together. Does this mean that even with the external power supply the Arduino will be connected to the UGND, and in effect the protective earth?

What is the best way to float the Arduino? Would it be ok to remove the jumper connection between UGND and GND? Or should I try something like a linear USB isolator like [this][1]?

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

  [1]: https://www.analog.com/media/en/dsp-documentation/evaluation-kit-manuals/DC2092A_LTP2884FA.PDF
  [2]: https://i.stack.imgur.com/fpRxy.png

body:
> Does this mean that even with the external power supply the Arduino will be connected to the UGND, and in effect the protective earth?

Yes.

> Would it be ok to remove the jumper connection between UGND and GND?

No. I don't know quite why they provided that jumper. I can see no scenario in the datasheet where it suggests the two can be separate.

> Or should I try something like a linear USB isolator like this?

If you want it to float then you need galvanic isolation on *all* USB pins. The device you link to will do that for you. There are others as well.

Personally in these situations I prefer to use a wireless communication system so there is no worry about grounds and isolation - it's naturally isolated.


message:
real-time reading of a quadrature encoder at full resolution with only one interrupt on ATmega328

I want to read a [quadrature rotary encoders][1] at full resolution with only one interrupt on Arduino Nano (ATmega328). So I [found out][2] that we can use [XOR][3] to reach a full resolution:

Where pin `3` is interruptable but `4` and `5` are not.

Our requirements are:

 1. Full resolution: for example, the solution offered in [this answer][4] works at a half-resolution only, not detecting all the edges.
 2. Real-time: being as fast as possible up to the level that this hardware allows and safe in terms of not missing any of the signal edges.
 3. using only one interrupt. We need the other one for other purposes.

So far, I have developed two different codes, one aiming for safety and the other for performance:

#Preamble:

~~~c++
#include "digitalWriteFast.h"

#define pinT 3 // trigger pin comming from XOR

#define pinA 4 // channel A
#define pinB 5 // channel B

volatile long counter = 0;
long counter_ = counter;
~~~

where the `digitalWriteFast` library can be downloaded from [here][5].

#Performant:

~~~c++
volatile short int increment = 0;
volatile bool tmpA;
volatile bool tmpB;
volatile bool lastA;

ISR(trigger) {
  tmpA = digitalReadFast(pinA);
  tmpB = digitalReadFast(pinB);
  counter += (1 - 2 * tmpA) * (1 - 2 * tmpB) * (1 - 2 * (lastA != tmpA));
  lastA = tmpA;
}

void setup() {
  pinMode(pinA, INPUT_PULLUP);
  pinMode(pinB, INPUT_PULLUP);
  pinMode(pinT, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(pinT), trigger, CHANGE);
  lastA = digitalReadFast(pinA);
  Serial.begin(9600);
}

void loop() {
  if (counter != counter_) {
    Serial.println(counter);
    counter_ = counter;
  }
}
~~~

#Safe:

~~~c++
volatile unsigned long error = 0;
unsigned long error_ = 0;

volatile bool inputA;
volatile bool inputB;

volatile short state; // 100 110 101 111
volatile short state_;

void detectState() {
  inputA = digitalReadFast(pinA);
  inputB = digitalReadFast(pinB);

  if (inputA) {
    if (inputB) {
      state = 111;
    } else {
      state = 110;
    }
  } else {
    if (inputB) {
      state = 101;
    } else {
      state = 100;
    }
  }
}

ISR(trigger) {

  detectState();

  if (state_ != state) {
    switch (state_) {
      case 100:
        if (state == 110) {
          counter++;
        } else if (state == 101) {
          counter--;
        } else {
          error++;
        }
        break;
      case 110:
        if (state == 100) {
          counter--;
        } else if (state == 111) {
          counter++;
        } else {
          error++;
        }
        break;
      case 101:
        if (state == 100) {
          counter++;
        } else if (state == 111) {
          counter--;
        } else {
          error++;
        }
        break;
      case 111:
        if (state == 110) {
          counter--;
        } else if (state == 101) {
          counter++;
        } else {
          error++;
        }
        break;
      default:
        error++;
        break;
    }

    state_ = state;
  } else {
    error++;
  }
}

void setup() {
  pinMode(pinT, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(pinT), trigger, CHANGE);

  pinMode(pinA, INPUT_PULLUP);
  pinMode(pinB, INPUT_PULLUP);

  detectState();
  state_ = state;

  Serial.begin(9600);
}

void loop() {
  if (counter != counter_) {
    Serial.print("counter: ");
    Serial.println(counter);
    counter_ = counter;
  }

  if (error != error_) {
    Serial.print(error);
    Serial.println(" errors");
    error_ = error;
  }
}
~~~

Now my questions are:

 1. Is there any way to improve the speed/safety of the performant/safe code? Any way to improve this code is appreciated.
 2. Is it possible to have maximum speed and safety together or some trade-off in between?
 3. What is the maximum frequency we can get out of this configuration?

Thanks for your help in advance.

  [1]: https://electronics.stackexchange.com/questions/459715/how-to-check-if-my-quadrature-encoder-is-broken-or-not
  [2]: https://electronics.stackexchange.com/a/459185/124243
  [3]: https://electronics.stackexchange.com/q/459852/124243
  [4]: https://arduino.stackexchange.com/a/12064/35432
  [5]: https://github.com/NicksonYap/digitalWriteFast

body:
This is just a partial, rushed answer.

You should be able to get a significant speed-up if you define your own
ISR for handling the interrupt, as in:

```c++
ISR(INT1_vect) { ... }
```

The Arduino way of using interrupts is instead

```c++
void trigger() { ...}

void setup() {
    attachInterrupt(int_number, trigger, CHANGE);
    ...
}
```

but this is slow, as it involves the ISR provided by the Arduino core,
which has to locate and call your interrupt handler. The way you wrote
the handler is wrong: either you define a regular function, without the
`ISR` macro, and go the Arduino way, or you go the plain AVR path and
define the ISR yourself, which should be named `INTERRUPT_NAME_vect`, in
which case you don't use `attachInterrupt()`. The way you did it is
probably the slowest you can get, as the compiler will needlessly add an
ISR-type prologue and epilogue to your handler.

As for the maximum frequency, that's hard to assess without testing, but
you may get some idea by reading [this answer on interrupt
latency](https://arduino.stackexchange.com/a/8926/7508).

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

**Edit**: As I stated in my first comment to the question, a pin change
interrupt can be used instead of an external logic gate. Here is how to
do it.

First, one should look at the Arduino Uno pinout and see that:

* digital 4 = PD4 = PCINT20
* digital 5 = PD5 = PCINT21

Both pins are tied to the pin change interrupt request 2 (PCINT2\_vect).
This interrupt can be configured in `setup()` as follows:

```c++
PCMSK2 = _BV(PCINT20)   // enable interrupt on pin PCINT20 = PD4
       | _BV(PCINT21);  // enable interrupt on pin PCINT21 = PD5
PCIFR  = _BV(PCIF2);    // clear interrupt flag
PCICR  = _BV(PCIE2);    // enable pin change interrupt request 2
```

Now, the interrupt will fire on every change of the logic levels of
inputs 4 and 5.

Then, in the ISR, the whole port D can be read in a single cycle by
just evaluating the corresponding pin input register, i.e. `PIND`. With
some shifting and masking, one can get a phase between 0 and 3
(the count is in Gray code: 0, 1, 3, 2, 0...). From the previous and the
current phase, one can compute the change that needs to be applied to
the counter:

```c++
// Handle pin change interrupt request 2.
ISR(PCINT2_vect) {
    static uint8_t previous_phase;
    uint8_t phase = (PIND >> 4) & 0x03;  // read input pins
    counter += encoder_delta(previous_phase, phase);
    previous_phase = phase;
}
```

The implementation of `encoder_delta()` is left as an exercise to the
reader. ;-)


message:
Specific ports on Teensy 3.6 not reading correct bit resolution using ADC library?

I have a basic circuit, where I'm reading analog values from 14 infrared receivers.

I set the bit resolution to 16 but specific ports are returning 10 bit values (from 0 - 1024) instead of 16 bit values (from 0 - 65536).

I can confirm this is not a problem with my circuitry because when I've tested reading each individual sensor with a port that "works" and the correct range is returned every time.

____
Here is my code:

    #include <ADC.h>

    ADC *adc = new ADC();
    const int* RECIEVERS = (int[14])
    {
        A15, A16, A17, A19, A20, A21, A22, A1, A2, A3, A6, A7, A8, A9
    };

    void setup() {
        Serial.begin(4608000);
        adc->setAveraging(16); // set number of averages
        adc->setResolution(16); // set bits of resolution
        adc->setConversionSpeed(ADC_CONVERSION_SPEED::HIGH_SPEED_16BITS);
        adc->setSamplingSpeed(ADC_SAMPLING_SPEED::VERY_HIGH_SPEED);
        for (int i = 0; i < 14; i++) pinMode(RECIEVERS[i], INPUT);
    }

    void loop() {
        for (int i = 0; i < 14; i++) {
            Serial.print(adc->analogRead(RECIEVERS[i]));
            Serial.print(" | ");
            delay(1);
        }
        Serial.println("");
    }

____

**Is there a problem with my code or is my Teensy damaged?**

body:
The Kinesis 66 (the chip on the Teensy 3.6) has *two* ADC modules. Each one talks to different pins.

By default the configuration functions in that library configure ADC0, so unless you tell it otherwise, you will only be configuring half the ADC pins.

You should call each of the configuration functions twice, once for ADC0 and once for ADC1:

    adc->setAveraging(16, 0); // set number of averages
    adc->setResolution(16, 0); // set bits of resolution
    adc->setConversionSpeed(ADC_CONVERSION_SPEED::HIGH_SPEED_16BITS, 0);
    adc->setSamplingSpeed(ADC_SAMPLING_SPEED::VERY_HIGH_SPEED, 0);

    adc->setAveraging(16, 1); // set number of averages
    adc->setResolution(16, 1); // set bits of resolution
    adc->setConversionSpeed(ADC_CONVERSION_SPEED::HIGH_SPEED_16BITS, 1);
    adc->setSamplingSpeed(ADC_SAMPLING_SPEED::VERY_HIGH_SPEED, 1);


message:
Program Arduino then Remove Atmega?

Can I program an Arduino and then remove the micro-controller from it and use it on a breadboard without reprogramming the micro-controller again?

My steps would be:

 1. create my Arduino code.
 2. I upload the compiled code to the board.
 3. I remove the Ic and use it alone without the whole board.

Will the code be preserved on the microcontroller?

body:
Yes. The programming of the arduino microcontroller sets the values inside the [FLASH][1]. This is [non volatile memory][2] and as such won't be erased by taking out the IC.

Please note that this is assuming a [DIP package][3] IC as these can be removed without force, heat and stress. A [TQFP][4], and [SMT packages][5] like that, IC might get damaged by moving them in such a way. This doesn't mean it has to be erased, it is still non volatile storage, but the moving process is much more dangerous for the chip.

I would recommend connecting the whole arduino or if you really need the whole chip: designing your own board/circuit which allows you to program the chip without moving it around as this is really tedious and not worth the effort. Also moving the chip around is a [ESD hazard][6].

Also please note that you'll need to add a clock source for the chip to work (most of the time). Or you'll need to enable an internal PLL. It will in any case require more effort on your part to make sure that the MCU can work. Therefore using the whole arduino board is preferable.

  [1]: https://en.wikipedia.org/wiki/Flash_memory
  [2]: https://en.wikipedia.org/wiki/Non-volatile_memory
  [3]: https://en.wikipedia.org/wiki/Dual_in-line_package
  [4]: https://en.wikipedia.org/wiki/Quad_Flat_Package
  [5]: https://en.wikipedia.org/wiki/Surface-mount_technology#/media/File:Photo-SMDchips.jpg
  [6]: https://en.wikipedia.org/wiki/Electrostatic_discharge


body:
Yes you can do it (as said by Tarick).

Note about clock:

Be sure to program it correctly:

- Do not add a bootloader if you don't need one
- Do not use an external oscillator if you don't have one on your new board! This is important, since if you remove it you will not be able to start or programming it again!

So, before you remove the IC, set this on your Arduino (I assume it is an ATMega328):

- 8MHz internal (leave external only if you have an oscillator in the new board!)
- Bootloader: no

You will see that you do not have this options if you select a normal Arduino, since it already has an oscillator.

So you should use the board manager and add this:
https://github.com/MCUdude/MiniCore


body:
As code is stored in the flash memory, your code won't erase until some unexpected happens. But the question might comes in whether your code will work properly or not when you remove microcontroller from arduino board and connect with breadboard.

As you are planning to remove the microcontroller, I am guessing you are using Arduino Uno atmega328 DIP package.

You need to do two things for the proper function of the microcontroller in the breadboard. There are other solutions exist. I always prefer this one as easy.

 1. connect 16MHz crystal with 22p(two) capacitor with the corresponding crystal pin(pin 9 &10). The crystal circuit is straightforward. Searching google might help.
 2. Pull the Reset Pin with VCC using a 10k resistor.


body: Don't forget 0.1uF caps on the VCC and AVCC pins to Gnd. AVCC must also have power on it, either direct to the VCC pin, or thru a filter (small inductor)


message:
Using a class inside of another class

I have a seemingly simple problem that seems to be popular, but after searching several forums I still have not found the answer: How do you use a class inside of another class?

I have simplified my problem:

    class A {
      const int pin;
      public:
      A(int attachPin) : pin(attachPin) {
      }

      void setup() {
        pinMode(pin, INPUT_PULLUP);
      }
    };

    class B {
      A myA;
      public:
      B(int a_attach) : myA(a_attach) {
      }

      void setup() {
        myA.setup();
      }
    };

    B test;

    void setup() {
       test.setup();
    }

    void loop() {
    }

body: I think, the problem in that line B test. You are define a variable, but you forget to define default constructor ( B() ). You try to setup an A class with unknown pin! To avoid this you may define test variable in that way B test(2); or in that way const int test_pin = 2; B test(test_pin);. Also to avoid this problem you may to set default value to the constructor sucha as  B(int attach=2) : myA(attach) {} and define test variable, as you do in your code B test;.


message:
Reading data from the MCP3002

I am using a MCP3002 to convert an analog signal to digital data. It works fine actually, sends good data. However; After a while, when the power is turned off and on again a few times, it only returns zeros. If I Power it on the next day, it works for a while again.

I am just beginning with SPI, so I do not know 'all' the basics. Is there something I should reset when powering on or something? (Clock, Timing, etc.)

This is the code I am using (pretty straightforward):

 #include <SPI.h>
 SPISettings spiSettings(7280000, MSBFIRST, SPI_MODE0);
 const int SPI_CS = 2;

 void setup() {
  pinMode (SPI_CS, OUTPUT);
  SPI.begin();
  SPI.setBitOrder(MSBFIRST);
  SPI.setFrequency(7280000);
 }

 void loop() {
  SPI.beginTransaction(spiSettings);
  digitalWrite (SPI_CS, LOW);

  uint8_t cmd = 0b11000000;
  byte msb, lsb;
  word assembled;

  msb = SPI.transfer(cmd);
  lsb = SPI.transfer(0);

  assembled = word(msb, lsb);
  Serial.println(assembled);

  digitalWrite (SPI_CS, HIGH);
  SPI.endTransaction();
 }

Is there something wrong, or should something be added to this?

body:
I thin the following is happening:

The MCP transmits 1 measurement per SPI transaction, which consists of activating chip select, reading data and deactivating chip select. To distinguish between different transactions, the time between deactivation and reactivation of chip select need to have a bit delay between them. Currently your code runs really fast, a few microseconds between the transactions at max.

This may also be connected to the MCP needing time to measure the analog signal.

I think there is some kind of race condition, so that the MCP does not have a new value to transmit, either because the MCP hasn't finished measurement yet, or because the delay between the transactions were just a bit too short, maybe a combination of both.

When the MCP is once in this situation, it will only send zeros at that point  (read chapter 5.1 in the datasheet. Last sentence in the left column).

You need to give the MCP more time between the transactions. I suggest using a small delay at the end of the `loop()` function. You can experiment with the actual value, I would guess, that you can go down to the microseconds range.


message:
RS485 communication problem

I'm trying to achieve RS485 communication between Arduino Mega and Arduino UNO as specified in following link:

https://www.engineersgarage.com/arduino/rs485-communication-between-arduino-mega-and-arduino-pro-mini

But now my problem is The master i.e. Arduino Mega doesn't print anything on Serial Monitor.

Please help me out to solve this issue, trying from week still no success.

---

Sir Peter Paul Kiefer,

Im attaching my circuit setup

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

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

Master Code/Mega code

    void setup()
    {
      //Using Serial1 Port
      Serial1.begin(9600);
      Serial.begin(9600);

      //DE/RE Controling pin of RS-485
      pinMode(8, OUTPUT);
    }

    void loop()
    {
      char getdata='m';

      //DE/RE=HIGH Transmit Enabled M1
      digitalWrite(8,HIGH);

      //Write '9' and Fetch Data From Pro Mini
      Serial1.print('9');

      //DE/RE=LOW Receive Enabled M1
      digitalWrite(8,LOW);
      delay(1000);

      //If Serial Data is available
      if(Serial1.available())
      {
        while( Serial1.available() && getdata!='d' )
        {
          getdata=Serial1.read();
          Serial.print(getdata);
        }

        Serial.println("");
      }
    }

Slave code

    void setup()
    {
      //Serial1.begin(9600);//Uncomment for Arduino Lenardo
      Serial.begin(9600);
      //while(!Serial1);//Uncomment for Arduino Lenardo

      //Led Connected
      pinMode(13, OUTPUT);

      //DE/RE Controling pin of RS-485
      pinMode(8, OUTPUT);
    }

    void loop()
    {
      // put your main code here, to run repeatedly:
      char getdata='c';

      //Led OFF
      digitalWrite(13,LOW);
      //DE/RE=LOW Receive Enabled
      digitalWrite(8,LOW);

      if(Serial.available())
      {
        getdata=Serial.read();
      }

      if(getdata=='9')
      {
         //DE/RE=HIGH Transmit Enabled
         digitalWrite(8,HIGH);

         Serial.print("AcruxTek");
         Serial.print("Isld");
      }

      delay(2000);
      //Led ON
      digitalWrite(13,HIGH);
      delay(2000);
    }

---

I connected gnd of RS485 converter to arduino gnd and also i did common gnd between circuits but still no output. I used same code nothing changed.. except one thing the example uses arduino pro mini but i used arduino uno as slave

body:
I think there might be two issues in the engineering garage code. delay() function parameter in both codes is not matched. And another thing might cause problem is"Arduino Serial monitor hardware serial is already connected with another usb-serial converter ic which you are using for code uploading, so you cannot use this serial port for rs-485. So using software serial of Arduino pro-mini is a safe option. Finally you have to connect the software Serial pins with rs-485 converter. I have modified the code a little bit and attached the code herewith.

**Arduino Mega code**

    void setup()
    {
      Serial1.begin(9600);//Using Serial1 Port
      Serial.begin(9600);
      pinMode(8, OUTPUT);//DE/RE Controling pin of RS-485
    }

    void loop()
    {
      digitalWrite(8,HIGH);//DE/RE=HIGH Transmit Enabled M1
      Serial1.print('9');//Write '9' and Fetch Data From Pro Mini

      int timeOut = 0;
      digitalWrite(8,LOW);//DE/RE=LOW Receive Enable
      while(!Serial1.available() && timeOut < 5000)
      {
       delay(1);
       timeOut++; // wait 5s to get response from slave
      }
      String response = Serial1.readString();
      Serial.println(response);
    }

**Arduino Pro-Mini Code**

    #include <SoftwareSerial.h>
    #define RS485_RX 2
    #define RS485_TX 3
    SoftwareSerial mySerial(RS485_RX,RS485_TX);//Creating object

    void setup()
    {
      //Serial1.begin(9600);//Uncomment for Arduino Lenardo
      Serial.begin(9600);
      mySerial.begin(9600);
      //while(!Serial1);//Uncomment for Arduino Lenardo

      pinMode(13, OUTPUT);//Led Connected
      pinMode(8, OUTPUT);//DE/RE Controling pin of RS-485
    }

    void loop()
    {
      digitalWrite(13,LOW);//Led OFF
      digitalWrite(8,LOW);//DE/RE=LOW Receive Enable

      while(!mySerial.available())
      {
       delay(1);
      }

      String res = mySerial.readString();
      if (res == "9")
      {
        digitalWrite(8,HIGH);//DE/RE=HIGH Transmit Enabled
         mySerial.print("AcruxTek");
         mySerial.print("Isld");
      }
      digitalWrite(13,HIGH);//Led OFF
    }


body:
It's not really clear from the picture, but it seems that, the two adapter have no common ground. i.e you have to connect the ground (GND) pin of one the adapter to the GND pin of the other one. But do *not* remove the connection between the GND pins and the arduino GND pins.

I also assume that the mega-adapter is powered with 3.3 V and the UNO-adapter is powered with 5 V (or 3.3V I can not see). This might cause a problem, because the MAX485 chip needs a 5V power supply.

EDIT:

Sorry by a second view a saw, the mega delivers 5 V. So possibly you only have to connect the GNDs of the adapters to solve your problem.

EDIT 2:

I guess the little yellow wire in front of of both adapters connects the DE pins of them. The DE pin of each adapter is also connected to the respective Arduino PIN 8. So it doesn't matter which Arduino is requesting to switch the adapter into the send mode. Both adapters are sending. As far as I know, the adapter only work in Half Duplex you mus define the direction of the data flow. If one adapter is in send mode the other must be in receive mode.

It might also be possible that the DE and RE PIN of each adapter is connected.
But this seams strange to me also. With that I would say you setup up one adapter in both receive and send mode and the other in none of them.

EDIT 3:

By looking into the MAX485 Spec. I saw that RE is LOW active but labeled as RE (which I understood as HIGH active), so sorry the last paragraph of my EDIT 2 is nonsense. So, perhaps it's a matter of timing or (more likely) there is still something wrong with the wiring.

EDIT 4:

In the picture I see that you connect the hardware tx and rx pins to the adapter. But Software Serial needs its own pins. Pin0 and Pin1 are connected with the PC Serial Terminal over the built in USB to Serial adapter of the arduino UNO. That's the reason why you need the software serial solution on an arduino. You need a second serial interface and UNO has only one of them which is already used for the connection to the PC (Programming and serial monitor).

In the code I don't see the initialization of the software serial port.
This is also necessary:

    #include <SoftwareSerial.h>

    const byte rxPin = 2;
    const byte txPin = 3;

    // set up a new serial object
    SoftwareSerial mySerial (rxPin, txPin);


message:
Nano 33 IoT rescue from the dead: No USB. No upload mode

First of all: my board used to work fine.

Now my Nano 33 IoT turns ON (green light) when connected to USB on Mac but:

1. doesn't enter in upload mode after pressing twice on board button.
2. doesn't shows up in any serial port: nor `/dev/cu.usbmodem14*01`, neither `/dev/tty.usbmodem14*01`

For reasons too long to explain, I want to connect via ANY pins to the SAMD21 and force the burning of a new bootloader.

Is that possible in any way? Any idea is welcome!

Tx

body:
Use the SWD interface and a programmer to burn the bootloader to SAMD.

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

source of the picture https://medium.com/@manuel.bl/arduino-in-circuit-debugging-with-platformio-9f699da57ddc

I had luck with [Adafruit DAP library][2] using an Arduino M0 to burn a bootloader to MKR Zero.

  [1]: https://i.stack.imgur.com/ZFNM6.png
  [2]: https://learn.adafruit.com/programming-an-m0-using-an-arduino