# Question
Title: LCD 16*02 I2C shield only shows first character printed
I have an I2C LCD screen provided with a Sunfounder kit and certainly built by DFRobot or such a constructor (there is nothing written on the LCD), and an Arduino Uno R3 copy.

My issue is when I use `lcd.print()` to write a string on the LCD, only the **first character** of the string is printed. I can only print on other positions by using setCursor but only one character at a time.

I tried to change libraries (https://github.com/fdebrabander/Arduino-LiquidCrystal-I2C-library, the one supplied with the LCD...), It always behaves the same!

For example, here's a very simplistic program which exhibits this behavior:

```
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);
// set the LCD address to 0x27 for a 16 chars and 2 line display
void setup() {
  lcd.init();
  lcd.backlight();
}

void loop() {
  lcd.print("write");
  delay(1000);
  lcd.setCursor(10, 0);
  lcd.print("p10");
  lcd.setCursor(0, 1);
  lcd.print("0, 1 write");
  if((millis() / 1000) % 5 == 0) {
    lcd.clear();
    delay(1000);
  }
}

```

I end up with something like:

```
w      p
0w

```

On the screen (before the `clear()` occurs of course).

Instead of something like:

```
write  p10
0, 1 writewrite

```

The lcd itself was ok some time ago. The only thing I could think is I recently updated to Arduino 1.6.6. Can it be a bug in the compiler?

The hello world from DFRobot also doesn't work properly (first char only, again) (please note to make it display something with my LCD I have to change the address from 0x20 to 27).

# Answer
That's definitely a bug appeared in 1.6.6. For reference, see https://blog.arduino.cc/2015/11/03/arduino-ide-1-6-6-released-and-available-for-download/#comment-278766 https://forum.arduino.cc/index.php?topic=359652.0 http://forum.arduino.cc/index.php?topic=357312.msg2476987#msg2476987

Last link seems to provide a solution, by a **updated version of LCD I2C lib** : https://github.com/marcoschwartz/LiquidCrystal\_I2C (not yet tried).

The 1.6.6 is a bit messy according some people, but the I2C lib too ;). So the question is : where should it be fixed ?
> 4 votes

# Answer
Your code contains, in part,

```
#include <LiquidCrystal_I2C.h>
....
LiquidCrystal_I2C lcd(0x27, 16, 2); // set the LCD address to 0x27 for a 16 chars and 2 line display
void setup() {
  lcd.init();
  lcd.backlight();
}

```

For all of the constructors in `LiquidCrystal_I2C.h` on my system, the second and third parameters are `EN` and `RW`, ie, the enable and read/write backpack-pin numbers. They don't specify the size of the display.

I suggest trying constructor usage like

```
LiquidCrystal_I2C lcd(0x27,2,1,0,4,5,6,7); // 0x27 is the I2C bus address for an unmodified backpack

```

and in place of `lcd.init();` say

```
lcd.begin (16,2); // for 16 x 2 LCD module

```

Note, `lcd.begin()` will call `init()`.
> 3 votes

# Answer
I'm incredibly new to Arduino (I literally got one a few hours ago and I'm still finding my feet with it!) so take that into account when considering anything I say however I'd be inclined to agree that this may be an issue with the 1.6.6 IDE.

I was getting pretty much the same symptoms on a Freematics MEGA2560/3.2" SSD1289 LCD using the MultiLCD library using 1.6.6. Based on your comment above I uninstalled and installed 1.6.5 instead, recompiled and uploaded and it's now displaying properly...
> 2 votes

# Answer
I tried the solution described by AFract and it solved the problem. (sorry, I couldn't reply to his comment because I don't have enough reputation.)

I got the new LiquidCrystal\_I2C library here: https://github.com/marcoschwartz/LiquidCrystal\_I2C

Info on the code commit is here: https://github.com/marcoschwartz/LiquidCrystal\_I2C/pull/5
> 2 votes

# Answer
I have had same problem, issued on v1.6.7 and v1.6.8. I solved it with the new 'marcoschwartz' library specified in other answers.

Previously, I had used the same DFRobot library, which worked fine on IDE 1.6.0, until I upgraded on v1.6.7.
> 2 votes

# Answer
I had the same problem. My LCD only showed one character. I downloaded and tryed docens of LCD libraries and ended up with a bunch of libraries installed in my IDE. After days trying to solve the problem I decided to clear my IDE deleting the libraries directory (mind that the IDE could take them from documents/arduino/library folder). After that I tested one by one the LCD libraries. I case it did not work I deleted it. The one posted above https://github.com/marcoschwartz/LiquidCrystal\_I2C worked!!.I don't really know where was the problem exactly, maybe a conflict among the libraries intalled.
> 1 votes

---
Tags: arduino-uno, i2c, lcd, compile
---


title: Serial Interrupt

text:
# Question
Title: Serial Interrupt
I want to create a simple program, that responds to me sending a character over the Arduino IDE console. I am using an arduino UNO. Here is my program:

```
volatile bool MeasReceived=false;

ISR(PCINT2_vect){
  PCICR = 0b00000000;    // turn off port d
  MeasReceived=true;
}

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

  Serial.print("Hello PC");
  delay(1000);
  cli();
  PCICR |= 0b00000100;    // turn on port d
  PCMSK2 |= 0b0000001;    // turn on pins PD0 , PCINT16
  sei();

}

void loop() {

  if(MeasReceived==true){
    MeasReceived=false;
    inByte = Serial.read();

    if(inByte=='A'){   //A: PC requests measurement data from Arduino
       Serial.print('B');
    }
    else{
      Serial.print(inByte);
    }
  }
  PCICR = 0b00000001; // re-enable port d
}

```

What I do is that I set the RX pin as a pin change interrupt. After that, I send a character through the console, for example 'A'. The ISR kicks in, firstly disabling the interrupt, and after that, the flag is set true. That way, I enter the part of the code where I do the Serial.read() command, to find what character was sent to me via the console.

The problem is that, no matter the character I send, the result is always 255. That means that the value of inByte, after the Serial.read() is always 255. What goes wrong?

**EDIT: Original question answered by me below. However, one interesting thing occured in the new code posted below.** If I put the Arduino to sleep (powerDown Mode), and try to wake it up with the serial interrupt, if I send only one character, then the arduino does wake up, but does not enter the ISR! If I send two characters, then the ISR is accessed and the flags set, with the program working fine. Here is the code, to reproduce the issue:

```
volatile bool MeasReceived=false;
uint8_t inByte;

ISR(PCINT2_vect){
  PCMSK2 = 0b00000000;    // turn off port d
  MeasReceived=true;
}

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);

  Serial.begin(9600);
  Serial.flush();
  Serial.print("Hello PC");
  delay(1000);

  cli();
  PCICR = 0b00000100;    // turn on port d
  PCMSK2 = 0b00000001;    // turn on pins PD0 , PCINT16
  sei();
}

void loop() {

  if(MeasReceived==true){
    MeasReceived=false;
    delay(2000);
    inByte = Serial.read();

    if(inByte=='A'){   //A: PC requests measurement data from Arduino
       Serial.print('B');
    }
    else{
      Serial.print(inByte);
    }
    PCMSK2 = 0b00000001;

  }

  set_sleep_mode(SLEEP_MODE_PWR_DOWN);    //Set power down mode
  sleep_bod_disable();  //disable brown-out detection
  digitalWrite(LED_BUILTIN, LOW);
  sleep_enable();
  sleep_cpu();
  sleep_disable();
  digitalWrite(LED_BUILTIN, HIGH);
  delay(1000);
  //int i=Serial.available();
  //Serial.print(i);
  delay(1000);

}

```

So, by sending one character, the Arduino wakes up, the LED shines, and after the two seconds, Arduino goes back to sleep, never entering the ISR and as a result not setting the flag. Furthermore, having sent one character, if I uncomment the Serial.available() printing, it prints "0"!

If I send two characters, the Arduino wakes up, and the program works fine.

# Answer
> 2 votes
Your diagnostic about the interrupt handled too fast is correct. When a byte arrives at the serial port, the start bit will trigger the interrupt, but the byte is only available for reading once the UART receives the stop bit, which is about one millisecond later.

> to disable/re-enable the pin-change interrupt, the right way seems to be to use the PCMSK register and not the PCICR.

The canonical procedure for enabling *any* edge-triggered interrupt is to first clear the interrupt flag, then set the interrupt enable bit. Note that the interrupt flag is cleared by writing a logic one to it. For the PCINT2 interrupt that would be:

```
PCIFR =  _BV(PCIF2);  // clear interrupt flag
PCICR |= _BV(PCIE2);  // enable interrupt

```

This being said, there is no point in using a pin change interrupt in the first place. You can instead use the canonical idiom

```
if (Serial.available() > 0) {
    char inByte = Serial.read();
    // ...
}

```

If you plan to sleep, you will likely want to do it with the serial port enabled, in order for it not to miss the start bit. This means you will use the IDLE sleep mode. Then, when the serial port receives a full byte, it will wake up the CPU with its own interrupt, so you do not have to take care of this yourself.

---

**Edit 1**: The simplest way to put the CPU to sleep until the next interrupt is received is to call `sleep_mode()` at the end of `loop()`, e.g.:

```
// Sleep until the next character is received.
set_sleep_mode(SLEEP_MODE_IDLE);
if (!Serial.available()) {
    sleep_bod_disable();
    sleep_mode();
}

```

There is, however, a race condition here: if the interrupt fires after you test `Serial.available()` but before going to sleep, you will sleep instead of handling the received character. The solution to this problem is to do the test with interrupts disabled and then enable them right before issuing the `sleep` instruction, as explained in the documentation of the avr-libc:

```
set_sleep_mode(SLEEP_MODE_IDLE);
cli();
if (!Serial.available()) {
    sleep_enable();
    sleep_bod_disable();
    sei();
    sleep_cpu();
    sleep_disable();
}
sei();

```

**Edit 2**: answering the questions in the comments.

1. Pin change interrupt allows you to sleep deeper than IDLE, but if you do so, the UART will be stopped and it will miss the start bit, which could throw off its timing. I would rather stick with IDLE and use the `power_*_disable()` functions to turn off the unneeded peripherals.
2. I have a theory, though I don't know if it's valid. Look at the schematic of the PCINT detection. If the clock is stopped, a change in the pin level will make the XOR gate switch to 1, which presumably wakes up the MCU, but that will not be recorded by the downstream flip-flops, which rely on the clock. If the pin returns to its original level before the clock restarts (which takes some time when coming out of PWR\_DOWN), then the flip-flops never see the pin change condition, and the interrupt flag does not rise.

**Edit 3**: I made a test that confirms that, when waking up from PWR\_DOWN by a pulse-triggered PCINT event, the ISR *does not run* if the pulse is too short. The setup involves two Arduinos:

* the “tester” Arduino:
    + sends pulses of various lengths through digital 8 = PB0
    + forwards on TX the data received on RX
* the “DUT” Arduino:
    + sleeps in PWR\_DOWN mode
    + wakes up by pin change interrupt on digital 8 = PB0 = PCINT0
    + reports whether the ISR ran on the serial port

The connections are:

```
DUT   Tester    PC
───────────────────
        USB --- USB
GND --- GND
+5V --- +5V
  8 --- 8
 TX --- RX

```

The “tester” program:

```
const uint32_t PULSE_PERIOD = 500;  // pulses every 500 ms

void setup() {
    DDRB |= _BV(PB0);  // digital 8 = PB0 as output
    Serial.begin(9600);
    Serial.println("Tester: ready");
}

void loop() {
    // Forward the serial communication.
    while (Serial.available())
        Serial.write(Serial.read());

    // Periodically send a pulse.
    static uint32_t last_pulse_time;
    if (millis() - last_pulse_time >= PULSE_PERIOD) {
        last_pulse_time += PULSE_PERIOD;

        // Send a pulse of 2^n microseconds.
        static uint8_t n = 0;
        uint16_t length = 1U << n;
        Serial.print("Tester: sending pulse of ");
        Serial.print(length);
        Serial.println(" us");
        Serial.flush();
        uint32_t now = millis();
        while (millis() == now) ;  // wait for the tick
        PORTB |= _BV(PB0);
        delayMicroseconds(length);
        PORTB &= ~_BV(PB0);

        // Next pulse size.
        if (++n >= 16) n = 0;
    }
}

```

The “DUT” program:

```
#include <avr/sleep.h>

// The PCINT ISR only sets a flag.
volatile bool isr_ran;
ISR(PCINT0_vect) { isr_ran = true; }

void setup() {
    // Setup interrupt.
    PCMSK0 = _BV(PCINT0);  // sense PCINT0 = PB0
    PCIFR |= _BV(PCIF0);   // clear interrupt flag
    PCICR  = _BV(PCIE0);   // enable PCINT0 interrupt

    // Avoid other interrupts.
    TIMSK0 = 0;         // avoid timer interrupt
    PORTD |= _BV(PD0);  // pull RX high to prevent USART_RX interrupt
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);

    Serial.begin(9600);
    Serial.println("DUT: ready");
}

void loop() {
    loop_until_bit_is_clear(PINB, PB0);  // wait for LOW input
    Serial.println("DUT: going to sleep");
    Serial.flush();
    isr_ran = false;
    sleep_mode();
    Serial.print("DUT: woke up, ISR ran: ");
    Serial.println(isr_ran ? "YES" : "NO");
}

```

And the results:

```
DUT: going to sleep
Tester: sending pulse of 1 us
DUT: woke up, ISR ran: NO
DUT: going to sleep
Tester: sending pulse of 2 us
...
Tester: sending pulse of 1024 us
DUT: woke up, ISR ran: NO
DUT: going to sleep
Tester: sending pulse of 2048 us
DUT: woke up, ISR ran: YES
DUT: going to sleep
Tester: sending pulse of 4096 us
DUT: woke up, ISR ran: YES
...

```

Conclusion: a pulse of 1024 µs or shorter wakes up the Arduino but the ISR does not run. If the pulse is 2048 µs or longer, the ISR does run.

# Answer
> 0 votes
After more testing, it seems that the problem was that when I sent the character over the console, the interval between the time t1 that the change was noticed and the ISR was fired, and the time t2 that the Serial.read() happened, was very short, almost immediate. As a result, the byte (character) that I had sent over the serial console was not yet ready to be read, and the Serial.read() command returned plain '1's.

Furthermore, to disable/re-enable the pin-change interrupt, the right way seems to be to use the PCMSK register and not the PCICR. The initially posted code, had the extra problem that, when PCICR was re enabled (set to 0x01), the ISR was immediately fired again, reading an extra character (obviously all '1's). That was solved by disabling/ re-enabling the pin change interrupt using PCMSK register. Here is the corrected code, which seems to work fine:

```
volatile bool MeasReceived=false;
uint8_t inByte;

ISR(PCINT2_vect){   //ISR for pin-change interrupts occuring at PD0-PD7

  PCMSK2 = 0b00000000;    // turn off PD0 interrupt
  MeasReceived=true;      //Set char received Flag

}

void setup() {

  Serial.begin(9600);
  Serial.flush();
  Serial.print("Hello PC");
  delay(1000);

  cli();
  PCICR = 0b00000100;    // turn on port d pin change interrupts
  PCMSK2 = 0b0000001;    // turn on pin PD0 , PCINT16
  sei();
}

void loop() {

  if(MeasReceived==true){  //If ISR fired
    MeasReceived=false;    //Reset the flag
    delay(1000);           //Wait a while for the character to be set. 1000ms may be too much
    inByte = Serial.read();  // Read the character that was sent

    if(inByte=='A'){   //If the character was A, write B to console
       Serial.print('B');
    }
    else{   //else, write the ASCII code of the character received
      Serial.print(inByte);
    }
    PCMSK2 = 0b00000001;   //re-enable PD0 interrupt
  }
}

```

---
Tags: serial, interrupt, isr
---


# Question
Title: Mega: attachInterrupt on pin 18/19/20/21 not working
**Task:** I'm trying to create a fan-control with the arduino mega. I'm generating a PWM signal on pin 6 and 7 and want to use interrups to measure the rpm of the fans.

**Problem:** On pin 2 and 3 everything wors fine, but I cannot get it working on any of pins 18-21. The numbers are jumping around wildly. BUT: The numbers are correct on 0% and 100% duty!

**What I've aleady tried:**

* Changed my timer from 1 to 4 (currently it's 4)
* Replaced the display to get rid of U8g2lib.
* Changing connection order of the signal cables (and thus the connected fan).
* Check the signal with an digital oscilloscope (looks fine on all ports)
* Set the global ISR variables to volatile and byte to prevent update hazards.
* Bang my head on the table.

Nothing solved my problem. What am I missing?

```
    #include <Arduino.h>
    #include <U8g2lib.h>
    #include <Bounce2.h>

    #ifdef U8X8_HAVE_HW_SPI
    #include <SPI.h>
    #endif
    #ifdef U8X8_HAVE_HW_I2C
    #include <Wire.h>
    #endif

    U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/U8X8_PIN_NONE);

    #define PIN_CONTROL_S 6
    #define PIN_CONTROL_L 7
    #define PIN_SENSE_1 18
    #define PIN_SENSE_2 19
    #define PIN_SENSE_3 3
    #define PIN_SENSE_4 2
    #define PIN_BUTTON 22

    #define UPDATE_CYCLE 1000 // Refresh interval of the display/measurement.
    #define SIGNAL_PER_RND 2  // 2 Signals per revolution
    #define DUTY_INC 10       // Increate of the duty in % per button press
    #define PWM_MAX 320       // PWM mode counts up 320 then down 320 counts (25kHz)
    #define lineOffset 10     // Offset (y) per line on display

    word duty = 0;  // 0-100 duty cycle
    word dutyS = 0; // 0-320 = 0-100% duty cycle for small fans
    word dutyL = 0; // 0-320 = 0-100% duty cycle for large fans

    volatile byte counterFan1 = 0;
    volatile byte counterFan2 = 0;
    volatile byte counterFan3 = 0;
    volatile byte counterFan4 = 0;

    unsigned long lastDraw = 0;

    Bounce btnBouncer = Bounce(PIN_BUTTON, 50);

    void setupPwm() {
        // Steuerung
        pinMode(PIN_CONTROL_S, OUTPUT);
        pinMode(PIN_CONTROL_L, OUTPUT);

        // Sensoren
        pinMode(PIN_SENSE_1, INPUT_PULLUP);
        pinMode(PIN_SENSE_2, INPUT_PULLUP);
        pinMode(PIN_SENSE_3, INPUT_PULLUP);
        pinMode(PIN_SENSE_4, INPUT_PULLUP);

        // Clear timer register
        TCCR4A = 0;
        TCCR4B = 0;
        TCCR4C = 0;
        TCNT4 = 0;

        TCCR4A |= _BV(WGM41);  // Set PWM mode, phase correct. TOP is ICR1.  (Mode 10)
        TCCR4B |= _BV(WGM43);  // Start BOTTOM, TOP from OCR1x to OCR1x.

        TCCR4B |= _BV(CS40);   // Prescaler 1:1

        TCCR4A |= _BV(COM4A1); // High output OC1A on compareMatch when up-counting / low when down-counting
        TCCR4A |= _BV(COM4B1); // High output OC1B on compareMatch when up-counting / low when down-counting

        OCR4A = dutyS;         // set initial duty
        OCR4B = dutyL;         // set initial duty

        ICR4 = PWM_MAX; // TOP for TCNTx. 320 => @16Mhz CPU -> 25kHz PWM
    }

    void setupDisplay() {
        u8g2.begin();
        u8g2.setFont(u8g2_font_6x10_tf);
        u8g2.setFontRefHeightExtendedText();
        u8g2.setDrawColor(1);
        u8g2.setFontPosTop();
        u8g2.setFontDirection(0);
    }

    void attachInterrups() {
        attachInterrupt(digitalPinToInterrupt(PIN_SENSE_1), isrFan1, RISING);
        attachInterrupt(digitalPinToInterrupt(PIN_SENSE_2), isrFan2, RISING);
        attachInterrupt(digitalPinToInterrupt(PIN_SENSE_3), isrFan3, RISING);
        attachInterrupt(digitalPinToInterrupt(PIN_SENSE_4), isrFan4, RISING);
    }

    void detachInterrups() {
        detachInterrupt(digitalPinToInterrupt(PIN_SENSE_1));
        detachInterrupt(digitalPinToInterrupt(PIN_SENSE_2));
        detachInterrupt(digitalPinToInterrupt(PIN_SENSE_3));
        detachInterrupt(digitalPinToInterrupt(PIN_SENSE_4));
    }

    void setup() {
        setupDisplay();
        setupPwm();
        attachInterrups();

        pinMode(PIN_BUTTON, INPUT_PULLUP);
    }

    void draw(void) {
        char output[22]; // One line of the display can show 21 characters.
        float uPerSekS1 = counterFan1; // * 60000 / measureDuration / SIGNAL_PER_RND;
        float uPerSekS2 = counterFan2; // * 60000 / measureDuration / SIGNAL_PER_RND;
        float uPerSekL1 = counterFan3; // * 60000 / measureDuration / SIGNAL_PER_RND;
        float uPerSekL2 = counterFan4; // * 60000 / measureDuration / SIGNAL_PER_RND;
        int y = 0;

        sprintf(output, "Duty    :    %3d", duty);
        u8g2.drawStr(0, y, output);

        y += lineOffset;
        sprintf(output, "U/sec S1: %6d", (int) uPerSekS1);
        u8g2.drawStr(0, y, output);

        y += lineOffset;
        sprintf(output, "U/sec S2: %6d", (int) uPerSekS2);
        u8g2.drawStr(0, y, output);

        y += lineOffset;
        sprintf(output, "U/sec L1: %6d", (int) uPerSekL1);
        u8g2.drawStr(0, y, output);

        y += lineOffset;
        sprintf(output, "U/sec L2: %6d", (int) uPerSekL2);
        u8g2.drawStr(0, y, output);
    }

    void measure() {
        unsigned long measureDuration = millis() - lastDraw;
        if (measureDuration >= UPDATE_CYCLE) {
            // Deactivate interrupt while we are calculating
            detachInterrups();

            u8g2.clearBuffer();
            draw();
            u8g2.sendBuffer();

            // reset state
            counterFan1 = 0;
            counterFan2 = 0;
            counterFan3 = 0;
            counterFan4 = 0;
            lastDraw = millis();

            // Reactivate interrupt
            attachInterrups();
        }
    }

    void loop() {
        measure();
        btnBouncer.update();
        if (btnBouncer.fell()) {
            // Button was pressed. Increase duty.
            if (duty > 90) {
                duty = 0;
            } else {
                duty += DUTY_INC;
            }

            dutyS = duty * PWM_MAX / 100;
            dutyL = duty * PWM_MAX / 100;

            OCR4A = dutyS;
            OCR4B = dutyL;
        }
    }

    void isrFan1() {
        counterFan1++;
    }

    void isrFan2() {
        counterFan2++;
    }

    void isrFan3() {
        counterFan3++;
    }

    void isrFan4() {
        counterFan4++;
    }

```

**Edit:** I've tried my best to create a readable circuit diagram. The 4-pin connectors represent the fans.

# Answer
Ok, I did not solve the problem regarding pin 18-21, but I found an other solution: using PinChangeInterrupts and the PinChangeInterrupt libary

I did not change anything about my hardware setup, excep moving the wires from pin 18/19 to A8/A9. I've changed my code to use PinChangeInterrups for two of the fans, maybe I'll change all 4 fans.

Here is the new code:

```
#include <Arduino.h>
#include <U8g2lib.h>
#include <Bounce2.h>
#include <PinChangeInterrupt.h>

#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif

U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/U8X8_PIN_NONE);

#define PIN_CONTROL_S 6
#define PIN_CONTROL_L 7

//#define PIN_SENSE_1 18
//#define PIN_SENSE_2 19
#define PIN_SENSE_1 A8
#define PIN_SENSE_2 A9

#define PIN_SENSE_3 3
#define PIN_SENSE_4 2
#define PIN_BUTTON 22

#define UPDATE_CYCLE 1000 // Refresh interval of the display/measurement.
#define SIGNAL_PER_RND 2  // 2 Signals per revolution
#define DUTY_INC 10       // Increate of the duty in % per button press
#define PWM_MAX 320       // PWM mode counts up 320 then down 320 counts (25kHz)
#define lineOffset 10     // Offset (y) per line on display

word duty = 0;  // 0-100 duty cycle
word dutyS = 0; // 0-320 = 0-100% duty cycle for small fans
word dutyL = 0; // 0-320 = 0-100% duty cycle for large fans

volatile byte counterFan1 = 0;
volatile byte counterFan2 = 0;
volatile byte counterFan3 = 0;
volatile byte counterFan4 = 0;

unsigned long measureDuration;
unsigned long lastDraw = 0;

Bounce btnBouncer = Bounce(PIN_BUTTON, 50);

void setupPwm() {
    // Steuerung
    pinMode(PIN_CONTROL_S, OUTPUT);
    pinMode(PIN_CONTROL_L, OUTPUT);

    // Sensoren
    pinMode(PIN_SENSE_1, INPUT_PULLUP);
    pinMode(PIN_SENSE_2, INPUT_PULLUP);
    pinMode(PIN_SENSE_3, INPUT_PULLUP);
    pinMode(PIN_SENSE_4, INPUT_PULLUP);

    // Clear timer register
    TCCR4A = 0;
    TCCR4B = 0;
    TCCR4C = 0;
    TCNT4 = 0;

    TCCR4A |= _BV(WGM41);  // Set PWM mode, phase correct. TOP is ICR1.  (Mode 10)
    TCCR4B |= _BV(WGM43);  // Start BOTTOM, TOP from OCR1x to OCR1x.

    TCCR4B |= _BV(CS40);   // Prescaler 1:1

    TCCR4A |= _BV(COM4A1); // High output OC1A on compareMatch when up-counting / low when down-counting
    TCCR4A |= _BV(COM4B1); // High output OC1B on compareMatch when up-counting / low when down-counting

    OCR4A = dutyS;         // set initial duty
    OCR4B = dutyL;         // set initial duty

    ICR4 = PWM_MAX; // TOP for TCNTx. 320 => @16Mhz CPU -> 25kHz PWM
}

void setupDisplay() {
    u8g2.begin();
    u8g2.setFont(u8g2_font_6x10_tf);
    u8g2.setFontRefHeightExtendedText();
    u8g2.setDrawColor(1);
    u8g2.setFontPosTop();
    u8g2.setFontDirection(0);
}

void attachInterrups() {
//    attachInterrupt(digitalPinToInterrupt(PIN_SENSE_1), isrFan1, RISING);
    attachPCINT(digitalPinToPCINT(PIN_SENSE_1), isrFan1, RISING);

//    attachInterrupt(digitalPinToInterrupt(PIN_SENSE_2), isrFan2, RISING);
    attachPCINT(digitalPinToPCINT(PIN_SENSE_2), isrFan2, RISING);

    attachInterrupt(digitalPinToInterrupt(PIN_SENSE_3), isrFan3, RISING);
    attachInterrupt(digitalPinToInterrupt(PIN_SENSE_4), isrFan4, RISING);
}

void detachInterrups() {
//    detachInterrupt(digitalPinToInterrupt(PIN_SENSE_1));
    detachPinChangeInterrupt(digitalPinToPCINT(PIN_SENSE_1));

//    detachInterrupt(digitalPinToInterrupt(PIN_SENSE_2));
    detachPinChangeInterrupt(digitalPinToPCINT(PIN_SENSE_2));

    detachInterrupt(digitalPinToInterrupt(PIN_SENSE_3));
    detachInterrupt(digitalPinToInterrupt(PIN_SENSE_4));
}

void setup() {
//    cli();
    setupDisplay();
    setupPwm();
    attachInterrups();

    pinMode(PIN_BUTTON, INPUT_PULLUP);
//    sei();
}

void draw() {
    char output[22]; // One line of the display can show 21 characters.
    float uPerSekS1 = counterFan1 * 60000 / measureDuration / SIGNAL_PER_RND;
    float uPerSekS2 = counterFan2 * 60000 / measureDuration / SIGNAL_PER_RND;
    float uPerSekL1 = counterFan3 * 60000 / measureDuration / SIGNAL_PER_RND;
    float uPerSekL2 = counterFan4 * 60000 / measureDuration / SIGNAL_PER_RND;
    int y = 0;

    sprintf(output, "Duty    :    %3d", duty);
    u8g2.drawStr(0, y, output);

    y += lineOffset;
    sprintf(output, "U/sec S1: %6d", (int) uPerSekS1);
    u8g2.drawStr(0, y, output);

    y += lineOffset;
    sprintf(output, "U/sec S2: %6d", (int) uPerSekS2);
    u8g2.drawStr(0, y, output);

    y += lineOffset;
    sprintf(output, "U/sec L1: %6d", (int) uPerSekL1);
    u8g2.drawStr(0, y, output);

    y += lineOffset;
    sprintf(output, "U/sec L2: %6d", (int) uPerSekL2);
    u8g2.drawStr(0, y, output);
}

void measure() {
    measureDuration = millis() - lastDraw;
    if (measureDuration >= UPDATE_CYCLE) {
        // Deactivate interrupt while we are calculating
        detachInterrups();

        u8g2.clearBuffer();
        draw();
        u8g2.sendBuffer();

        // reset state
        counterFan1 = 0;
        counterFan2 = 0;
        counterFan3 = 0;
        counterFan4 = 0;
        lastDraw = millis();

        // Reactivate interrupt
        attachInterrups();
    }
}

void loop() {
    measure();
    btnBouncer.update();
    if (btnBouncer.fell()) {
        // Button was pressed. Increase duty.
        if (duty > 90) {
            duty = 0;
        } else {
            duty += DUTY_INC;
        }

        dutyS = duty * PWM_MAX / 100;
        dutyL = duty * PWM_MAX / 100;

        OCR4A = dutyS;
        OCR4B = dutyL;
    }
}

void isrFan1() {
    counterFan1++;
}

void isrFan2() {
    counterFan2++;
}

void isrFan3() {
    counterFan3++;
}

void isrFan4() {
    counterFan4++;
}

```
> 1 votes

---
Tags: arduino-mega, interrupt, pwm, timers
---


# Question
Title: Implement two processes at the same time
I am a beginner in arduino and due to the lockdown I have been learning it by implementing it on tinkercad. I have made a simulation where I have attached :

1. Servo Motor
2. Ultrasonic Sensor
3. Led Bulb
4. LCD display

to an arduino uno 3

My AIM : When something falls under 30cm of the ultrasonic sensor, the servo motor starts from zero position and goes upto 180 degrees in a span of 20seconds and then goes back to its initial position. At the same time and led switches on for 20s and switches off when the motor returns back to its position. I was able to successfully implement this. But then I added an lcd to show the time i.e time is initialized at 0seconds and then goes to 20 seconds and when the motor resets. Time also resets.

I was able to make a timer on another simulation and I tried to run it in this one by placing the code correctly but I am not able to figure out how?

The present code I have written keeps blinking the led at an interval of one second and the servo moves very very slowly.

Any sort of help will be amazing.

This is my simulation, I have made it public, you may copy and simulate it if you have a tinkercad account. Even without an account you can see how it looks.

Here is the code: (Please ask if you want me to add comments some areas)

```
//library code for lcd
#include <LiquidCrystal.h>
//setting up pins
const int rs = 9, en = 8, d4 = 5, d5 = 4, d6 = 3, d7 = 2;

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

unsigned long readTime=20;

//servo motor
#include <Servo.h>
Servo servo_9;
int pos = 0;
//servo motor end

//ultrasonic sensor pin
const int pingPin = 12;

//lcd
signed short seconds;
char timeline[16];

void setup()
{

  servo_9.attach(13); //servo pin
  Serial.begin(9600);

  pinMode(11,OUTPUT);// led

  //lcd initialize
  lcd.begin(16, 2);
  lcd.print("Time : ");

}

void loop()
{

  long duration, cm;
  //Ultrasonic start
  // The PING))) is triggered by a HIGH pulse of 2 or more microseconds.
  // Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
  pinMode(pingPin, OUTPUT);
  digitalWrite(pingPin, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin, HIGH);
  delayMicroseconds(5);
  digitalWrite(pingPin, LOW);

  // The same pin is used to read the signal from the PING))): a HIGH
  // pulse whose duration is the time (in microseconds) from the sending
  // of the ping to the reception of its echo off of an object.
  pinMode(pingPin, INPUT);
  duration = pulseIn(pingPin, HIGH);

  // convert the time into a distance
  cm = microsecondsToCentimeters(duration);

  // Print the distance
  Serial.print("Distance: ");
  Serial.print(cm);
  Serial.print("cm");
  Serial.println();
  // ultrasonic end

  // the servo motor should activate when object is
  //less than 30cm close to the sensor

 if(cm < 30) {

  // sweep the servo from 0 to 180 degrees in steps
  // of 1 degrees
  for (pos = 0; pos <= 180; pos += 1) {

    // tell servo to go to position in variable 'pos'
    servo_9.write(pos);

     //LCD TIMER START
    lcd.setCursor(0, 1);
    sprintf(timeline,"%0.2d secs", seconds);
    lcd.print(timeline);
    delay(1000);
    seconds++;

    //led buld switch on
    digitalWrite(11,HIGH);

    // wait 20ms for servo to reach the position
    delay(200);

    //switch of the bulb
    digitalWrite(11,LOW);

  }

  //moving servo back to zero
  for (pos = 180; pos >= 0; pos -= 1) {
      // tell servo to go to position in variable 'pos'
      servo_9.write(pos);
      // wait 20 ms for servo to reach the position
      delay(20); // Wait for 15 millisecond(s)
            }

    } //if end

  delay(100);

}//loop end

//FUNCTIONS

long microsecondsToCentimeters(long microseconds) {
  // The speed of sound is 340 m/s or 29 microseconds per centimeter.
  // The ping travels out and back, so to find the distance of the
  // object we take half of the distance travelled.
  return microseconds / 29 / 2;
}

```

# Answer
Think of an Arduino as a circus clown spinning plates. It has to spend very little time on any one plate, and then it can keep a lot of plates spinning, moving quickly from one to the next.

That's how "multi-tasking" works on a realtime device like an Arduino. You write a loop function that buzzes through a bunch of sub-tasks, spending a few microseconds on each one, and then repeats the process. Each plate (sub-task) gets a little bit of time on each pass, but only a little.

The `delay()` function is the death of that. If you're in a `delay()`, everything comes to a screeching halt. Your program stops checking for button presses, stops switching output pins to control your motors, etc. It's like the clown taking a coffee break. The plates start crashing to the ground.

You might get away with single-digit delays for things like timing changes in output state (and `delayMicroseconds()` is rarely a problem since those delays are so short), but a `delay(1000)` means everything comes to a screeching halt for a full second.

You need to refactor your code to get rid of calls to `delay()` with delay values of more than a few milliseconds. Do a search on "Arduino blink without delay" to figure out how.

Note that on a single core device with preemptive multi-tasking, the circus clown analogy still holds, but now the OS serves as the clown's manager. The OS schedules the clown's time, and tells it when to switch between plates. If the clown gets distracted by a particularly shiny plate and tries to spend too long on that plate, the OS forces the clown to switch plates. The OS also saves the clown's current state each time it switches away from a task, and restores that state when it returns to that task.

On A multi-core device with preemptive multi-tasking, the manager (OS) has a team of clowns (cores). Each clown (core) gets assigned to different plates (tasks), and all the clowns work at the same time (The cores run concurrently.) The OS has to make sure the clowns (cores) don't bump elbows (have conflicting access to the same memory or other resources.)
> 7 votes

---
Tags: arduino-uno, lcd, servo
---


# Question
Title: 3 input (on/off/off with delay) to control 1device using ESP8266 as Web Server
I want to control one device in three ways : turn on / turn off / turn off with delay. To do that i use an ESP8266 web server + android phone app. The problem is that turn off with delay wont work. It works with `delay()` but i dont want to use `delay()` as it stops other functions. I would be grateful if you could help me. here is my code :

```
#include <ESP8266WiFi.h>
const int device1 = 14;
unsigned long previousMillis = 0;
const long interval = 5000;
const char* ssid     = "****";
const char* password = "****";
#include <Arduino.h>
WiFiServer server(80);
String data = "";

void setup() {
 pinMode(device1, OUTPUT);
Serial.begin(115200, SERIAL_8N1, SERIAL_TX_ONLY);
WiFi.begin(ssid, password);
IPAddress ip(*,*,*,*);
IPAddress gateway(*,*,*,*);
IPAddress subnet(*,*,*,*);
WiFi.config(ip, gateway, subnet);
 while (WiFi.status() != WL_CONNECTED) {
   delay(500);
   Serial.print(".");
 }
 Serial.println("");
 Serial.println("WiFi connected");

 server.begin();

 Serial.println(WiFi.localIP());
 }

void loop() {
    unsigned long currentMillis = millis();

  WiFiClient client = server.available();
 if (!client) {
   return;
 }

 while(!client.available()){
 }

 String req = client.readStringUntil('\r');
 client.flush();
 if (req.indexOf("/on") != -1)
   { digitalWrite(device1, HIGH);}
 if (req.indexOf("/off") != -1)
   { digitalWrite(device1, LOW);}

 if (req.indexOf("/delay") != -1)
 {
  unsigned long currentMillis = millis();
  unsigned long previousMillis = millis();
if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;

    digitalWrite(device1, LOW);

}
}

```

# Answer
> 0 votes
You have various logic problems:

You block until WiFiClient has bytes available. Everything comes to a stop. So if you send a "/delay" command, it will receive and parse that command, turn on the device, then block again, indefinitely, until you send another command. Once you send another command, it will check the interval ONCE, and then lock up again. You need to rewrite your loop to check for bytes, read them if found, and do other work (like checking your time interval) if no bytes are available.

Next, your timing code is a mess. You only ever set currentMillis and previousMillis at the same time, so they will never be different. And you only ever check the times once when you first detect a "/delay" command.

Instead, refactor your logic. Only set previousMillis when you first detect the delay command, and then only compare if previousMillis to currentMillis if previousMillis is not 0:

```
if (req.indexOf("/delay") != -1)
{
    previousMillis = millis();
}

if (previousMillis != 0 && millis() - previousMillis >= interval) {
    digitalWrite(device1, LOW);
    previousMillis = 0;
}

```

(Also note that you were declaring a second, independent variable previousMillis inside your if statement, which only exists inside the curly braces for that if statement. Don't do that. Use the existing global variable you defined, as I show in my edited code.)

---
Tags: esp8266, web-server, millis
---


title: Wire Library Timer Usage

text:
# Question
Title: Wire Library Timer Usage
I would like to know if the Wire Library is using a Hardware Timer from the Arduino Mega 2560. And If so which Timer it is.

As I am using the Timer 1. After implementing the Wire Library I have some strange things happening that are probably due to the Timer.

Thanks a lot.

# Answer
> 0 votes
No, it's not.

It has its own timer called the "Bit Rate Generator Unit" which is controlled using the `TWBR` register. It takes its time source direct from the main CPU clock and divides it down.

---
Tags: timers, wire-library
---


# Question
Title: what is good practice around initializing variables
Should vars be initialed when declared or in setup fuction? Safe to assume compiler will initialze?

Boolean x; --- init to true/false here? Void setup() . . --- or init here? .

Void loop() If (x) --- x is unknown state if not initialized.

# Answer
Initializing a global is appropriate if you know in advance that it should always have a given value at startup. The compiler will generate a globals image in ROM that will be copied into RAM before any of your code is executed.

> Safe to assume compiler will initialze?

The compiler will initialize to 0, a global not specifically initialized by you. Let's take the case of your Boolean. '0' means 'false', right? So 'x' is pre-initialized to 'false'. But I, as the reader (or yourself, six months later) may not know whether you intended this to be initialized to 'false' (the default value) or forgot to initialize it. Specifying it to be 'false' may not have any different effect on the code, but it does inform me or your future self, that you *meant* it to be set 'false' at startup. Remember that your code communicates to people as well as to the compiler. Write it so you or I will not only be able to understand it, but won't be able to misunderstand it.

If you initialize it in setup(), the compiler generates code in setup() specifically to do that. If the setup() function needs to decide during startup, what the initial value of that variable should be, then this is the place to do it. Otherwise, the extra code just takes up space in Flash. It's not any more harmful than wasting those few extra bytes of code-space, but it doesn't accomplish anything more than letting the globals image do it.

Whatever you did or didn't do with 'x' at load time or in 'setup()', it will persist into 'loop()', so 'x's state isn't unknown when you get there. (If I misunderstood that part of your question, please edit it in your question.)
> 1 votes

# Answer
There is only one rule to follow, really:

**Never read a variable before writing a defined value to it.**

You don't need to write explicitly into a variable, because the C++ language distinguishes between two kinds of variables:

* *Static* variables are initialized to all zero bits, if no explicit initialization is done.
* *Automatic* variables are never automatically initialized. Their initial value is that of the memory cells they occupy, if no explicit initialization is done.

*Static* variables are defined outside any function or method, or with the keyword `static`.

*Automatic* variables are all others.

Example:

```
static int s1; // static, initialized to 0
int s2 = 42; // static, initialized to 42

void setup() {
    int a1; // automatic, has an unknown initial value
    static int s3; // static, initialized to 0
}

void your_function() {
    static int s4 = 23; // static, initialized to 23
    int a2 = 7; // automatic, initialized to 7 each time control flow comes here
}

```

All static variables are initialized exactly one time, before `main()` is called. Or in the case of Arduino, before `setup()` or any other method or function is called.

---

Oh, another quite important rule: Know, what you are doing, don't guess, be sure.

You might need to read the standard, or at least some good book.

If you use some rare feature, make it explicit or comment.

---

*Additional notes:*

The Arduino uses C++. This is a really different language than C.

You can think of `main()` as:

```
void main() {
    setup();
    for (;;) {
        loop();
    }
}

```
> 0 votes

---
Tags: programming
---


# Question
Title: Is it possible to exit a loop on the change of an input state?
I would like to exit a particular loop if the state of an input changes from LOW to HIGH. This is the current loop:

```
void brakeFade() {
pixels.clear();
pixels.setBrightness(255);
pixels.fill(16711680, 0, 0);

for(int i=255; i>=10; i-=1) {
  pixels.setBrightness(i);
  pixels.show();
  delay(5);
  }
for(int j=10; j<=255; j+=1) {
  pixels.setBrightness(j);
  pixels.show();
  delay(5);

```

} }

I need that loop to exit if

```
(digitalRead(brakeFeed) == LOW)

```

Changes to **HIGH** during the loop.

# Answer
figured it out:

```
void brakeFade2() {
pixels.clear();
pixels.setBrightness(255);
pixels.fill(16711680, 0, 0);

for(int i=255; i>=10; i-=1) {
  if (digitalRead(brakeFeed) == LOW){
  pixels.setBrightness(i);
  pixels.show();
  delay(5);
  }
  else {
    break;
  }
}
for(int j=10; j<=255; j+=1) {
  if (digitalRead(brakeFeed) == LOW){
  pixels.setBrightness(j);
  pixels.show();
  delay(5);
  }
  else {
    break;
  }
  }

```

}
> 1 votes

---
Tags: input, loop
---


title: Fast random booleans

text:
# Question
Title: Fast random booleans
I am looking for a way of generating booleans rapidly. For booleans, one usually uses `random(0,2);` but in my case I need about 250 booleans and calling random every time is slow.

So I thought about using all bits of a random number on the whole range as such:

```
randomSeed(100); // A seed to always keep the same sequence
long rdm = random(MIN,MAX);  // Generate a number in range MIN,MAX of type long
long mask = 1;
for(int i=0; i<32; i++){
    if((rdm>>i)&mask){
        //do something
    } else {
        //do something else
    }
}

```

But with this I have three questions:

1. What are MIN and MAX so that the LONG random uses all bits, with value ranging from -2,147,483,648 to 2,147,483,647 (arduino long type). I tried several MIN and MAX, also simply `random();` but without success.
2. Is it a valid approach? Do I expect each bit to be uniformly distributed? Should I use fewer bits, e.g. `random(0, 2^16);` for a "better" distribution?
3. Is there some seed known to be good or bad at this?

## My project

I am working on a device made of Neopixel LED strips. It is for a visual neuroscience experiment where each "pixel" is either ON or OFF. I need the speed to be able to reach high refresh rate (60-100Hz), with normal statistical distribution to avoid bias in neuron response analysis. With this approach, I can reach the desired speed but I'm concerned about the statistics. So I need a better understanding of `random()`'s behaviour to do it right!

# Answer
> 1 votes
1. I didn't try myself, but in the documentation it shows the MAX value is 2,147,483,647, which is 2^31-1. The MIN value I expect is -2^31, thus -2,148.483.648. Wondering what you mean by 'without success'.
2. Yes this is a valid approach. A 'perfect' random generator should be able to generate all values with an equal distribution. Since the values are within \[-2^31, 2^31-1\] this means all values within a 32 bit value is used, which automatically means all bits are also evenly distributed. So you can pick individual bits (as long as you use the entire MIN/MAX range).
3. In principle all seeds are good, as long as they are random. In the documentation it is advised to take an unconnected analog pin value. If you don't have one unconnected, you can use e.g. the `millis` function.

# Answer
> 0 votes
The `random()` function returns a number between 0 and `RANDOM_MAX` (0x7FFFFFFF). The `random(min, max)` function takes the value from `random()` and manipulates it to fit into the specified range (calculate the offset difference, modulus the random value by that difference, then add the lower offset).

That means that the widest range you can get is from `random()` directly, whilch is the same as `random(0, RANDOM_MAX)`. However that is only ever going to be 31 bits, so your most significant bit will *always* be zero.

That's not what you want.

The best you can do to get 32 bits of random data is to take two random 31 bit values and combine them. Maybe left shifting one value by one bit and the XORing them together would be enough:

```
uint32_t rand1 = random();
uint32_t rand2 = random();
uint32_t fullrand = (rand1 << 1) ^ rand2;

```

Alternatively just working with 31 bits instead of 32 may be enough for your needs and would be faster than generating two numbers and combining them just to fill that one extra bit.

---
Tags: programming, mathematics
---


# Question
Title: How does supply voltage affect `analogRead()` on AVR-based microcontrollers?
I'm using an ATmega328P based Arduino to prototype reading a TMP36 temperature sensor. I will eventually move this to an ATtiny85 based board with a battery supply. Both the TMP36 and ATtiny85 have a Vcc range from 2.7V to 5.5V so a battery that starts at say 4.5V and slowly drops to 2.7V should not be out of range.

I am expecting to read temperatures in the range -5°C to +30°C which should correspond to a TMP36 output between 0.5 to 0.9V. I am getting 0.74V at around 23°C so this sort of range seems plausible.

The TMP36 outputs 10 mV/°C regardless of Vcc (within 2.7-5.5v). But I suspect the AnalogRead() value will be scaled by the supply voltage and so will slowly change as the battery drains. Is this correct?

Do I need to include an external voltage-regulator / voltage-reference device to supply some fixed voltage (e.g. 2.5V) to AREF?

---

Solution

Following Edgar Bonet's Answer I successfully enabled the internal voltage reference for the ADC.

Initially I added a 100nF bypass capacitor to AREF and tried

```
#define REFS1 7
#define REFS0 6
#define REFS2 4

```

...

```
//ADMUX = (_BV(REFS1) | _BV(REFS2)); // 2.56V ATtiny85   datasheet §17.3 pp134
ADMUX = (_BV(REFS1) | _BV(REFS0)); // 1.1V  ATmega328P datasheet §23.9 pp217

```

but didn't get it to work, my code had no effect on values from `analogRead()`. So after a bit of further reading I instead used

```
analogReference(INTERNAL);

```

Which worked.

# Answer
The ADC measures a *voltage ratio*. The conversion result is the rounded value of 1024×V/Vref, where V is the voltage at the input and Vref is the voltage reference.

In the default Arduino configuration, the reference is connected to Vcc. This will not fit your use case, as the voltage you want to read does not vary proportionately to Vcc. You could use an external reference. However, the ATtiny85 has two internal voltage references at 1.1 and 2.56 V. Either of these may be well suited for you application, which should save you having to add an extra part.

See the chapter on the ADC in the datasheet for details on how to select the voltage reference.
> 2 votes

---
Tags: analogread
---


# Question
Title: How to produce rolling count per minute?
I have a counter attached to ISR:

```
void ISR_impulse() {
  CNT++;
}

```

and I want to calculate rolling count per minute with arbitrary update rate.

However I can only get it to update every minute:

```
void loop() {
  if (t - t0 > 60000) {
    CPM = CNT - CNT0;
    t0 = t;
    CNT0 = CNT;
  }

  t = millis();
  delay(100);
}

```

Requirement:

* Rolling count with a window of 1 minute, and arbitrary update rate like 1 second ?
* CPU has other tasks to do, which might take a significant amount of time.
* SAMD21 has pulse period measurement in TC, but I have no idea how to set it up.

Partial solution one by edgar bonet:

```
  static uint8_t buf[60];
  static uint8_t idx;
  static uint32_t t0;
  static uint16_t CNT0;
  static uint8_t cpm;

  if (millis() - t0 >= 1000) {
    t0 = millis();
    uint16_t cps = CNT - CNT0;
    CNT0 = CNT;
    cpm += cps - buf[idx];
    buf[idx] = cps;
    if (++idx >= 60) idx = 0;
  }

```

How ever this only works if the loop code finishes in less than 1ms.

# Answer
If you want to update every second a one minute running average, you have no choice but store in memory the counts you got the previous 60 seconds. You store them in a ring buffer, so that every new reading replaces the oldest one. Then, every second:

* you add to the CPM count the number of counts you got this second
* you subtract the number of counts you got on the second that just got out of the sliding window.

I would implement that logic this way:

```
const uint32_t ONE_SECOND = 1000;

uint16_t counts_per_minute;
uint16_t previous_counts[60];
size_t counts_pos;

void loop() {
    static uint32_t previous_second;
    if (millis() - previous_second >= ONE_SECOND) {
        previous_second += ONE_SECOND;
        noInterrupts();
        uint16_t CNT_copy = CNT;
        interrupts();
        static uint16_t CNT_previous;
        uint16_t second_count = CNT_copy - CNT_previous;
        CNT_previous = CNT_copy;
        counts_per_minute += second_count - previous_counts[counts_pos];
        previous_counts[counts_pos] = second_count;
        if (++counts_pos >= 60) counts_pos = 0;
    }
}

```

Note that:

* The timing variable is updated with `previous_second += ONE_SECOND` rather than `previous_second = now` in order to avoid the accumulation of small timing errors.
* The counter that is updated in the ISR has to be read only once, with interrupts disabled. Otherwise the interrupt may change it while you are in the middle of reading it.
> 2 votes

# Answer
You need a First-In, First-Out buffer (FIFO) so that the oldest data drops off to make room for the newest. This is usually done with a circular buffer - an array whose beginning / end point change as data is added. (For comparison, the simplistic way is an array whose contents gets moved down (toward i = 0) each time you need to add a datum. But moving data is slow, so remembering where the oldest entry is, replacing it with the newest one, and updating the remembered oldest-data location gives a huge permormance improvement.

Secondly, you need to define how responsive your counter needs to be - how many updates per minute you'll need. That's the number of elements you need in the array.

Evaluating the immediately-passed minute's count is as simple as summing the array, which can be done without caring where the begin/end point is. Sum from 0 to N-1; the result will be the same.
> 0 votes

---
Tags: arduino-uno
---


# Question
Title: Having problems with running two 74HC595 as a single 16bit shift register
I'm using two of these together to create a single 16bit register which will give me access to 16 outputs. I have gotten them to work but not exactly how I imagined them to work. The code written is for a 18650 cell charger/discharger. The first 6 bits (0-5) of the shift register will be connected to 6 NPNs which will turn on or off each of their tp4056s connected in series. The next 6 bits (5-11) will be connected to 6 different constant current loads. The user selects if they want to charge or discharge their cell and depending on the mode, that particular cell's charger or current sink is turned on (but both not on the same time). In reality, I have to firstly shift 6 bits manually by selecting a mode and then pressing select for all 6 cells in the register for it to show something and even after that it misses bits randomly. btw last 4 bits (12-15) will also get used in the final product. For experimenting, I've connected LEDs to all outputs.

```
#include <Arduino.h>
#include <LiquidCrystal_I2C.h>
#include <Encoder.h>

//initalisation
LiquidCrystal_I2C lcd(0x27, 20, 4);
Encoder encoder(2, 3);

//software constants
const int numOfCells = 6;
const int analogInput[numOfCells] = {A0, A1, A2, A3, A6, A7};
const float arduinoPowerLine = 4.80;
const long interval = 60000; //60 seconds
const char* functions [2] = {"CHARGE   ", "DISCHARGE"}; //mode select array
const int dataPin  = 12;//DS - pin 9
const int latchPin = 11;//ST_CP --pin12
const int clockPin = 8;//SH_CP --pin11

//Encoder setup
long oldPostion = -999;
long newPostion = 0;
long prevPostion;

//making battery arrays and setting their default flags
double batteryVoltage[numOfCells];
bool noBatteryFlag[numOfCells] = {LOW, LOW, LOW, LOW, LOW, LOW};
float minimum = 3.00; //Cutoff voltage
float capacity[numOfCells];

//mode variables
int modeState[numOfCells];
int confirmedModeState[numOfCells];

//button setup
int inputPin = 5;
int inputState;
int lastInputState = LOW;
int inputFlag = LOW;

//debounce timer
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 50;

//lcd varuables
int currentCell = -1;

//Cell timers
unsigned long prevMillis[numOfCells];
int minute[numOfCells];
unsigned long currentMillis;

//shift resister variables
word outputs = 0B0000000000000000;

void updateShiftRegister(word bits){//takes bits from the resolvemode function and sets them appropriately
  byte resisterOne  = lowByte(outputs);//right most byte
  byte resisterTwo = highByte(outputs);//left most byte
  digitalWrite(latchPin, LOW);
  shiftOut(dataPin, clockPin, MSBFIRST, resisterTwo);
  shiftOut(dataPin, clockPin, MSBFIRST, resisterOne);
  digitalWrite(latchPin, HIGH);
}
void setup() {
  Serial.begin(9600);
  lcd.init();
  lcd.backlight();
  pinMode(inputPin, INPUT_PULLUP);
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin,  OUTPUT);
  pinMode(clockPin, OUTPUT);
  updateShiftRegister(outputs);//Resets all shift resister output to LOW
}
void BatteryVoltage(){//reading each cells and converting the adc value into voltage
  for (int i = 0; i < numOfCells; i++){
    int reading = analogRead(analogInput[i]);
    batteryVoltage[i] = (reading * arduinoPowerLine) / 1023;
    //flagging stuff
    if (batteryVoltage[i] <= 0.50) {//checking if a battery is inserted in the holder
    noBatteryFlag[i] = HIGH;
    }else{
      noBatteryFlag[i] = LOW;
    }
  }
}
void ButtonDebounce(){//checking input state and flaggint button
  int reading = digitalRead(inputPin);
  if (reading != lastInputState){
    lastInputState = millis();
  }
  if ((millis() - lastInputState > debounceDelay)){//debouncing button
    if (reading != inputState){
      inputState = reading;
      if (inputState == HIGH) {
        inputFlag = HIGH;
      }
    }
  }
  lastInputState = reading;
}
void ResolveFlags(){
   if (inputFlag == HIGH){ //incrementing currentscreen
       if (currentCell == numOfCells - 1){ //if counter at its limit ,it wraps back to the start
        currentCell = 0;
      } else {
        currentCell++;
      }
      confirmedModeState[currentCell] = modeState[currentCell]; //mode selected in stored
      lcd.clear();//clears lab every time button is pressed
        inputFlag = LOW;
  }
}
void BatteryTimeKeeper(){//keeping track of battery time while it is discharging
for (int i = 0; i < numOfCells; i++){
  if (currentMillis - prevMillis[i] > interval){
    if (noBatteryFlag[i] == LOW){//if a battery is in the holder
      if (batteryVoltage[i] > minimum){//and if it is greater then 3v, it can be discharged
   minute[i]++;
   prevMillis[i] = currentMillis;
  }
  if (batteryVoltage[i] <= minimum){
    capacity[i] = (minute[i] / 60) * 500; //total time taken divided by 500mA (constant current load)
    minute[i] = 0;
    }
  }
}
    if (noBatteryFlag[i] == HIGH){//if a battery is removed, its timer is reset back to 0
      minute[i] = 0;
    }
  }
}
void EncoderFunctionNavigator(){//tracks encoder
  newPostion = encoder.read();
  if (newPostion != oldPostion){
    oldPostion = newPostion;
  }
  if(prevPostion < newPostion){
    modeState[currentCell]++;
  } else if(prevPostion > newPostion){
    modeState[currentCell]--;
  }
  if (modeState[currentCell] == 2){ //wraps back selection mode
    modeState[currentCell] = 0;
  } else if (modeState[currentCell] < 0){
    modeState[currentCell] = 1;
  }
}
void ResolveMode(){//sets shift resister output on or off depending on the mode selected
  for (int i = 0; i < numOfCells; i++){
    if (confirmedModeState[i] == 0){
      bitWrite(outputs, i, HIGH) && bitWrite(outputs, i+6, LOW);
    } else if (confirmedModeState[i] == 1){
      bitWrite(outputs, i, LOW) && bitWrite(outputs, i+6, HIGH);
    }
    updateShiftRegister(outputs);
  }
}
void PrintScreen(){//printing all the info in lcd
  lcd.home();
  int cellCounter = currentCell + 1; //this is here because I have ocd
  char buffer[25];
  sprintf(buffer, "Cell#:%d    %s", cellCounter, functions[modeState[currentCell]]);
  lcd.print(buffer);
  lcd.setCursor(0, 1);
  lcd.print("VOL:");
  lcd.setCursor(4, 1);
  lcd.print(batteryVoltage[currentCell]);
  lcd.setCursor(0, 2);
  lcd.print("Cap:");
  lcd.setCursor(4, 2);
  lcd.print(capacity[currentCell]);
}
void loop() {
 currentMillis = millis(); //main currentmillis variable
 BatteryVoltage();
 BatteryTimeKeeper();
 ButtonDebounce();
 EncoderFunctionNavigator();
 ResolveFlags();
 PrintScreen();
 ResolveMode();
 prevPostion = newPostion; //records the last postion of encoder
}

```

# Answer
To put the comments into an answer:

You are controlling the shift registers in this function

```
void ResolveMode(){//sets shift resister output on or off depending on the mode selected
  for (int i = 0; i < numOfCells; i++){
    if (confirmedModeState[i] == 0){
      bitWrite(outputs, i, HIGH) && bitWrite(outputs, i+6, LOW);
    } else if (confirmedModeState[i] == 1){
      bitWrite(outputs, i, LOW) && bitWrite(outputs, i+6, HIGH);
    }
    updateShiftRegister(outputs);
  }
}

```

Since the `updateShiftRegister()` call is inside the for loop, you are updating the shift registers for every bit, that you set. I guess this is the point, where you get your weird behavior. You don't need to update for every bit. Instead change all needed bits inside the `outputs` variable, and then at the end of `ResolveMode()` you can update the registers with all data at once.

So just move `updateShiftRegister(outputs);` one line down to outside of the for loop.
> 1 votes

---
Tags: arduino-nano, shift-register
---


# Question
Title: 3pin (GND, 12V, tach) 12v FAN control using PWM
I know there are fans out there that have a dedicated PWM input, but I like to know if I can PWM control a fan that does not have such a dedicated PWM input. So...

If I have a 3 pin 12v fan like the Noctua NF-A20 with connections:

* GND
* 12 V
* tach out (RPM measurement)

Can I control its speed by PWM on the 12V supply voltage (using a MOSFET most probably)? Would the tach out still work?

# Answer
Yes, and yes.

You have to modulate the +12V rather than GND because the output is referenced to ground. That means you need to use the classic N+P channel FET arrangement:

simulate this circuit – Schematic created using CircuitLab
> 2 votes

---
Tags: pwm
---


# Question
Title: What is the maximum "wattage" can be pushed into an ATMega328 ADC pins?
I was doing some **Ohm's Law** calculations to calculate the voltage output from a 2-resistor voltage divider, the input will be with a maximum of 12 volts, I want the ATMega328 to measure that voltage, so I simply thought of putting two resistors in series with values of 330 ohms and 220 ohms like this:

simulate this circuit – Schematic created using CircuitLab

Theoretically on paper the maximum voltage outputting from the node going to the ATMega328 is ~4.8V, but I want a special safety feature, I want to put in mind that at **anytime** the ground connection can be hung open (to simulate a lose breadboard connection, bad soldering joint etc...) now based upon my understanding if there is no ground connection, the voltage going to the Arduino will be 12V which is a killer, as after looking on the ATMMega328 datasheet it states that

> 28.1 Absolute Maximum Ratings. Voltage on any pin except RESET with respect to ground =\> VCC + 0.5

The current will be limited by the 330ohm resistor to only 36mA which I think is a lot, I thought of doubling the resistors values to 330000 and 220000 by that the current will be limited to only 36uA. Again based upon my understanding there is still 12V going to the Arduino but wouldn't it directly drop if the ground connection was cut off ? That's why I ask what is the maximum input **power** to an Arduino?

# Answer
This is actually a special case that is undocumented, and in fact not as simple as you would at first think.

The input port itself is not actually what is in question here. Instead every IO pin on the Arduino, be it set to INPUT or OUTPUT, has a set of ESD protection diodes on them. These look like this:

simulate this circuit – Schematic created using CircuitLab

The "IO MODULE" when in INPUT mode can pretty much be ignored, since it is a very high impedance. Just like a (roughly) 10MΩ resistor to ground. Very very little current will flow that way.

D2 is also reverse biased so that direction can be ignored.

So the current will want to flow through D1 to the VCC rail (+5V). The diodes have approximately a 600mV forward voltage (which is where the VCC + *0.5* comes from).

So we can recalculate, given those parameters, what the current flowing through the diode will be to the 5V rail:

* Voltage difference = 12V - 5V - 0.5V = 6.5V
* Current = V/R = 6.5/330 = 19.7mA

The recommended maximum (from what I can gather) is only 1mA. You have 20x that.

So you will need at least 20x higher resistances. 10kΩ in the upper half and 6.8kΩ in the bottom half. That will give you 4.85V on the output at 12V and limit you to 0.65mA in a failure situation.

It also gives you an output impedance of a little over 4kΩ which is below the recommended maximum of 10kΩ for the ADC input.

You can further protect your input by adding a 5V zener diode and small series resistor on the ADC pin so if the voltage goes above 5V it clamps it and protects the pin.

simulate this circuit
> 2 votes

---
Tags: current, adc
---


# Question
Title: Arduino exercise that i have no idea how to do
The messages received by the Arduino take the form: $ Ba, Pb, Rc #

Where $ represents the beginning of the message, # represents m, and B, P, and R are characters representing B button, P period and R repetition.

1. \`a 'designates the button to be read, which can be 1, 2 or 3.
2. \`b 'designates the time (in seconds) that the button should be expected to be pressed.
3. \`c 'designates the number of times the button is expected to be pressed during the indicated period.

For example, with the message: $ B2, P4, R2 # you want to know if button 2 has been pressed twice for four seconds. If condition is verified, then the Arduino must send the message $ MSG, TRUE # where MSG represents the message received without the start and m message characters. Otherwise, you must send the message $ MSG, FALSE #.

Incoming messages must respect the format presented. If not, the condition is not checked and the message $ NOK, MSG, KON # must be sent as a response.

I have no idea how to do this since im new to arduino

# Answer
To begin, forget the Arduino for a moment and assume the task of determining true or false from $....# message. Think about what you would have to do, step by step, to accomplish this. (e.g.: Read the buttons; Record the time and the button states. Is there a message from the Serial port beginning with '$'? Then read the rest of the message. etc.) Then, for each of those steps, do the same thing again: write down the smaller steps to accomplish what that step requires. Do that until you can't break it down any further.

Those small steps should each look like something you could do in C++ code (sometimes called "Arduino" code, but it's really C++). Start replacing each English (or your language) steps with the C++ equivalent. Do this until all of the human-language steps are written in C++.

There will inevitably be mistakes. Fix one or a few at a time. When you're stuck, ask here, something like "Here is my (well formatted) code. I tried \[this\]. I expected to see \[that\]. But what happened instead was \[something else\]. How can I fix it?"; or: "I am getting this error message \[with its complete text including any line numbers, please\] from the compiler. What does it mean, and how could I have found that out on my own?"

Small steps....
> 2 votes

---
Tags: esp32
---


# Question
Title: TinyGPS doesn't give longitude latitude and other data
I'm trying to get GPS coordinates using TinyGPS. But it keeps printing \********* for the data fields. Any idea on how to get this working?. Here is what the serial monitor looks like.

Here is my code

```
#include <SoftwareSerial.h>

#include <TinyGPS.h>

/* This sample code demonstrates the normal use of a TinyGPS object.
   It requires the use of SoftwareSerial, and assumes that you have a
   4800-baud serial GPS device hooked up on pins 4(rx) and 3(tx).
*/

TinyGPS gps;
SoftwareSerial ss(1, 0);

static void smartdelay(unsigned long ms);
static void print_float(float val, float invalid, int len, int prec);
static void print_int(unsigned long val, unsigned long invalid, int len);
static void print_date(TinyGPS &gps);
static void print_str(const char *str, int len);

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

  Serial.print("Testing TinyGPS library v. "); Serial.println(TinyGPS::library_version());
  Serial.println("by Mikal Hart");
  Serial.println();
  Serial.println("Sats HDOP Latitude  Longitude  Fix  Date       Time     Date Alt    Course Speed Card  Distance Course Card  Chars Sentences Checksum");
  Serial.println("          (deg)     (deg)      Age                      Age  (m)    --- from GPS ----  ---- to London  ----  RX    RX        Fail");
  Serial.println("-------------------------------------------------------------------------------------------------------------------------------------");

  ss.begin(4800);
}

void loop()
{
  float flat, flon;
  unsigned long age, date, time, chars = 0;
  unsigned short sentences = 0, failed = 0;
  static const double LONDON_LAT = 51.508131, LONDON_LON = -0.128002;

  print_int(gps.satellites(), TinyGPS::GPS_INVALID_SATELLITES, 5);
  print_int(gps.hdop(), TinyGPS::GPS_INVALID_HDOP, 5);
  gps.f_get_position(&flat, &flon, &age);
  print_float(flat, TinyGPS::GPS_INVALID_F_ANGLE, 10, 6);
  print_float(flon, TinyGPS::GPS_INVALID_F_ANGLE, 11, 6);
  print_int(age, TinyGPS::GPS_INVALID_AGE, 5);
  print_date(gps);
  print_float(gps.f_altitude(), TinyGPS::GPS_INVALID_F_ALTITUDE, 7, 2);
  print_float(gps.f_course(), TinyGPS::GPS_INVALID_F_ANGLE, 7, 2);
  print_float(gps.f_speed_kmph(), TinyGPS::GPS_INVALID_F_SPEED, 6, 2);
  print_str(gps.f_course() == TinyGPS::GPS_INVALID_F_ANGLE ? "*** " : TinyGPS::cardinal(gps.f_course()), 6);
  print_int(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0xFFFFFFFF : (unsigned long)TinyGPS::distance_between(flat, flon, LONDON_LAT, LONDON_LON) / 1000, 0xFFFFFFFF, 9);
  print_float(flat == TinyGPS::GPS_INVALID_F_ANGLE ? TinyGPS::GPS_INVALID_F_ANGLE : TinyGPS::course_to(flat, flon, LONDON_LAT, LONDON_LON), TinyGPS::GPS_INVALID_F_ANGLE, 7, 2);
  print_str(flat == TinyGPS::GPS_INVALID_F_ANGLE ? "*** " : TinyGPS::cardinal(TinyGPS::course_to(flat, flon, LONDON_LAT, LONDON_LON)), 6);

  gps.stats(&chars, &sentences, &failed);
  print_int(chars, 0xFFFFFFFF, 6);
  print_int(sentences, 0xFFFFFFFF, 10);
  print_int(failed, 0xFFFFFFFF, 9);
  Serial.println();

  smartdelay(1000);
}

static void smartdelay(unsigned long ms)
{
  unsigned long start = millis();
  do
  {
    while (ss.available())
      gps.encode(ss.read());
  } while (millis() - start < ms);
}

static void print_float(float val, float invalid, int len, int prec)
{
  if (val == invalid)
  {
    while (len-- > 1)
      Serial.print('*');
    Serial.print(' ');
  }
  else
  {
    Serial.print(val, prec);
    int vi = abs((int)val);
    int flen = prec + (val < 0.0 ? 2 : 1); // . and -
    flen += vi >= 1000 ? 4 : vi >= 100 ? 3 : vi >= 10 ? 2 : 1;
    for (int i=flen; i<len; ++i)
      Serial.print(' ');
  }
  smartdelay(0);
}

static void print_int(unsigned long val, unsigned long invalid, int len)
{
  char sz[32];
  if (val == invalid)
    strcpy(sz, "*******");
  else
    sprintf(sz, "%ld", val);
  sz[len] = 0;
  for (int i=strlen(sz); i<len; ++i)
    sz[i] = ' ';
  if (len > 0)
    sz[len-1] = ' ';
  Serial.print(sz);
  smartdelay(0);
}

static void print_date(TinyGPS &gps)
{
  int year;
  byte month, day, hour, minute, second, hundredths;
  unsigned long age;
  gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age);
  if (age == TinyGPS::GPS_INVALID_AGE)
    Serial.print("********** ******** ");
  else
  {
    char sz[32];
    sprintf(sz, "%02d/%02d/%02d %02d:%02d:%02d ",
        month, day, year, hour, minute, second);
    Serial.print(sz);
  }
  print_int(age, TinyGPS::GPS_INVALID_AGE, 5);
  smartdelay(0);
}

static void print_str(const char *str, int len)
{
  int slen = strlen(str);
  for (int i=0; i<len; ++i)
    Serial.print(i<slen ? str[i] : ' ');
  smartdelay(0);
}

```

# Answer
> 1 votes
```
#include <SoftwareSerial.h>
#include <TinyGPS++.h>
#include <SPI.h>

float lattitude,longitude; // create variable for latitude and longitude object
SoftwareSerial gpsSerial(8,9);//rx,tx
TinyGPSPlus gps;// create gps object

void setup(){
    Serial.begin(9600); // connect serial
    gpsSerial.begin(9600); // connect gps sensor
    delay(1000);
}

void loop(){

  while(1)
  {
   while (gpsSerial.available() > 0)
   { gps.encode(gpsSerial.read()); }

      if (gps.location.isUpdated())
      {
       lattitude=gps.location.lat();
       longitude=gps.location.lng();
       break;
      }

 }
   Serial.print("LATTITUDE="); Serial.println(lattitude,6);
   Serial.print("LONGITUDE="); Serial.println(longitude,6);
   delay(1000);
}

```

I managed to get it working using the following library `TinyGPS++.h`

# Answer
> 0 votes
From the description: It requires the use of SoftwareSerial, and assumes that you have a 4800-baud serial GPS device hooked up on pins 4(rx) and 3(tx). \*/ But you are using Pin0 and Pin 1, as shown in your code: SoftwareSerial ss(1, 0); given that pin0 and pin one are hard Tx and Rx may create problems.

to check if the GPS is receiving anything use the BareMinimum sketch: void setup() { // put your setup code here, to run once: } void loop() { // put your main code here, to run repeatedly: }

//Remember that Tx connects to Tx and Rx to Rx

that will show the NMEA string in the serial monitor.
(you can see a video about it, search for:"GPS Module with Arduino- Ublox NEO-6M"

Note: in TinyGPS the Rx connects to Tx and Tx connects to Rx...

In case you use Softwareserial.h with Arduino Mega you may have issues as not all pins can Rx (receive)... please check: https://www.arduino.cc/en/Reference/SoftwareSerial

for NEO-6M the seed should be 9600baud, not 4800 as shown in the sketch, please check page 11 on:

https://www.u-blox.com/sites/default/files/products/documents/NEO-6\_DataSheet\_%28GPS.G6-HW-09005%29.pdf

Also change Serial.begin(115200); to 9600 so they are in sync.

---
Tags: arduino-uno, gps, tinygps
---


# Question
Title: NodeMCU V3 + SD Card with Arduino IDE Not working
I am trying to connect CATALEX MicroSD Card adaptor to new NodeMCU V3 and PIN configuration are as below,

```
NodeMCU  ---------> SD Card
GPIO13 (D7) ------> MOSI
GPIO12 (D6) ------> MISO
GPIO14 (D5) ------> SCK
GPIO15 (D8) ------> CS
VCC (3.3V) -------> VCC
GND --------------> GND

```

Tested above setup with QuickStart program from SdFat library in Arduino IDE. But it gives error output as below,

```
SPI pins:
MISO: 12
MOSI: 13
SCK:  14
SS:   15

SD chip select is the key hardware option.
Common values are:
Arduino Ethernet shield, pin 4
Sparkfun SD shield, pin 8
Adafruit SD shields and modules, pin 10

Enter the chip select pin number: 15

Disabling SPI device on pin 10
Can't access SD card. Do not reformat.
No card, wrong chip select pin, or SPI problem?
SD errorCode: 0X20,0XFF

SD initialization failed.
Do not reformat the card!
Is the card correctly inserted?
Is chipSelect set to the correct value?
Does another SPI device need to be disabled?
Is there a wiring/soldering problem?

errorCode: 0x20, errorData: 0xff

```

> chipSelect is 15.

Also, I am using SanDisk 16GB Micro SDHC class 4 Memory Card.

I have tried googling with the error but did not find solution. Please help me.

# Answer
SD cards work on 3.3 V, so the adapter has 5 V to 3.3 conversion for power and signal, to connect SD card reader to a 5 V MCU. You can't connect this SD card adapter to an 3.3 V MCU like the esp8266.
> 0 votes

# Answer
If you are giving power to nodemcu through USB cable. SD card VCC can be connected to the VIN pin of nodemcu ESP8266. I faced the same problem

**NodeMCU V3 + SD Card with Arduino IDE Not working**

but after connecting VCC of SD Card to VIN pin of nodemcu. it worked.

Thanks for the helping me Mr. Juraj
> 1 votes

---
Tags: arduino-ide, sd-card, nodemcu
---


# Question
Title: Can I force a function to live in the boot sector without overwriting the bootloader?
Not for any practical purpose but just out of curiosity, I want to abuse the flash memory and write it dynamically at run-time. This is, in a sense, what the bootloader does. If I understand it, the only way to modify flash is to do so from instructions written to the boot sector. Is it possible to stick a simple function in there that writes to flash memory, and call it from running code? If so, how do I put it there? I have no issue with calling functions from function pointers, so I don't think I'll have an issue actually calling the function once I get there, but I need to know how to stick into flash in the first place.

# Answer
The Optiboot version 8 has a `do_spm` function which can be called from application. The Optiboot repository contains an example for the use of this function.

SPM is the AVR CPU instruction to write to flash memory. The Optiboot wraps this in a function. A pointer to this function is put in a 'vector table' at the beginning of the bootloader. The first pointer jumps to `main`, the second pointer jumps to `do_spm`. The optiboot.h then has the function as (version for small Optiboot)

```
typedef void (*do_spm_t)(uint16_t address, uint8_t command, uint16_t data);
const do_spm_t do_spm = (do_spm_t)((FLASHEND-511+2)>>1)

```

I made an enhancement of this, a copy\_flash\_pages function with reset option to bootload an AVR from its own flash. It is added as third entry in the 'vectors table' of Optiboot. It is used in my ArduinoOTA library for AVR MCUs.

```
typedef void (*copy_flash_pages_t)(uint32_t dest, uint32_t src, uint16_t page_count, uint8_t reset);
const copy_flash_pages_t copy_flash_pages = (copy_flash_pages_t)((FLASHEND-1023+4)>>1);

```
> 8 votes

---
Tags: bootloader, flash
---


# Question
Title: How to connect HC-06 with HC-08 with the HC-06 as master and HC-08 as slave?
How do you connect HC-06 with HC-08 with the HC-06 as master and HC-08 as slave? I will try it using 2 Arduino Unos.

# Answer
> 0 votes
You cannot. The HC-06 is a slave only device.

So you need to use a device as master, that is actually capable of it. I don't know, if the HC-08 can do it. Another typical bluetooth master device is the HC-05. Just like HC-06, but can also be a master.

---
Tags: arduino-uno, bluetooth
---


# Question
Title: Arduino Uno R3 cannot detect GPRS Shield SIM900
I am new to Arduino which I got only this week for my project which sends sms from my windows application.

I have **Arduino Uno R3** and **GPRS Shield (Simcom) Sim900 (S2-1040S-Z0912)**

I am currently following this guide \> https://educ8s.tv/arduino-gsm-shield/

As of the moment I have problem connecting the Sim900 to Arduino (I think Arduino cannot detect Sim900). The Arduino is working properly as my PC detected it. Also I confirm that the SIM900 is working properly as I can call the Sim inside and it is ringing (also the led on the device is blinking almost every 3 secs or so)

I found this, but I'm planning to use USB powered only as I only need the SMS feature so I am stacking the SIM900 on top of the Arduino. How to communicate the Arduino board with SIM900?

I am using this library http://www.tinyosshop.com/datasheet/GSM\_GPRS\_GPS\_Shield\_GSMSHIELD.rar

and below is the sketch:

```
#include "SIM900.h"
#include <SoftwareSerial.h>
#include "sms.h"
SMSGSM sms;

int numdata;
boolean started=false;
char smsbuffer[160];
char n[20];

char sms_position;
char phone_number[20];
char sms_text[100];
int i;

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

    if (gsm.begin(9600))
    {
        Serial.println("\nstatus=READY");
        started=true;
    }
    else
        Serial.println("\nstatus=IDLE");

    if(started)
    {
        if (sms.SendSMS("214", "?15001"))
        {
          Serial.println("\nSMS sent OK.");
        }
        else
        {
          Serial.println("\nError sending SMS.");
        }
    }
};

void loop()
{
    if(started)
    {
        sms_position=sms.IsSMSPresent(SMS_UNREAD);
        if (sms_position)
        {
            Serial.print("SMS postion:");
            Serial.println(sms_position,DEC);
            sms.GetSMS(sms_position, phone_number, sms_text, 100);
            Serial.println(phone_number);
            Serial.println(sms_text);
        }
        delay(2000);
    }
};

```

and here is the output

```
Trying to force the baud-rate to 9600

1200
2400
4800
9600
19200
38400
57600
115200
ERROR: SIM900 doesn't answer. Check power and serial pins in GSM.cpp

status=IDLE

```

What I have tried so far:

I tried the sketch with `SoftwareSerial mySerial(7, 8);` and `SoftwareSerial mySerial(9, 10)` which i found on other tutorials but didn't work.

I tried modifying `GSM.cpp` and modify the value of `_GSM_TXPIN_` and `_GSM_RXPIN_` to 7, 8 and 9, 10 but didn't work.

Found that the pin on my Arduino is RX=0 and TX=1, and SIM900 is TX=0 and RX=1, tried the SoftwareSerial code above but with 0, 1 and GSM.cpp with 0, 1 but still not working.

I am currently still trying every other sketch i find on the internet but nothing works.

EDIT: This is the link for the module i bought https://www.lazada.com.ph/products/sim900-gsm-shield-i267689740-s379728457.html?mp=1

I cant find the link for the datasheet of this specific module so I will try to include the picture of the module

# Answer
After many trials, I found the solution to my problem, thanks to @Majenko for mentioning the jumpers.

I am still stacking the SIM900 module on top of Arduino.

Switching the jumpers from `D1` and `D0` to `D8` and `D7` solved the problem (see green square on the pic)

I don't know why it needs to be on `D8` and `D7` since on board it says TX=0 and RX=1 and vise-versa for Arduino

Then used the below sketch from this tutorial \> https://lastminuteengineers.com/sim900-gsm-shield-arduino-tutorial/

```
#include <SoftwareSerial.h>

//Create software serial object to communicate with SIM900
SoftwareSerial mySerial(7, 8); //SIM900 Tx & Rx is connected to Arduino #7 & #8

void setup()
{
  //Begin serial communication with Arduino and Arduino IDE (Serial Monitor)
  Serial.begin(9600);

  //Begin serial communication with Arduino and SIM900
  mySerial.begin(9600);

  Serial.println("Initializing...");
  delay(1000);

  mySerial.println("AT"); //Handshaking with SIM900
  updateSerial();
  mySerial.println("AT+CSQ"); //Signal quality test, value range is 0-31 , 31 is the best
  updateSerial();
  mySerial.println("AT+CCID"); //Read SIM information to confirm whether the SIM is plugged
  updateSerial();
  mySerial.println("AT+CREG?"); //Check whether it has registered in the network
  updateSerial();
}

void loop()
{
  updateSerial();
}

void updateSerial()
{
  delay(500);
  while (Serial.available())
  {
    mySerial.write(Serial.read());//Forward what Serial received to Software Serial Port
  }
  while(mySerial.available())
  {
    Serial.write(mySerial.read());//Forward what Software Serial received to Serial Port
  }
}

```

With this, it displays correct output on serial monitor based on the tutorial and I can confirm that its working as well on my windows form application as it can send sms from the application.
> 0 votes

---
Tags: arduino-uno, gsm
---


# Question
Title: Error while inputting EEPROM.read() and EEPROM.write()
I am trying to store data in ATmega328 (Arduino Uno) using the following code using tinkercad:

```
#include <EEPROM.h>

void setup() {
  int addr, data=1;
  Serial.begin(9600);
  for (addr=0; addr<1023; addr++) {
    EEPROM.write(addr, data);
  }
  for (addr=0; addr<1023 ; addr++) {
    Serial.print(EEPROM.read(addr), DEC);
  }
}

```

When I simulate the code in the tinkercad, then i get the following error:

```
In function `main':
43: undefined reference to `loop'
 error: ld returned 1 exit status

```

Please help me where is the error in my code. I am not able to understand the error source.

# Answer
> 4 votes
Have you looked at any Arduino IDE example programs?

They all have a `setup()` and `loop()` function.

Apparently, Tinkercad is missing the `loop()` function in your code.

You can solve the issue by adding an empty `void loop() { }` after your `void setup() { ... }` code.

---
Tags: arduino-uno, arduino-ide, atmega328, eeprom
---


# Question
Title: Speed control of BLDC with an integrated controller (Hall out, PWM in)
I am aiming at precise speed control of this BLDC motor: it has an integrated controller, outputting digital Hall signal (period 20.8ms on oscilloscope, w/o load) and taking PWM as input for speed regulation.

As far as my knowledge goes, this is a task for PID: measure Hall pulses at input, adjust duty cycle of the PWM based on target period/frequency of the Hall output.

The speed should be controlled with \<1% error (even less is better).

* Is this goal realistic with this particular motor?
* How should I measure pulse duration?
* Is `pulseIn` (with interrupts disabled) going to be sufficiently precise? Should I measure lows or highs?
* Should I measure several pulses instead (and how)? Or should I accept imprecision in the pulse period and compensate (smooth) it using integral/derivative terms?
* Do I need more than 8-bit PWM resolution for this task? (I will use Nano at first, but might switch to Nano Every, which has 10-bit PWM).

Any other comments/suggestions are welcome.

# Answer
> 3 votes
This is only a partial answer, about measuring pulse period or duration.

For best accuracy, I would recommend using the “input capture” feature of a 16-bit timer. This is not as easy as using `pulseIn()` or timing the signal with `micros()`: you will have to carefully study the MCU's datasheet and manually configure the bits of some I/O registers. You will be rewarded with high accuracy (single-cycle if the timer runs at the MCU clock speed) and without the jitter inherent to any software-based approach.

Beware that the Nano and Nano Every use different MCUs, with very different timers. Both have input capture capability, but if you switch from one to the other you will have to redo most of the work. Note that the Nano is capable of 10-bit PWM if you program it low-level.

A software-based approach (`pulseIn()` or `attachInterrupt()` \+ `micros()`) has the advantage of portability.

# Answer
> 1 votes
To expand a little on Edgar's answer:

There are two main ways of measuring frequency, and both require different resources and are better for different situations.

The method Edgar describes using the Input Capture method, is good for rapidly changing low frequency signals where you want to respond very quickly to changes in the frequency. It works by measuring the time between two pulses using a free-running timer. Of course you can only measure frequencies as fast as the timer can run, which is pretty fast anyway, and if configured right it can run almost entirely asynchronously so you can just query the current recorded time whenever you need to.

The other option is to count the number of pulses within a given time period. This can also be done in hardware but using a different set of peripherals.

For this you have two timers. Timer 1 has the ability to us an external signal on pin D5 as its clock. This basically turns it into a pulse counter, and every time a pulse arrives on the timer pin it increments the count by one.

Then you have a second timer which triggers an interrupt at a predefined period. What that period is depends on the responsiveness you want and the frequency range you want to measure. You can also use the "prescaler" of Timer 1 to increase the frequency measurement range by only counting every 2nd or 4th or 8th etc edge.

Of course, all that timer use would interfere with PWM generation on the Nano, but should be better on the Nano Every, but you'd want to check the datasheet for timer usages.

So in summary:

**Input capture**

* Fast response
* Limited frequency range

**Pulse counting with timer 1**

* Slower response
* Naturally smoothed output
* Greater frequency range
* Understands the concept of zero Hz
* Interferes with PWM generation

Whichever method you choose, sure, feed it through PID to create a stable output RPM.

---
Tags: motor, pwm, pid, hall-effect
---


# Question
Title: Problems with detecting button digital state
I am trying to start an event after pressing and holding the *FLASH built-in Nodemcu button* for a specific time, I wrote two functions, one for debouncing and detecting the state, the other is to detect the pressing time, I'm not getting any result unless I decrease the input pressing time to less than 1s, which makes the button works as a single-push button, I think i have a problem with **debouncing** the button, I can't figure out where it is?

```
/**
* @brief debounces the button and returns the current level high or low
*
* @return int the button state 0: low, 1: high, -1 indetermined
*/
int button_state(int btn)
{
    int const DEBOUNCE = 200;
    static int hi = DEBOUNCE;
    static int lo = 0;
    if (digitalRead(buttonPin[btn]))
    {
        if (hi < DEBOUNCE)
        {
            hi++;
        }
        if (lo > 0)
        {
            lo--;
        }
    }
    else
    {
        if (lo < DEBOUNCE)
        {
            lo++;
        }
        if (hi > 0)
        {
            hi--;
        }
    }

    if (hi == DEBOUNCE)
    {
        return 1;
    }
    else if (lo == DEBOUNCE)
    {
        return 0;
    }
    else
    {
        return -1;
    }
}
/**
 * @brief Detects the button state and starts a time to calculate pressing duration
 *
 * @param btn input button pin
 * @param PressTime Desired pressing duration to compare to
 * @return int returns 1 when PressTime is reached
 */
int PressNHold(int btn, int PressTime)
{
    int lastButtonState = 0, Startpressed = 0, endPressed = 0, holdTime = 0,
    buttonState = button_state(btn);
    if(buttonState != -1)
    {
        if (buttonState != lastButtonState)
        {
            if (buttonState == 1)
            {
                Startpressed = millis();
            }
            else
            {
                endPressed = millis();
                holdTime = endPressed - Startpressed;
                if (holdTime >= PressTime)
                {
                    Serial.printf("Button %d pressed for %ds or more\n", btn, holdTime);
                    holdTime = 0;
                    return 1;
                }
            }
        }
    }
    lastButtonState = buttonState;
}
.....

void loop {

if (PressNHold(buttonPin[1], 5 * 1000) == 1)
  {
   //launch your event
  }

```

# Answer
> 1 votes
turns out that it is very simple, I shouldn't put buttonPin\[1\] a variable for PressNHold, I had to put just1, buttonPin was used already in button\_state, also, PressnHold local variables should be declared static to not get a reset after function execution.

---
Tags: esp8266, button, debounce, esp
---


# Question
Title: Possible to drive Waveshare E-ink without driver hat?
I bought and E-Ink display from waveshare and it came with such a “driver hat”: https://www.waveshare.com/wiki/E-Paper\_Driver\_HAT#Display\_Config\_Switch

I am wondering what exactly is the role of this component? Why can’t I directly connect the cables from the display to the GIPO pins and drive the display without the driver hat - given the right software?

(I am also happy to get a pointer to a better forum to ask in if this here isn’t the right place.)

# Answer
> 0 votes
No, you need the hat, or something equivalent. Turn it over. You see all those components? They exist to generate the right voltages for the ePaper display. Without those it won't work.

Sure, you can recreate it from the schematic, but why bother when you have it already?

---
Tags: spi
---


# Question
Title: Liquid Crystal LCD and serial monitor not playing well together
On my Arduino Uno, when I'm not using the serial everything seems in order:

```
#include <LiquidCrystal.h>

LiquidCrystal lcd(1, 2, 4, 5, 6, 7);

void setup()
{
    // put your setup code here, to run once:
    lcd.begin(16, 2);
    lcd.clear();
    lcd.print("Prints");
    lcd.setCursor(0, 1);
    lcd.print("Well");
}

void loop()
{
    delay(1000);
}

```

However the moment I open the serial port with:

```
Serial.begin(9600);

```

The problem starts.

Clearing the LCD does not clear it but prints a character with 4 horizontal lines. Trying to move the cursor will print a different unrecognisable character. Sending things to the Arduino via the Serial port prints gibberish on the LCD.

Any idea why? Is there a way to work with the LCD and the serial port simultaneously? I require the serial port in order to control the Arduino from NodeJS.

```
#include <LiquidCrystal.h>

LiquidCrystal lcd(1, 2, 4, 5, 6, 7);

void setup()
{
    // put your setup code here, to run once:
    lcd.begin(16, 2);
    lcd.clear();
    lcd.print("Prints");
    lcd.setCursor(0, 1);
    lcd.print("Well");

    Serial.begin(9600);

    while (!Serial)
    {
        ; // wait for serial port to connect. Needed for Native USB only
    }
}

void loop()
{
    lcd.clear(); // This will print 4 horizontal lines character instead of clearing
    delay(500);
}

```

# Answer
> 3 votes
On an UNO pin 1 is one of the hardware serial pins. You can’t use pin 0 or pin 1 for other things if you are using Serial in your code.

Even if you aren’t using Serial, you use pins 0 and 1 when uploading your code and having other things connected can mess up that process. It’s generally advisable to stay away from pins 0 and 1 unless you absolutely must use them.

---
Tags: serial, lcd
---


title: Getting enum name from enum instance

text:
# Question
Title: Getting enum name from enum instance
Hello Arduino Stack Exchange,

I have an an `enum` instance called `state`:

```
enum States
{
  SLEEP,
  AWAKE,
  CRAZY
} state;
States state = SLEEP;

```

I would like to convert the value of `state` to a `String` so I can serially print it using `Serial.println()`.

Currently, when I type `String(state)`, I get a value `0`, `1`, etc. I suppose this corresponds with the index of the `enum`'s key.

How can I get it to return `"SLEEP"`, `"AWAKE"`, etc.?

# Answer
> 5 votes
You can print the value as it is:

```
Serial.println(state);

```

This will print the the ordering number of the enum, but you can specify the value as any number **or char**.

```
enum States
{
  SLEEP = 'S',
  AWAKE = 'A',
  CRAZY = 'C'
};

```

Now if you print it with cast to char `Serial.println((char) state);` it will print a character, which in my opinion is much better then some number.

If you want to convert the enum values identifiers to strings you can do it with a preprocessor macro.

```
enum States
{
  SLEEP,
  AWAKE,
  CRAZY
} state;

#define IDNAME(name) #name
const char* stateNames[] = {IDNAME(SLEEP), IDNAME(AWAKE), IDNAME(CRAZY)};

```

I don't think this is better then to print the char values. To do a pretty print it is better to use descriptions.

```
const char* stateStr[] = {"Sleep", "Awake", "Undefined"};
Serial.println(stateStr[state]);

```

---
Tags: programming, c++, variables
---


# Question
Title: Why is my real time clock getting the wrong time from my PC?
I want my real-time clock to set its time as the time on my PC. However, when I run the following sketch, the real-time clock reports the time as being 32-33 seconds earlier than my PC says the time is.

```
#include <Wire.h>
#include "RTClib.h"

RTC_DS1307 RTC;

void setup () {
  Serial.begin(57600);
  Wire.begin();
  RTC.begin();

  if (! RTC.isrunning()) {
    Serial.println("RTC is NOT running!");
// following line sets the RTC to the date & time this sketch was compiled
// uncomment it & upload to set the time, date and start run the RTC!
    RTC.adjust(DateTime(__DATE__, __TIME__));
  }
}

void loop () {
  DateTime now = RTC.now();
  Serial.print(now.year(), DEC);
  Serial.print('/');
  Serial.print(now.month(), DEC);
  Serial.print('/');
  Serial.print(now.day(), DEC);
  Serial.print(' ');
  Serial.print(now.hour(), DEC);
  Serial.print(':');
  Serial.print(now.minute(), DEC);
  Serial.print(':');
  Serial.print(now.second(), DEC);
  Serial.println();
}

```

I have also tried manually setting the time on the RTC, but I end up with the same problem: the RTC is always 32-33 seconds behind what I set it to. The lag happens as soon as I run the sketch. It seems very odd to me that no matter how I try to set the time, I end up with exactly the same error. I can tell the Arduino to report the time as being 33 seconds after what the RTC says it is, but this solution seems kind of sketchy, and I am worried that something is fundamentally wrong with my RTC or the way I am using it.

I am using an Arduino Uno with an Assembled Data Logging Shield from Adafruit. The data logging shield uses a DS1307 RTC. Has anyone had this problem before, or have any ideas about what could be causing it? Any help would be much appreciated.

# Answer
> 17 votes
The `__DATE__` and `__TIME__` are set when the code is compiling so they will naturally be behind since the code still needs to finish compiling and then be flashed to the chip.

See the Arduino Playground for an example of how to sync it to your computer over serial.

> TimeSerial.pde shows Arduino as a clock without external hardware.
>
> It is synchronized by time messages sent over the serial port. A companion Processing sketch will automatically provide these messages if it is running and connected to the Arduino serial port.

# Answer
> 0 votes
You can fix the offset by calling once the following code in the `setup()` function:

```
RTC_DS3231 rtc;

DateTime now = rtc.now();
rtc.adjust(DateTime(now.unixtime() + 10)); // add 10s to current time for fixing the offset

```

# Answer
> 0 votes
I am experiencing a similar problem with an Arduino UNO and a Nano. Both from the same PC. Indeed it looks like the time it takes from compile time to upload + MCU start is reflected.

Assuming the RTC has a good battery and the compilation + upload times are consistent, then adding a drift compensation to the code seems to do the trick. Here's how I did it (in my case 7 seconds did the "trick" - sorry for the hardocode, but that's for mere description purposes):

```
RTC.adjust(DateTime(__DATE__, __TIME__));
DateTime t = DateTime(RTC.now().unixtime()+7);
RTC.adjust(t);

```

Regards, Hugo Bertini

# Answer
> 0 votes
With the \<DS1307RTC.h\> library the DS1307 can be adjusted during time setup, by using a global variable and then adding this to Sec reading in the getTime() function, for example as follows:

```
#include <DS1307RTC.h>
tmElements_t tm;
byte adjustt = 8;  // adustment for seconds lag allowing for compiler download time

/*********************

bool getTime(const char *str) {
  int Hour, Min, Sec;
  if (sscanf(str, "%d:%d:%d", &Hour, &Min, &Sec) != 3) return false;
  tm.Hour = Hour;
  tm.Minute = Min;
  tm.Second = Sec + adjustt;
  return true;
}

```

# Answer
> -1 votes
The Arduino takes the computer time and sends it to the DS1307. The time it takes to copy is the one you are seeing wrong. I would solve the problem by advancing the computer time the necessary seconds that you say is delayed and when programming you should have the exact time.

---
Tags: arduino-uno, programming, time
---