title: So many missed bytes with serial comm

text:
# Question
Title: So many missed bytes with serial comm
I have a setup with serial comm from Raspberry Pi to Arduino. It's communicating at baud 9600 on both devices, and from Raspberry Pi 3b+ GPIO-14,UART0,TX0 to Arduino Nano RX0. There's a level shifter in between setup as recommended by AdaFruit tutorials. I'm sending data from Raspberry Pi as such:

```
#loop here
m = []
m.append(255)
m.append(i) // index value between 0-150
m.append(p[0][i]) // value between 0-254
m.append(p[1][i]) // value between 0-254
m.append(p[2][i]) // value between 0-254
#print statement here
'''
Data: [255, 94, 0, 0, 0, 255, 95, 254, 0, 0, 255, 96, 0, 254, 0]
...
'''

```

And receiving data on Arduino as such:

```
void serialEvent() {
  while (Serial.available()) {
    // get the new byte:
    byte inChar = (byte)Serial.read();
    sprintf(printString, "Received: %d", inChar);
    Serial.println(printString);
  }
}
/*
Received: 255
Received: 94
Received: 0
Received: 255
Received: 95
Received: 254
Received: 0
Received: 255
Received: 96
Received: 0
Received: 254
Received: 255
Received: 94
Received: 0
Received: 0
Received: 0
Received: 255
Received: 254
Received: 255
...
*/

```

Any idea why there are so many missed bytes and how to fix this?

EDIT: @juraj There is a ground between both. I've measured with a portable oscilloscope. I can post the picture of the setup tomorrow.

@Edgar Bonet The loop function is empty, and looks as follows:

```
void loop() {
}

```

I also don't have any data being sent back to the Raspberry Pi. I have the Serial TX wire out from Arduino completely disconnected

# Answer
Without the full codes, we can only guess. My guess would be the serial receive buffer on the Arduino is overflowing.

One reason this could happen is if `serialEvent()` is not called frequently enough. This function is called by the Arduino core on every loop iteration, just after `loop()` returns. If your `loop()` takes too long (e.g. you are using `delay()` or blocking waits), the receive buffer can overflow before `serialEvent()` has a chance to empty it.

Another reason is if the Raspberry Pi is sending too much data, too fast. For every byte the Arduino receives, it must send back between 13 and 15 bytes. If too much data comes too fast, the transmit buffer will eventually get full, and then `Serial.println()` becomes *really slow*, because it has to wait for the bytes to actually get out on the wire. This in turn slows down `serialEvent()` to the point where it can make the receive buffer overflow.

**Edit**: If this (the Raspberry sending data too fast) is the cause of the problem, the obvious solution is to have it send data more slowly, as:

```
repeat:
    send a message
    delay for some suitable time

```
> 1 votes

---
Tags: serial, voltage-level, uart, raspberrypi, digital
---


# Question
Title: MPU6050 Arduino Jeff Rowberg library interrupt Issue
I was trying to get the data from MPU6050 using the Arduino library mentioned here.

The following code is an edited version of the sample code given in the library folder which seems to be working fine.

```
#define printfloatx(Name,Variable,Spaces,Precision,EndTxt) { Serial.print(F(Name)); {char S[(Spaces + Precision + 3)];Serial.print(F(" ")); Serial.print(dtostrf((float)Variable,Spaces,Precision ,S));}Serial.print(F(EndTxt)); }//Name,Variable,Spaces,Precision,EndTxt

#include "I2Cdev.h"
#include "MPU6050_6Axis_MotionApps_V6_12.h"

#include "Wire.h"

MPU6050 accelgyro;
MPU6050 mpu;

I2Cdev a;

/*
    IMU Zero variables
*/

int16_t data_acc[3];
int16_t data_Gyro[3];

/*
   IMU initialization variables
*/
uint8_t devStatus;      // return status after each device operation (0 = success, !0 = error)
uint8_t mpuIntStatus;   // holds actual interrupt status byte from MPU
bool dmpReady = false;  // set true if DMP init was successful
uint16_t packetSize;    // expected DMP packet size (default is 42 bytes)

/*
   IMU angle finding variables
*/
uint16_t fifoCount;     // count of all bytes currently in FIFO
uint8_t fifoBuffer[64]; // FIFO storage buffer

Quaternion q;           // [w, x, y, z]         quaternion container
VectorFloat gravity;    // [x, y, z]            gravity vector
float ypr[3];           // [yaw, pitch, roll]   yaw/pitch/roll container and gravity vector

void Initialize()
{
  // initialize device
  Serial.println("Initializing I2C devices...");
  accelgyro.initialize();

  // verify connection
  Serial.println("Testing device connections...");
  Serial.println(accelgyro.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");
  Serial.println("tuning Each Dot = 100 readings");
  accelgyro.CalibrateAccel(10);
  accelgyro.CalibrateGyro(10);

  a.readWords(0x68, 0x06, 3, (uint16_t *)data_acc);
  a.readWords(0x68, 0x13, 3, (uint16_t *)data_Gyro);
} // Initialize

void setup() {
  Wire.begin();
  Serial.begin(115200);
  Initialize();
  Wire.setClock(400000);
  while (!Serial);
  Serial.println(F("Initializing I2C devices..."));
  mpu.initialize();
  Serial.println(F("Testing device connections..."));
  Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));

  Serial.println(F("\nSend any character to begin DMP programming and demo: "));
  while (Serial.available() && Serial.read()); // empty buffer
  while (!Serial.available());                 // wait for data
  while (Serial.available() && Serial.read()); // empty buffer again

  // load and configure the DMP
  Serial.println(F("Initializing DMP..."));
  devStatus = mpu.dmpInitialize();

  // supply your own gyro offsets here, scaled for min sensitivity
  mpu.setXGyroOffset(data_Gyro[0]);
  mpu.setYGyroOffset(data_Gyro[1]);
  mpu.setZGyroOffset(data_Gyro[2]);
  mpu.setXAccelOffset(data_acc[0]);
  mpu.setYAccelOffset(data_acc[1]);
  mpu.setZAccelOffset(data_acc[2]);

  if (devStatus == 0) {
    // Calibration Time: generate offsets and calibrate our MPU6050
    mpu.CalibrateAccel(6);
    mpu.CalibrateGyro(6);
    Serial.println();
    mpu.PrintActiveOffsets();
    // turn on the DMP, now that it's ready
    Serial.println(F("Enabling DMP..."));
    mpu.setDMPEnabled(true);

    // enable Arduino interrupt detection
    Serial.print(F("Enabling interrupt detection (Arduino external interrupt "));
    mpuIntStatus = mpu.getIntStatus();
    Serial.println(F("DMP ready! Waiting for first interrupt..."));
    dmpReady = true;
    packetSize = mpu.dmpGetFIFOPacketSize();
  } else {
    Serial.print(F("DMP Initialization failed (code "));
    Serial.print(devStatus);
    Serial.println(F(")"));
  }

  Serial.println("-------------- done --------------");
} // setup

void loop()
{
  if (!dmpReady) return;
  if (mpu.dmpGetCurrentFIFOPacket(fifoBuffer)) {
    mpu.dmpGetQuaternion(&q, fifoBuffer);
    mpu.dmpGetGravity(&gravity, &q);
    mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
    Serial.print("ypr\t");
    Serial.print(ypr[0] * 180 / M_PI);
    Serial.print("\t");
    Serial.print(ypr[1] * 180 / M_PI);
    Serial.print("\t");
    Serial.print(ypr[2] * 180 / M_PI);
    Serial.println();
  }

}

```

Then I have activated the input capture pin to use with the interrupt and the code is as follows

```
#define printfloatx(Name,Variable,Spaces,Precision,EndTxt) { Serial.print(F(Name)); {char S[(Spaces + Precision + 3)];Serial.print(F(" ")); Serial.print(dtostrf((float)Variable,Spaces,Precision ,S));}Serial.print(F(EndTxt)); }//Name,Variable,Spaces,Precision,EndTxt

#include "I2Cdev.h"
#include "MPU6050_6Axis_MotionApps_V6_12.h"

#include "Wire.h"

MPU6050 accelgyro;
volatile MPU6050 mpu;

I2Cdev a;

/*
    IMU Zero variables
*/

int16_t data_acc[3];
int16_t data_Gyro[3];

/*
   IMU initialization variables
*/
uint8_t devStatus;      // return status after each device operation (0 = success, !0 = error)
uint8_t mpuIntStatus;   // holds actual interrupt status byte from MPU
bool dmpReady = false;  // set true if DMP init was successful
uint16_t packetSize;    // expected DMP packet size (default is 42 bytes)

/*
   IMU angle finding variables
*/
uint16_t fifoCount;     // count of all bytes currently in FIFO
uint8_t fifoBuffer[64]; // FIFO storage buffer

Quaternion q;           // [w, x, y, z]         quaternion container
VectorFloat gravity;    // [x, y, z]            gravity vector
volatile float ypr[3];           // [yaw, pitch, roll]   yaw/pitch/roll container and gravity vector

void Initialize()
{
  // initialize device
  Serial.println("Initializing I2C devices...");
  accelgyro.initialize();

  // verify connection
  Serial.println("Testing device connections...");
  Serial.println(accelgyro.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");
  Serial.println("tuning Each Dot = 100 readings");
  accelgyro.CalibrateAccel(10);
  accelgyro.CalibrateGyro(10);

  a.readWords(0x68, 0x06, 3, (uint16_t *)data_acc);
  a.readWords(0x68, 0x13, 3, (uint16_t *)data_Gyro);
} // Initialize

void timer4_initialization() {
  pinMode(49, INPUT);
  TCCR4A = 0; TCCR4B = 0; TCCR4C = 0;
  TCCR4B = B11000000;
  TIFR4 = _BV(ICF4);
  TIMSK4 = B00100000;
}

ISR(TIMER4_CAPT_vect) {
  if (!dmpReady) return;
  if (mpu.dmpGetCurrentFIFOPacket(fifoBuffer)) {
    mpu.dmpGetQuaternion(&q, fifoBuffer);
    mpu.dmpGetGravity(&gravity, &q);
    mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
  }
}

void setup() {
  Wire.begin();
  Serial.begin(115200);
  Initialize();
  Wire.setClock(400000);
  while (!Serial);
  Serial.println(F("Initializing I2C devices..."));
  mpu.initialize();
  Serial.println(F("Testing device connections..."));
  Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));

  Serial.println(F("\nSend any character to begin DMP programming and demo: "));
  while (Serial.available() && Serial.read()); // empty buffer
  while (!Serial.available());                 // wait for data
  while (Serial.available() && Serial.read()); // empty buffer again

  // load and configure the DMP
  Serial.println(F("Initializing DMP..."));
  devStatus = mpu.dmpInitialize();

  // supply your own gyro offsets here, scaled for min sensitivity
  mpu.setXGyroOffset(data_Gyro[0]);
  mpu.setYGyroOffset(data_Gyro[1]);
  mpu.setZGyroOffset(data_Gyro[2]);
  mpu.setXAccelOffset(data_acc[0]);
  mpu.setYAccelOffset(data_acc[1]);
  mpu.setZAccelOffset(data_acc[2]);

  if (devStatus == 0) {
    // Calibration Time: generate offsets and calibrate our MPU6050
    mpu.CalibrateAccel(6);
    mpu.CalibrateGyro(6);
    Serial.println();
    mpu.PrintActiveOffsets();
    // turn on the DMP, now that it's ready
    Serial.println(F("Enabling DMP..."));
    mpu.setDMPEnabled(true);

    // enable Arduino interrupt detection
    Serial.print(F("Enabling interrupt detection (Arduino external interrupt "));
    mpuIntStatus = mpu.getIntStatus();
    Serial.println(F("DMP ready! Waiting for first interrupt..."));
    dmpReady = true;
    packetSize = mpu.dmpGetFIFOPacketSize();
  } else {
    Serial.print(F("DMP Initialization failed (code "));
    Serial.print(devStatus);
    Serial.println(F(")"));
  }

  Serial.println("-------------- done --------------");

  delay(2000);

  timer4_initialization();

} // setup

void loop()
{
  Serial.print("ypr\t");
  Serial.print(ypr[0] * 180 / M_PI);
  Serial.print("\t");
  Serial.print(ypr[1] * 180 / M_PI);
  Serial.print("\t");
  Serial.print(ypr[2] * 180 / M_PI);
  Serial.println();
}

```

Here when I am using with the interrupt I am not getting anything printed, seems like the program is frozen somewhere in the interrupt -\> function call.

What is the mistake I am making here.

How to take the measurement from MPU6050 using ISR routines.

# Answer
> 4 votes
The functions `mpu.dmpGetCurrentFIFOPacket(fifoBuffer)`, etc, are using I2C for getting the data. The I2C interface on the Uno and Mega (which you tagged your question with) is implemented in hardware and needs interrupts for handling the data bytes (taking the received byte out of the register or writing data to the register for sending).

By default interrupts are disabled inside of an ISR. Thus the mentioned functions cannot execute correctly. They are waiting for an interrupt, which is never going to happen, since the functions are executed while interrupts are disabled.

It is possible to reactivate interrupts in an ISR, but that is something, that you should only do in a few situations and only, when you know exactly, what you are doing.

Instead you should just set a volatile flag variable inside the ISR. In the main code (in `loop()`) you can then check for that flag, execute the I2C code when it is set and reset the flag afterwards. And you can then also just print, when there is new data instead of every loop iteration. So somewhat like this:

```
volatile byte timer_flag = 0;

ISR(TIMER4_CAPT_vect) {
  timer_flag = 1;
}

void loop(){
    if(timer_flag){
        if (!dmpReady) return;
        if (mpu.dmpGetCurrentFIFOPacket(fifoBuffer)) {
            mpu.dmpGetQuaternion(&q, fifoBuffer);
            mpu.dmpGetGravity(&gravity, &q);
            mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
            // then print the values here, since we got new data from the MPU
        }
        timer_flag = 0; // Resetting the flag for the next timer interrupt
    }
}

```

# Answer
> 0 votes
I've tweaked chrisl's answer to show how to copy the ISR data and reset the ISR flag in an atomic manner.

```
volatile bool isr_timer_flag = false;
volatile uint32_t isr_counter = 0;  // Added to demonstrate how to copy a multibyte data type atomically.

ISR(TIMER4_CAPT_vect)
{
    isr_timer_flag = true;
    isr_counter++;
}

void loop()
{
    //
    // Get a copy of the data and reset the flag atomically by temporarily disabling interrupts.
    //

    // Disable interrupts by clearing the global interrupt flag.
    cli();

    // Copy the data.
    bool timer_flag = isr_timer_flag;
    uint32_t counter = isr_counter;

    // Reset the ISR flag for the next timer interrupt.
    // Resetting it here avoids clearing any re-flag during the following if statements.
    isr_timer_flag = false;

    // Enable interrupts by setting the global interrupt flag.
    sei();

    // Now use the local copy of the ISR flag.
    // The ISR flag could be re-flagged at any time during the remainder of the loop,
    // but a fresh copy will be obtained on the next iteration of the loop.

    if (timer_flag)
    {
        if (!dmpReady) return;
        if (mpu.dmpGetCurrentFIFOPacket(fifoBuffer))
        {
            mpu.dmpGetQuaternion(&q, fifoBuffer);
            mpu.dmpGetGravity(&gravity, &q);
            mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
            // then print the values here, since we got new data from the MPU
        }
    }
}

```

---
Tags: arduino-uno, arduino-mega, interrupt, timers, mpu6050
---


# Question
Title: Keypad pin as an interrupt (Wiring or programming)
I have this project of a "phone". It consists of:

* Arduino DUE,
* 4x4 Keypad,
* SD Data shield,
* a phone receiver detect (on/off)
* an Amp and a Speaker.

In the beginning, after the phone receiver is being picked, I am playing a .wav file of an intro on how to choose a language. And this .wav should be interrupted when the user presses the 4th row of a keypad (Buttons A/B/C/D). I only need one pin as far as I know, in this setup - pin 38 (Column 4 pin). As I understand, there is no proper way to declare a keypad input pin as an interrupt on DUE. Or is it?

So my question - how to wire a keypad input pin as an interrupt? I have read about wiring with a diode. But most of the threads lack any specifics.

Can someone push me in the right direction? Cheers!

Code:

```
#include <DAC.h>
#include <SD.h>
#include <SPI.h>
#include <Audio.h>
#include <Key.h>
#include <Keypad.h>

const byte ROW_NUM = 4;
const byte COLUMN_NUM = 4;

int code1 = 12345;  //The code I used, you can change it
int code2 = 45678;  //The code I used, you can change it
int code3 = 78900;  //The code I used, you can change it

int tot, i1, i2, i3, i4, i5;
char c1, c2, c3, c4;

char hexaKeys[ROW_NUM][COLUMN_NUM] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};

byte hookPinA = 23;  // your interrupt pin
byte interruptPin = 22;  // your interrupt pin

byte pin_rows[ROW_NUM] = {52, 50, 48, 46}; //connect to the row pinouts of the keypad
byte pin_column[COLUMN_NUM] = {44, 42, 40, 38}; //connect to the column pinouts of the keypad

int keyCounter = 0;

Keypad myKeypad = Keypad(makeKeymap(hexaKeys), pin_rows, pin_column, ROW_NUM, COLUMN_NUM);

char keypresses[5];
char language;
char key;

int goIntoKeys = 0;

volatile uint8_t interruptState = 0;
volatile byte hookOffState = 0;

void setup() {
  // debug output at 9600 baud
  Serial.begin(9600);
  SD.begin(10);
  analogWriteResolution(12);

//for( int i=0; i< ROW_NUM; ++i) pinMode(pin_rows[i], INPUT_PULLUP);
//for( int i=0; i< COLUMN_NUM; ++i) pinMode(pin_column[i], INPUT_PULLUP);

 pinMode(hookPinA, INPUT_PULLUP);

 attachInterrupt(digitalPinToInterrupt(hookPinA), hookOffToggle, CHANGE);

// EIFR |= bit(INTF0); // clear INT0 interrupt flag

 attachInterrupt(digitalPinToInterrupt(interruptPin), interruptToggle, RISING); //test interrupt with a regular button

 pinMode(38, INPUT_PULLUP);
 attachInterrupt(digitalPinToInterrupt(38), interruptToggle, RISING);

  DACC->DACC_CHDR = DACC_CHDR_CH1; //disable DAC1

}

int state = 0;
const int STATE_OFF = 0;
const int STATE_IDLE = 1;
const int STATE_LISTEN_KEY = 2;
const int STATE_PLAYER = 3;

bool isLanguageKey(char customKey) {
  return ('A' == customKey || 'B' == customKey || 'C' == customKey || 'D' == customKey);
}

void loop() {
  switch (state) {
    case STATE_OFF:
    //listen for a telephone receiver to be removed
      if (hookOffState == 1) {
      Serial.print("HOOK OFF ");
      Serial.println(hookOffState);
        interruptState = 0;
        state = STATE_IDLE;
               }
               else if (hookOffState == 0) {
      Serial.print("HOOK ON ");
      Serial.println(hookOffState);
               }
        break;
    case STATE_IDLE:
    //listen for a language key. Cannot dial a number before
      Serial.print("interrupt IDLE ");
      Serial.println(interruptState);
               if (interruptState == 1) {
         buttonBeep();
        processLanguage();
        state = STATE_LISTEN_KEY;
               }
               else if (hookOffState == 0){
                state = STATE_OFF;
               }
               else {
      playSound("intro.wav");
        }
      break;
    case STATE_LISTEN_KEY:
    //listen for any key
      Serial.print("interrupt LISTEN KEY ");
      Serial.println(interruptState);
      if (isKeyPressed()) {
        interruptState = 0;
        if (isLanguageKey(key)) {
          buttonBeep();
          processLanguage();
        }
        else {
      Serial.print("interruptStateF ");
      Serial.println(interruptState);
               buttonBeep();
          keypresses[keyCounter] = key;
          keyDial();
          keyCounter++;
          if (keyCounter > 4) {
            state = STATE_PLAYER;
            //when 5 numbers are pressed - try to open the .wav file
          }
        }
      }
               else if (hookOffState == 0){
                state = STATE_OFF;
               }
      break;
    case STATE_PLAYER:
        //Play the audio and go back to state LISTEN
      calculateAndPlay();
      keyCounter = 0;
      interruptState = 0;
      state = STATE_LISTEN_KEY;
      break;
    default:
      break;
  }
}

void hookOffToggle(){
 if (digitalRead(hookPinA) == 1) {
  hookOffState = 1;
 }
  else  {
      hookOffState = 0;
  }
}

void interruptToggle() {
    interruptState = 1;
}

void kalba() {
  Serial.println("Kalba? Language? Valoda? Yazik?");
}

bool isKeyPressed() {
  key = myKeypad.getKey();
  return key != NO_KEY;
}

bool langKeyPressed() {
  key = myKeypad.getKey();
  return key != NO_KEY && isLanguageKey(key);
}

void processLanguage() { //press A/B/C/D keys - select 1 out of 4 languages
  //goIntoKeys = 1;
  keyCounter = 0;
  if (key == 'A') {
    Serial.println("   LT    ");
  }
  if (key == 'B') {
    Serial.println("   EN    ");
  }
  if (key == 'C') {
    Serial.println("   LV    ");
  }
  if (key == 'D') {
    Serial.println("   RU    ");
  }
  language = key;
}

void keyDial() {    // LCD displays the number dialed in 3 slots.
  keypresses[keyCounter] = 0x00;//null-byte
  keypresses[keyCounter] = key;

  if (key != NO_KEY)   {
    Serial.println(keypresses[keyCounter]);
  }
}

void buttonBeep(){
      for (int j = 0; j < 200; j++) {
        for (int i = 0; i < 200; i++)
          analogWrite(DAC0, i);
        for (int i = 200; i >= 0; i--)
          analogWrite(DAC0, i);
      }
}

void backgroundHumm() {
      for (int j = 0; j < 256; j++) {
        for (int i = 0; i < 256; i++)
          analogWrite(DAC0, j);
          for (int j = 256; j >= 0; j--) {
            for (int i = 256; i >= 0; i--)
          analogWrite(DAC0, j);
      }
  }
}

void calculateAndPlay() {
  //if we have 4+1 numbers - proceed
  //the keys pressed are stored into chars I convert them to int then i did some multiplication to get the code as an int of xxxx
  i1 = (keypresses[0] - 48) * 10000;
  i2 = (keypresses[1] - 48) * 1000;
  i3 = (keypresses[2] - 48) * 100;
  i4 = (keypresses[3] - 48) * 10;
  i5 = (keypresses[4] - 48) * 1;

  tot = i1 + i2 + i3 + i4 + i5;
  if (language == 'A') {
    if (tot == code1) //if the code is correct you trigger to play .wav
    {
      playSound("ledaiLT.wav");
    }
    else if (tot == code2)
    {
      playSound("zuvisLT.wav");
    }
    else if (tot == code3)
    {
      playSound("draugLT.wav");
    }
    else //if the code is wrong you get a beep and audio message
  {
      playSound("blogasLT.wav");
    }
  }
  if (language == 'B') {
    if (tot == code1) //if the code is correct you trigger to play .wav
    {
      playSound("ledaiEN.wav");
    }
    else if (tot == code2)
    {
      playSound("zuvisEN.wav");
    }
    else if (tot == code3)
    {
      playSound("draugEN.wav");
    }
    else //if the code is wrong you get a beep and audio message
    {
      playSound("blogasEN.wav");
    }
  }
  if (language == 'C') {
    if (tot == code1) //if the code is correct you trigger to play .wav
    {
      playSound("ledaiLV.wav");
    }
    else if (tot == code2)
    {
      playSound("zuvisLV.wav");
    }
    else if (tot == code3)
    {
      playSound("draugLV.wav");
    }
    else //if the code is wrong you get a beep and audio message
    {
      playSound("blogasLV.wav");
    }
  }
  if (language == 'D') {
    if (tot == code1) //if the code is correct you trigger to play .wav
    {
      playSound("ledaiRU.wav");
    }
    else if (tot == code2)
    {
      playSound("zuvisRU.wav");
    }
    else if (tot == code3)
    {
      playSound("draugRU.wav");
    }
    else //if the code is wrong you get a beep and audio message
    {
      playSound("blogasRU.wav");
    }
  }
}

// Playing assigned filename
void playSound(const char* cName) {
  File myFile = SD.open(cName);
  const int S = 1024; // Number of samples to read in block
  short buffer[S];
  // until the file is not finished
  Serial.println("playing ");
  Serial.println(cName);

  Audio.begin(44100, 200);
  delay(200);
  while (myFile.available()) {
    myFile.read(buffer, sizeof(buffer));
    // Prepare samples
    int volume = 512;
    //max volume 1024
    Audio.prepare(buffer, S, volume);
    Audio.write(buffer, S);
   if ( interruptState ) break;
     else if ( hookOffState == 0 ) break;
  }
  Audio.end();
  myFile.close();
  delay(50);
  DACC->DACC_CHDR = DACC_CHDR_CH1; //disable DAC1
}

```

The schematics (if you can call it that) below:

EDIT: @Damago solution works! I just wanted to share here the solution for future searches. What you need to do is to get the 4th column of 4x4 keypad to work as an interrupt properly: Set all row pins as output and column pins as input with pullup.

```
for( int i=0; i< ROW_NUM; ++i) pinMode(pin_rows[i], OUTPUT);
for( int i=0; i< COLUMN_NUM; ++i) pinMode(pin_column[i], INPUT_PULLUP);

```

Set row pins to low:

```
for( int i=0; i< ROW_NUM; ++i) digitalWrite(pin_rows[i], LOW);

```

Attach the 4th column pin as interrupt:

```
attachInterrupt(digitalPinToInterrupt(pin_column[3]), interruptToggle, FALLING);

```

And of course, fix the syntax overall (it was a bit messy :) )

Full sketch below:

```
#include <DAC.h>
#include <SD.h>
#include <SPI.h>
#include <Audio.h>
#include <Keypad.h>

const byte ROW_NUM = 4;
const byte COLUMN_NUM = 4;

int code1 = 12345;  //The code I used, you can change it
int code2 = 45678;  //The code I used, you can change it
int code3 = 78900;  //The code I used, you can change it

int tot, i1, i2, i3, i4, i5;
char c1, c2, c3, c4;

char hexaKeys[ROW_NUM][COLUMN_NUM] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};

byte hookPinA = 23;  // your interrupt pin
byte pin_rows[ROW_NUM] = {52, 50, 48, 46}; //connect to the row pinouts of the keypad
byte pin_column[COLUMN_NUM] = {44, 42, 40, 38}; //connect to the column pinouts of the keypad

Keypad myKeypad = Keypad(makeKeymap(hexaKeys), pin_rows, pin_column, ROW_NUM, COLUMN_NUM);

char keypresses[5];
char language;
char key;

volatile uint8_t interruptState = 0;
volatile byte hookOffState = 0;
int keyCounter = 0;

void setup() {
  // debug output at 9600 baud
  Serial.begin(9600);
  SD.begin(10);
  analogWriteResolution(12);

for( int i=0; i< ROW_NUM; ++i) pinMode(pin_rows[i], OUTPUT);
for( int i=0; i< COLUMN_NUM; ++i) pinMode(pin_column[i], INPUT_PULLUP);

for( int i=0; i< ROW_NUM; ++i) digitalWrite(pin_rows[i], LOW);
 pinMode(hookPinA, INPUT_PULLUP);
 attachInterrupt(digitalPinToInterrupt(hookPinA), hookOffToggle, CHANGE);
 attachInterrupt(digitalPinToInterrupt(pin_column[3]), interruptToggle, FALLING);

  DACC->DACC_CHDR = DACC_CHDR_CH1; //disable DAC1
}

int state = 0;
const int STATE_OFF = 0;
const int STATE_IDLE = 1;
const int STATE_LISTEN_KEY = 2;
const int STATE_PLAYER = 3;

bool isLanguageKey(char customKey) {
  return ('A' == customKey || 'B' == customKey || 'C' == customKey || 'D' == customKey);
}

void loop() {
  switch (state) {
    case STATE_OFF:
    //listen for a telephone receiver to be removed
      if (hookOffState == 1) {
        interruptState = 0;
        state = STATE_IDLE;
                      }
               else if (hookOffState == 0) {
               }
        break;
    case STATE_IDLE:
    //listen for a language key. Cannot dial a number before
               if (interruptState == 1) {
         isKeyPressed(); //get the key input
         buttonBeep();
        processLanguage();
        state = STATE_LISTEN_KEY;
               }
               else if (hookOffState == 0){
                state = STATE_OFF;
               }
               else {
      playSound("intro.wav");
        }
      break;
    case STATE_LISTEN_KEY:
    //listen for any key
      if (isKeyPressed()) {
        interruptState = 0;
        if (isLanguageKey(key)) {
          buttonBeep();
          processLanguage();
        }
        else  {
          buttonBeep();
          keypresses[keyCounter] = key;
          keyCounter++;
          if (keyCounter > 4) {
            state = STATE_PLAYER;
            //when 5 numbers are pressed - try to open the .wav file
          }
        }
      }
               else if (hookOffState == 0){
                state = STATE_OFF;
               }
      break;
    case STATE_PLAYER:
        //Play the audio and go back to state LISTEN
      calculateAndPlay();
      keyCounter = 0;
      interruptState = 0;
      state = STATE_LISTEN_KEY;
      break;
    default:
      break;
  }
}

void hookOffToggle() {     //detect a telephone receiver to be removed
hookOffState = digitalRead(hookPinA);
}

void interruptToggle() {
    interruptState = 1;
}

bool isKeyPressed() {
  key = myKeypad.getKey();
  return key != NO_KEY;
}

bool langKeyPressed() {
  key = myKeypad.getKey();
  return key != NO_KEY && isLanguageKey(key);
}

void processLanguage() { //press A/B/C/D keys - select 1 out of 4 languages
  keyCounter = 0;
  if (key == 'A') {
    Serial.println("   LT    ");
  }
  if (key == 'B') {
    Serial.println("   EN    ");
  }
  if (key == 'C') {
    Serial.println("   LV    ");
  }
  if (key == 'D') {
    Serial.println("   RU    ");
  }
  language = key;
}

void buttonBeep(){
      for (int j = 0; j < 200; j++) {
        for (int i = 0; i < 200; i++)
          analogWrite(DAC0, i);
        for (int i = 200; i >= 0; i--)
          analogWrite(DAC0, i);
      }
}

void backgroundHumm() {
      for (int j = 0; j < 256; j++) {
        for (int i = 0; i < 256; i++)
          analogWrite(DAC0, j);
          for (int j = 256; j >= 0; j--) {
            for (int i = 256; i >= 0; i--)
          analogWrite(DAC0, j);
      }
  }
}

void calculateAndPlay() {
  //if we have 4+1 numbers - proceed
  //the keys pressed are stored into chars I convert them to int then i did some multiplication to get the code as an int of xxxx
  i1 = (keypresses[0] - 48) * 10000;
  i2 = (keypresses[1] - 48) * 1000;
  i3 = (keypresses[2] - 48) * 100;
  i4 = (keypresses[3] - 48) * 10;
  i5 = (keypresses[4] - 48) * 1;

  tot = i1 + i2 + i3 + i4 + i5;
  if (language == 'A') {
    if (tot == code1) //if the code is correct you trigger to play .wav
    {
      playSound("ledaiLT.wav");
    }
    else if (tot == code2)
    {
      playSound("zuvisLT.wav");
    }
    else if (tot == code3)
    {
      playSound("draugLT.wav");
    }
    else //if the code is wrong you get a beep and audio message
  {
      playSound("blogasLT.wav");
    }
  }
  if (language == 'B') {
    if (tot == code1) //if the code is correct you trigger to play .wav
    {
      playSound("ledaiEN.wav");
    }
    else if (tot == code2)
    {
      playSound("zuvisEN.wav");
    }
    else if (tot == code3)
    {
      playSound("draugEN.wav");
    }
    else //if the code is wrong you get a beep and audio message
    {
      playSound("blogasEN.wav");
    }
  }
  if (language == 'C') {
    if (tot == code1) //if the code is correct you trigger to play .wav
    {
      playSound("ledaiLV.wav");
    }
    else if (tot == code2)
    {
      playSound("zuvisLV.wav");
    }
    else if (tot == code3)
    {
      playSound("draugLV.wav");
    }
    else //if the code is wrong you get a beep and audio message
    {
      playSound("blogasLV.wav");
    }
  }
  if (language == 'D') {
    if (tot == code1) //if the code is correct you trigger to play .wav
    {
      playSound("ledaiRU.wav");
    }
    else if (tot == code2)
    {
      playSound("zuvisRU.wav");
    }
    else if (tot == code3)
    {
      playSound("draugRU.wav");
    }
    else //if the code is wrong you get a beep and audio message
    {
      playSound("blogasRU.wav");
    }
  }
}

// Playing assigned filename
void playSound(const char* cName) {
  File myFile = SD.open(cName);
  const int S = 1024; // Number of samples to read in block
  short buffer[S];
  // until the file is not finished
  Serial.println("playing ");
  Serial.println(cName);

  Audio.begin(44100, 200);
  delay(200);
  while (myFile.available()) {
    myFile.read(buffer, sizeof(buffer));
    // Prepare samples
    int volume = 512;
    //max volume 1024
    Audio.prepare(buffer, S, volume);
    Audio.write(buffer, S);
   if ( interruptState ) break;
   else if ( hookOffState == 0 ) break;
  }
  Audio.end();
  myFile.close();
  delay(50);
  DACC->DACC_CHDR = DACC_CHDR_CH1; //disable DAC1
}

```

# Answer
> 3 votes
There is a bit of a problem here. You cannot simply use one diode. There voltage is present on the keyboard pins only during getKey() function evaluation.

The keyboard works this way: when you call a myKeypad.getKey(); then arduino does the following:

* changes the first column from input (high impedance) to output
* outputs 0V voltage to first column,
* scans all rows if they are 0V (normally they are pulled up - you know what pullup is).
* if any key in this column is pressed then the column voltage of 0V is pulling down the corresponding row voltage. That is there is a connection between row and column.

Here is the exact code:

```
    pin_mode(columnPins[c],OUTPUT);
    pin_write(columnPins[c], LOW);  // Begin column pulse output.
    for (byte r=0; r<sizeKpd.rows; r++) {
        bitWrite(bitMap[r], c, !pin_read(rowPins[r]));  // keypress is active low so invert to high.
    }
    // Set pin to high impedance input. Effectively ends column pulse.
    pin_write(columnPins[c],HIGH);
    pin_mode(columnPins[c],INPUT);

```

It is not impossible to do this this way but it would require either modifying keyboard or creating a bit more complicated circuit. However it really does not make real sense.

I would do this different way: I would completely skip interrupt here. You are checking for a flag set inside interrupt:

```
if ( interruptState ) break;

```

I would directly check here for the voltage on a specific pin. You have to (simply):

* set row pin (46 as far as I understand from your code) to output, and set it to low,
* set column pins (all of them) to input-pullup - as I understand {44, 42, 40, 38}
* check if any of those pins is 'LOW', if yes - then break;

As far as I understand the library you don't even have to revert any pins back, the library re-initializes the pins correctly on every GetKey()

If for any reason the operation above takes too long you can shorten it using direct port manipulation as in https://forum.arduino.cc/t/arduino-due-how-to-direrct-port-access/251656 but note, that it is not as simple on Arduino Due as on AVR based ones.

# Answer
> 1 votes
If you want to use interrupts, it requires a separate pin to detect the falling edge on column 4 (pin 38). In the following example, I used pin 28 for the column 4 interrupt. These can be connected together via a 1K resistor to protect against pin 28 inadvertently outputting low while the other is outputting high.

Pin 38 is pulled low during the call of `myKeypad.getKey()` thus triggering the ISR.

Working copies are made of the variables that are updated in the ISRs. This will require changes to the state machine to process `column4Pressed` obtained from the ISR.

```
const byte hookPinA = 23;  // your interrupt pin
const byte interruptPin = 22;  // your interrupt pin

const byte column4InterruptPin = 28;  // Column 4 interrupt pin connected to column4Pin via a wire link. Could add a 1K series resistor to protect against short circuit to ground if it were output low when pin 38 is output high.
const byte column4Pin = 38;  // Column 4 pin connected to column4InterruptPin via a wire link.

// States updated by ISR.
volatile byte isr_hookOffState = 0;
volatile byte isr_interruptState = 0;
volatile bool isr_column4Pressed = false;

// Working copies of ISR data.
byte hookOffState = 0;
byte interruptState = 0;
bool column4Pressed = false;

// Use a single byte for the state variable and initialise it to OFF.
enum class State : byte
{
    OFF = 0,
    IDLE = 1,
    LISTEN_KEY = 2,
    PLAYER = 3
} state = State::OFF;

void setup()
{
    pinMode(hookPinA, INPUT_PULLUP);
    attachInterrupt(digitalPinToInterrupt(hookPinA), hookOffToggle, CHANGE);

    pinMode(interruptPin, INPUT);
    attachInterrupt(digitalPinToInterrupt(interruptPin), interruptToggle, RISING); // test interrupt with a regular button

    pinMode(column4InterruptPin, INPUT_PULLUP);
    attachInterrupt(digitalPinToInterrupt(column4InterruptPin), interruptColumn4, FALLING);  // Triggered by pulling column 4 low, e.g. digitalWrite(column4Pin, LOW) or within myKeypad.getKey().
}

void loop()
{
    // Get a fresh copy of the ISR data and reset the interrupt state flag atomically
    // by temporarily disabling interrupts.
    cli();
    hookOffState = isr_hookOffState;
    interruptState = isr_interruptState;
    column4Pressed = isr_column4Pressed;
    isr_interruptState = 0;  // Reset to detect next interrupt.
    isr_column4Pressed = false; // Reset to detect next interrupt.
    sei();

    // Alternative method to test whether any button in column 4 is pressed.
    // This is how to do it without using interrupts.
    /*
    pinMode(column4Pin, OUTPUT);
    digitalWrite(column4Pin, LOW);
    column4Pressed = !digitalRead(52) || !digitalRead(50) || !digitalRead(48) || !digitalRead(46);
    digitalWrite(column4Pin, HIGH);
    pinMode(column4Pin, INPUT);
    */

    // Process the working copies of the ISR data.
    // You will need to change the state machine logic to process column4Pressed obtained from the ISR.

    switch (state)
    {
    case State::OFF:
        break;
    case State::IDLE:
        break;
    case State::LISTEN_KEY:
        break;
    case State::PLAYER:
        break;
    }
}

void hookOffToggle()
{
    isr_hookOffState = digitalRead(hookPinA);
}

void interruptToggle()
{
    isr_interruptState = 1;
}

void interruptColumn4()
{
    // Test whether any button in column 4 is pressed.
    isr_column4Pressed = !digitalRead(52) || !digitalRead(50) || !digitalRead(48) || !digitalRead(46);
}

```

Here is the Wokwi simulation which uses an Arduino Mega and pin 2 for the column 4 interrupt. Note that there is no protection resistor between pins 2 and 38. The Wokwi simulator will create a Value Change Dump (VCD) file for viewing in your favourite trace analyser:

Alternatively, if you don't want to use interrupts, you could pull column 4 (pin 38) low and test the row pins for a logic low. See the commented code in `loop()`.

---
Tags: interrupt, arduino-due, sound, keypad
---


title: Need help in writing a function

text:
# Question
Title: Need help in writing a function
I am reading an accelerometer using arduino. Basically i receive positive values and I need to get only first row of negative values. E.g. I receive values \> -0.5 , then I start to have values \< -0.5 (which i put them into an array , and then in case I get again values greater than -0.5 I want to stop it.

Also if in 30 seconds it should stop anyway. This is what I did till now but is not working like expected

```
void reading_mpu_brake(){
          unsigned long StartTime = millis();

      float acc[500];
      int read_time[500];

      byte arrayIndex = 0;

    while(1){
      unsigned long CurrentTime = millis();
      if (CurrentTime - StartTime < interval) {
        mpu.update();
        if (mpu.getAccX() < -0.05){
          total_acc = sqrt((pow((mpu.getAccX() - offsetx), 2) + pow((mpu.getAccY() - offsety), 2) + pow((mpu.getAccZ() - offsetz), 2) ));

          acc[arrayIndex] = total_acc;
          read_time[arrayIndex] = millis();

          Serial.print(acc[arrayIndex]);
          Serial.print(" | ");
          Serial.print(mpu.getAccX());
          Serial.print(" | ");
          Serial.println(read_time[arrayIndex]);
          Serial.println(arrayIndex);
           arrayIndex++;
        }
      }
      else if (CurrentTime - StartTime > interval)
      {
        Serial.println("Over time");
        break;

      }

    }

```

Now is working and get values less than -0.5 but if after several good values if I get positive values and then again negative it will put in array also the last one which I don t.

So basically I need to stop it after first bunch of good values...

Any help appreciated

Thank you!

L.E. Seems I miss a good explanation so I will try again.

1 - I call the function and it start monitoring values for 30 seconds.

Case 1 : I receive 0.6 , 0.7 , 0.4 , 0.2 , -0.2 , -0.6 , -0.7 , -0.8 , -0.4 , 0.3 , 0.5 ...etc

In this case I get into acc array values : -0.6 , -0.7 , -0.8 then after 30 sec gone the function exit

That is OK partially .

Case 2 : I receive 0.6 , 0.7 , 0.4 , 0.2 , -0.2 , -0.6 , -0.7 , -0.8 , -0.4 , 0.3 , 0.5 , -0.6 , -0.7 , 0.6...etc

In this case I get into array values -0.6 , -0.7 , -0.8 and if the 30 secs are not gone I also get -0.6 , -0.7 .

What I want is function to exit after get first bunch of good values (-0.6 , -0.7 , -0.8) .

Hope now is more clear

# Answer
> 5 votes
```
float acc[500];
int read_time[500];

```

Right, so a float is 4 bytes on this platform, so that array takes 2000 bytes. And an int is 2 bytes, so that other array is another 1000 bytes.

The Uno has 2KB of RAM, so those two declarations alone take up more RAM than the device has.

I'm a little surprised it works at all, but certainly "not working as expected" is indeed an expected outcome here.

---
Tags: arduino-uno
---


title: 'GIMSK' was not declared in this scope

text:
# Question
Title: 'GIMSK' was not declared in this scope
I'm programming an ATTiny 85 using the Arduino IDE and an Arduino Nano as "Arduino as ISP" to program the ATTiny. I succeeded a week ago and now I want to program a second chip but get the `'GIMSK' was not declared in this scope` error during compile.

The GIMSK is called at the start of the `sleep()` function. I tried adding `#include <avr/interrupt.h>` but continue to receive the compile error.

```
#include <avr/sleep.h>    // Sleep Modes
#include <avr/power.h>
#include <elapsedMillis.h>
const int hallPin = 2;     // the number of the hall effect pin
const int magnetPin =  1;      // the number of the magnet pin
const long debouncing_time = 15; //Debouncing Time in milliseconds
// variables will change:
volatile int hallState = 0;         // variable for storing the hall counter
volatile unsigned long last_micros;
elapsedMillis timer;

void setup()
{
  pinMode(magnetPin, OUTPUT);
  pinMode(hallPin, INPUT);
  digitalWrite(hallPin, HIGH);    // pullup enabled.
  // Attach an interrupt to the ISR vector
  attachInterrupt(0, pin_ISR, RISING); //default interupt pin is always 0 on attiny85 (physical pin 7)
  timer = 0;
}

void sleep()
{
    GIMSK |= _BV(PCIE);                     // Enable Pin Change Interrupts
    PCMSK |= _BV(PCINT2);                   // Use PB2 as interrupt pin
    ADCSRA &= ~_BV(ADEN);                   // ADC off
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);    // replaces above statement
    sleep_enable();                         // Sets the Sleep Enable bit in the MCUCR Register (SE BIT)
    sei();                                  // Enable interrupts
    sleep_cpu();                            // sleep
    cli();                                  // Disable interrupts
    PCMSK &= ~_BV(PCINT2);                  // Turn off PB2 as interrupt pin
    sleep_disable();                        // Clear SE bit
    ADCSRA |= _BV(ADEN);                    // ADC on
    sei();                                  // Enable interrupts
} // sleep
etc.

```

Can anyone give me a pointer? I had saved my work so I'm puzzled by the error.

Thank you.

---

Solution:

*Programming configuration for the ATTiny 85 via the Nano as ISP.*

# Answer
In order to program the ATtiny85, you need a suitable board support package, and you have to configure the Arduino IDE in order to target that specific chip.

From the description of your issue, it sounds like you did that a week ago, and then, maybe by accident, you undid the IDE configuration. Now the IDE is targeting a type of MCU that does not have a register named `GIMSK`. Double check that you have the right target configured.

Another possibility would be that the Arduino.h file for the core you are using does not automatically include avr/io.h. If this is the case, add

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

```

at the top of your code.
> 0 votes

---
Tags: attiny, sleep, compilation-errors
---


# Question
Title: Why do I have to burn the code to make it run?
Why do I have to burn the code twice to actually burn it on to the Arduino board? I have to execute this command twice - only *then* is the chip getting programmed.

I'm using this command to burn the program into the Arduino Uno board using a Rasp Pi 3, via SSH from Windows 10.

```
avr-gcc -mmcu=atmega328 filename.c | avr-objcopy -O ihex -j .text -j .data a.out a.hex | avrdude -C avrdude.conf -v -p atmega328p -c arduino -P /dev/ttyACM* -b 115200 -D -U flash:w:a.hex:i

```

# Answer
> 6 votes
On a Unix shell, separating commands with the pipe character (`|`) means “run these commands in parallel, feeding the standard output of each one to the standard input of next one”.

In this context, it makes no sense to use pipes, as both avr-objcopy and avrdude read their data from files, not from stdin. Furthermore, running these in parallel means that avrdude will *not* have access to a.hex when it starts.

The solution is to run the commands *sequentially* instead of in parallel. Type and run one command at a time.

Alternatively, if you really want to have everything in a single line, separate the commands with a semicolon (`;`, meaning “run the next command when the previous one is done”) or, better yet, double ampersand (`&&` = “run the next command only if the previous one exits successfully”).

---
Tags: raspberrypi, avr-gcc, ssh
---


# Question
Title: Divide two integers resulting into a float
Suppose I want to divide two integer variables and put the result into a float. In order to prevent integer division do I have to program like this:

```
    int i = 6312;
    int j = 258;
    float f;
    f = i;
    f = i/j;

```

Or can I straightforward program like below and the compiler makes sure it is handled the 'proper' way:

```
    f = i/j;

```

# Answer
Cast the integers to float before doing the calculation.

```
float f = float(i) / float(j);

```

or

```
float f = (float) i / (float) j;

```

Always be clear how the calculation should be done, so the compiler will do what you want it to do.
> 4 votes

# Answer
As Arduino is C++, you should *really* use a static cast, to be technically accurate. However, for Arduino code it probably doesn't really matter.

So either

```
float f = static_cast< float >(i) / static_cast< float >(j);

```

or

```
float f = static_cast< float >(i) / j;

```

**Note**: Using a static cast on each operand, rather than just one, is useful to quiet any warnings about the loss of precision with `int` to `float`, which typically needs to form a rounded `float` for large `int` values.

See C++ int float casting for more info.

---

Just to add to Jot's answer: Strictly speaking, it should be pointed out that `(float)` is C, whereas `float()` is C++.

---

Also, as you had meant to write in your question:

```
int i = 6312;
int j = 258;
float f;
f = i;
**f = f/j;**
```

Yes, that would work. However, even though it seems quite elegant, it could cause confusion later in time, when someone else examines the code - unless you added a comment explaining why.

it is probably best to keep the code simple and obvious (for debugging purposes) unless you are deliberately intending to obfuscate the code.
> 1 votes

---
Tags: programming-sequence
---


# Question
Title: How to light up middle points in a display with 4 digits?
How to light up the two points that is in the middle? It only lights up when the `digB` is set to `LOW`, and it lights up all 3 points that is in the middle.

Example code:

```
const int displayPins[] = {2,3,4,5,6,7,8,9,10,11,12,13};
const int digA = 7;
const int digB = 4;
const int digC = 3;
const int digD = 8;
const int decimalPoint = 10;

void setup() {
    for (int i = 0; i < (sizeof(displayPins)/sizeof(displayPins[0])); i++) {
        pinMode(displayPins[i], OUTPUT);
    }

    digitalWrite(digA, 1);
    digitalWrite(digB, 0);
    digitalWrite(decimalPoint, 1);
    digitalWrite(digC, 1);
    digitalWrite(digD, 1);
}

void loop() {
}

```

I want to display a clock in this format: 00:00. But did not found a way to light up the two points that is in the middle.

# Answer
> 2 votes
It is not possible to separate the colon dots from the decimal point dot - they are all wired together in parallel internally:

As has been mentioned in the comments you need to use the "black tape" method of selecting the LEDs. That's not a joke, that's really what's done. Cover the LED that you don't want visible with black tape (or black paint, etc).

---
Tags: arduino-uno, display
---


# Question
Title: Arduino How can I add 30s delay and turn off the led to the following code
```
const int buttonPin =  2;
boolean currentState = LOW;
boolean lastState    = LOW;
boolean stateChange  = false;

int currentButton = 0;
int lastButton    = 4;
int ledArray[]    = {9, 10, 11, 12};
long previousMillis = 0;
long interval = 1000 ;

void setup() {
        pinMode(buttonPin, INPUT);
        for (int i=0; i<5; i++){
            pinMode(ledArray[i],OUTPUT);
        }
        Serial.begin(9600);
}

void loop(){
            currentState = debounceButton();
            stateChange = checkForChange(currentState, lastState);
            currentButton = getButtonNumber(lastButton, currentState, stateChange);
            indicatorLight(currentButton);
            lastState  = currentState;
            lastButton = currentButton;
}

boolean debounceButton()
            {
            boolean firstCheck   = LOW;
            boolean secondCheck  = LOW;
            boolean current = LOW;
            firstCheck  = digitalRead(buttonPin);
            delay(50);
            secondCheck = digitalRead(buttonPin);
                    if (firstCheck == secondCheck){
                        current = firstCheck;
                    }
            return current;
}

boolean checkForChange(boolean current, boolean last)
        {
        boolean change;
                if (current != last){
                    change = true;
                }
                        else {
                        change = false;
                        }
                return change;
}

int getButtonNumber(int button, boolean state, boolean change)
            {
            if (change == true && state == LOW){
                button++;
                        if (button > 3){
                        button = 0;
                        }
                        Serial.println("g");

            }
            return button;
}

void indicatorLight(int button)
         {
                for (int i=0; i<4; i++) {
                            digitalWrite(ledArray[i], LOW);
                        }
                        digitalWrite(ledArray[button], HIGH);
  }

```

# Answer
> 1 votes
You have the right idea to debounce the buttons, but there is a 50 ms delay per button which blocks the loop for a total of 200 ms with four buttons.

So consider using a non-blocking debouncer of which there are many examples on the internet, but here is a simple debouncer I put on GitHub. It could be implemented something like the following example:

```
#include "debouncer.h"

const uint16_t LED_OFF_TIME_DELAY_ms = 2000;  // milliseconds. For testing.
//const uint16_t LED_OFF_TIME_DELAY_ms = 30000;  // milliseconds.

struct ButtonLed
{
  Debouncer button;
  byte button_pin;
  byte led_pin;
};

const ButtonLed BUTTONS_LEDS[] =
{
  { Debouncer(5, 50, LED_OFF_TIME_DELAY_ms), 5, 11 },
  { Debouncer(4, 50, LED_OFF_TIME_DELAY_ms), 4, 10 },
  { Debouncer(3, 50, LED_OFF_TIME_DELAY_ms), 3, 9 },
  { Debouncer(2, 50, LED_OFF_TIME_DELAY_ms), 2, 8 }
};

void setup()
{
  for (const auto& button_led : BUTTONS_LEDS)
  {
    pinMode(button_led.button_pin, INPUT_PULLUP);
    pinMode(button_led.led_pin, OUTPUT);
    digitalWrite(button_led.led_pin, LOW);
  }
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop()
{
  uint16_t timestamp = millis();

  //
  // TASK 1: Read the buttons and set their corresponding LEDs.
  //

  for (const auto& button_led : BUTTONS_LEDS)
  {
    button_led.button.Update();
    if (button_led.button.Fall())
    {
      digitalWrite(button_led.led_pin, HIGH);
    }
    else if (button_led.button.RepeatCount() == 1)
    {
      digitalWrite(button_led.led_pin, LOW);
    }
  }

  //
  // TASK 2: Blink the inbuilt LED.
  //

  const uint16_t LED_BLINK_INTERVAL = 100;
  static uint16_t led_blink_previous_timestamp = timestamp;
  static bool led_state = false;
  if (timestamp - led_blink_previous_timestamp >= LED_BLINK_INTERVAL)
  {
    led_state = !led_state;
    digitalWrite(LED_BUILTIN, led_state);
    led_blink_previous_timestamp += LED_BLINK_INTERVAL;
  }
}

```

And here it is in action in the Wokwi simulator:

---
Tags: arduino-uno
---


title: Powering Atmega328p from 4.5V

text:
# Question
Title: Powering Atmega328p from 4.5V
I want to use Atmega328p controller to handle some very simple signals. I'm using the chip and not the whole arduino board because it is a lot cheaper. The problem is that chip itself doesn't have voltage regulator so I need to think of a rechargeable power source. My idea is to use 3 rechargeable AA batteries (~4.5V). I read that it can handle somewhere from 1.5V to 5.5V but I also read that clock speed is then reduced and a lot other complications. So, finally, the question, If I were to use described power source, what challenges should I be ready to face and how will it impact the performance and is it even possible to pull it off.

# Answer
> 9 votes
From the ATmega328P datasheet:

Within the range 2.7 V – 4.5 V, the maximum frequency is a linear function of Vcc. From this graph, you can compute the minimum value of Vcc required to run the microcontroller at 16 MHz: it's 3.78 V.

If you do want to run at 16 MHz, in order to emulate an Arduino Uno, it may become unreliable once the supply voltage drops below 3.78 V, i.e. 1.26 V per cell. Whether this is a serious issue or not depends on the cell chemistry. For reference, alkalines reach about 1 V at the end of their useful life, and NiCd has about 1.2 V when fully charged. You will have to find the relevant voltage for the chemistry you plan to use.

If you can afford running the microcontroller at 8 MHz, then you will most certainly be safe.

**Edit**: If you want to run the microcontroller at 8 MHz, and you are programming it with the Arduino IDE, you have to select a board/processor combination that runs at 8 MHz. For example, “Arduino Pro or Pro Mini” / “ATmega328P (3.3V 8MHz)”. This will ensure that the time-related functions (`millis()`, `delay()`, etc.) and the baudrates of `Serial.begin()` provide the correct timings. Other than that, the drawback of running at a lower clock speed is that the CPU-bound functions (computations) take twice as long.

# Answer
> 1 votes
They make SEPIC converters that will hold the voltage at 5V for you. The reason for the SEPIC is during charge what happens to the battery voltage and especially if the battery open circuits. If there is no chance for the battery voltage to go to high a boost converter will work just fine. This solution will allow it to run at full speed without degrading performance etc. The new converters are not very expensive and are generally greater than 95% efficient depending on the unit. If you can up the battery voltage things will get a lot more efficient but you would then need to change the boost to a buck, the SEPIC would be fine. I tend to use the China Nanos, they are inexpensive, probably less then your parts and readily available. I have not had problems with them. I like to supply them with about 8 volts via Vin, that gives me the additional filtering of the onboard power supply.

---
Tags: atmega328
---


title: How to see log from Arduino IDE?

text:
# Question
Title: How to see log from Arduino IDE?
Where can I see outputs from such instruction in an ino file ?

```
Serial.println("my message");

```

# Answer
> 5 votes
The Serial.print statements show up on whatever terminal program is opened and connected. Their can be only one open at a time, but it could the Arduino IDE built in monitor (ctl-shft-m) or an external terminal program, eg putty, or some other program you wrote that opened the com/serial port the Arduino is on.

Remember though - only 1 can be open at a time. If you use an external program you MUST close the com port before attempting to download a new version of your sketch. If you use the built in monitor/terminal it will automatically do this for you.

# Answer
> 3 votes
It took me ages to realize that instead of remembering Ctrl-Shft-M you can just click on the little magnifying glass in the upper right of the IDE interface. Wait until after your script uploads though, it won't do anything while compiling or uploading your script.

# Answer
> 1 votes
Call `Serial.begin(9600)` in your `setup()` function:

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

```

Call `Serial.print('example')` or `Serial.println('example')` in your `loop()` function (or one of your own functions that your `loop()` function calls:

```
void loop() {
  Serial.print('example');
  Serial.print('example');
  // Output of the two calls above: exampleexample
  Serial.println('example');
  Serial.println('example');
  // Output of the two calls above:
  // example
  // example
}

```

Go to **Tools** \> **Serial Monitor** to see the output.

References:

---
Tags: arduino-ide
---


title: ATtiny85 plugin and removed it self

text:
# Question
Title: ATtiny85 plugin and removed it self
So I bought ATtiny85 recently, when I plug it to my PC it make sound like mouse has been plugin, but then it make sound like the device has been removed. It happen again and again until I remove the device. Is it the device problem or am I missing something? Can I fix it?

# Answer
I'm assuming you've bought a Digispark (or compatible) ATTiny85 USB board.

The sound of a USB device inserting and removing is normal. When the digiSpark boots it listens to the USB bus for a short period so you can upload your sketches. Then it proceeds to boot your sketch.

If no sketch has been uploaded, it might just reboot until you upload one. The Digisparks I have, have all had a "blink" sketch preloaded but yours may not.

The "problem" will go away when you start running your own sketches. It will then only announce itself once and then remove itself from the USB bus, unless your sketch also communicates via the USB bus.
> 2 votes

---
Tags: hardware, attiny85
---


title: Problem in upload bootloader into esp32

text:
# Question
Title: Problem in upload bootloader into esp32
I have problem with my esp32 Device and asked one question as you can see below:

How to understand the ESP32 is working (Error: Arduino unknown board ...)

As it is not fixed, so I am thinking to upload the bootloader codes on the ESp32. SO I have tried the ArduinoISP example codes and tried to use the bootloader icon on Arduino, but it doesn't work, and I get below error:

```
java.lang.NullPointerException
    at cc.arduino.packages.uploaders.SerialUploader.burnBootloader(SerialUploader.java:329)
    at processing.app.Editor.lambda$handleBurnBootloader$61(Editor.java:2379)
    at java.base/java.lang.Thread.run(Thread.java:829)
Error while burning bootloader.

```

Also, the whole process is show below:

So I have asked here for some comments or answers.

Thanks.

# Answer
1. esp32 has a fixed bootloader in read only memory. it is not replaceable
2. ArduinoISP sketch is a programmer only for classic ATmega MCU boards
3. in valid case you would have to select the programmer in Tools menu before using Burn Bootloader. (There are no options in your Programmer menu, because no programmers are defined for esp32 boards package)
> 3 votes

---
Tags: bootloader, compilation-errors
---


# Question
Title: ESP8266: error: 'getLocalTime' was not declared in this scope
I am getting

> error: 'getLocalTime' was not declared in this scope

when I am compiling this code for ESP8266, however works for ESP32:

```
#include "time.h"

void gettime()
{
  static int16_t delaycount = 0 ;                         // To reduce number of NTP requests
  static int16_t retrycount = 100 ;

  if ( timeinfo.tm_year )                                 // Legal time found?
  {
    sprintf ( timetxt, "%02d:%02d:%02d",                  // Yes, format to a string
              timeinfo.tm_hour,
              timeinfo.tm_min,
              timeinfo.tm_sec ) ;
  }
  if ( --delaycount <= 0 )                                // Sync every few hours
  {
    delaycount = 7200 ;                                   // Reset counter
    if ( timeinfo.tm_year )                               // Legal time found?
    {
      dbgprint ( "Sync TOD, old value is %s", timetxt ) ;
    }
    dbgprint ( "Sync TOD" ) ;
    if ( !getLocalTime ( &timeinfo ) )                    // Read from NTP server
    {
      dbgprint ( "Failed to obtain time!" ) ;             // Error
      timeinfo.tm_year = 0 ;                              // Set current time to illegal
      if ( retrycount )                                   // Give up syncing?
      {
        retrycount-- ;                                    // No try again
        delaycount = 5 ;                                  // Retry after 5 seconds
      }
    }
    else
    {
      sprintf ( timetxt, "%02d:%02d:%02d",                // Format new time to a string
                timeinfo.tm_hour,
                timeinfo.tm_min,
                timeinfo.tm_sec ) ;
      dbgprint ( "Sync TOD, new value is %s", timetxt ) ;
    }
  }
}

```

What shall I replace getLocalTime with?

# Answer
It looks like the esp8266 Arduino core don't have a similar function.

The getLocalTime in esp32 arduino core is a simple function implemented in esp32-hal-time.c.

```
bool getLocalTime(struct tm * info, uint32_t ms)
{
    uint32_t start = millis();
    time_t now;
    while((millis()-start) <= ms) {
        time(&now);
        localtime_r(&now, info);
        if(info->tm_year > (2016 - 1900)){
            return true;
        }
        delay(10);
    }
    return false;
}

```

The function compiles on esp8266 arduino as it is so you can copy it to your sketch.
> 3 votes

---
Tags: esp8266, c++, time
---


title: ATtiny85 won't wake from sleep

text:
# Question
Title: ATtiny85 won't wake from sleep
My ATtiny 85 won't wake up!

The purpose of the device is to monitor a reed switch and give a 20 ms output pulse on every alternate positive-going transition of the reed switch input. The device should go to sleep after 30 s of inactivity. It should wake up on reed switch activity (rising or falling edge).

```
/*
          ATMEL ATTINY 85
              +-\/-+
        PB5  1|    |8  Vcc
        PB3  2|    |7  PB2 (INT0) reed switch input (1 MΩ ext. pull-up)
        PB4  3|    |6  PB1        output
        GND  4|    |5  PB0
              +----+
*/
#include <avr/sleep.h>
#include <avr/power.h>
#include <elapsedMillis.h>

const int hallPin = 2;            // Reed switch in this case.
const int magnetPin =  1;         // Output.
const long debouncing_time = 15;  // Debouncing time in milliseconds.

volatile int hallState = 0;       // variable for storing the hall counter
volatile bool hallMem = 0;        // One-shot memory.
volatile unsigned long last_micros;

elapsedMillis timer;

void setup(){
  pinMode(magnetPin, OUTPUT);
  pinMode(hallPin, INPUT);
  // Attach an interrupt to the ISR vector. DO I NEED THIS?
//  attachInterrupt(0, pin_ISR, RISING); //default interupt pin is always 0 on ATtiny85 (physical pin 7).
  timer = 0;                             //Reset the timer
}

void loop(){
  if(digitalRead(hallPin) && !hallMem){
    hallMem = true;               // One-shot memory.
    hallState++;
    delay(debouncing_time);       // Keep it simple.
    timer = 0;
  }
  if(!digitalRead(hallPin)){
    hallMem = false;              // Allow re-trigger.
  }
  if(hallState > 1) {
      digitalWrite(magnetPin, HIGH);        // Send 20 ms pulse to sensor activation coil.
      delay(20);
      digitalWrite(magnetPin, LOW);
      hallState = 0;                        // Reset the trigger.
  }
  if(timer >= 30000) {                      // No activity.
    system_sleep();
  }
}

// From http://interface.khm.de/index.php/lab/experiments/sleep_watchdog_battery/
void system_sleep() {
  GIMSK |= _BV(PCIE);                     // Enable Pin Change Interrupts
  PCMSK |= _BV(INT0);                     // Use INT0 (PB2) as interrupt pin
  ADCSRA &= ~_BV(ADEN);                   // ADC off
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);    // replaces above statement

  sleep_enable();                         // Sets the Sleep Enable bit in the MCUCR Register (SE BIT)
  sei();                                  // Enable interrupts
  sleep_cpu();                            // sleep

  cli();                                  // Disable interrupts
//  PCMSK &= ~_BV(INT0);                  // Turn off INT0 (PB2) as interrupt pin
  sleep_disable();                        // Clear SE bit
  ADCSRA |= _BV(ADEN);                    // ADC on

  sei();                                  // Enable interrupts

  timer = 0;          // Reset the sleep timer on wake-up.
}

ISR(PCINT0_vect) {
}

```

Can anyone spot my error that is preventing a wake-up?

What is the ADC enabling instruction doing? Do I need it?

Many thanks.

# Answer
I believe your problem lies here:

```
PCMSK |= _BV(INT0);  // Use INT0 (PB2) as interrupt pin

```

You seem to have mixed up two sorts of interrupts:

1. INT0 (External Interrupt), which only works on pin INT0 (i.e. PB2) and can sense low-level, rising edge, falling edge, or any change.
2. PCINT0 (Pin Change Interrupt), which works on any IO pin, but can only sense “any change”.

Since you are sleeping in PWR\_DOWN mode, pin change interrupt is the appropriate choice. All your program is consistent with this choice but for the line above.

The `INT0` macro has the value 6. It represents bit 6 of `GIMSK`, which is used to enable the INT0 interrupt. Not what you want. Bit 6 of `PCMSK` is reserved, so you are not supposed to touch it. If you want the pin change interrupt to sense changes in pin PB2 (aka PCINT2), you instead have to:

```
PCMSK |= _BV(PCINT2);  // sense changes in PCINT2 = PB2

```
> 3 votes

---
Tags: sleep, attiny85
---


# Question
Title: Hacking old car dvd monitors with arduino
I got this old junk LCD from my car. The DVD function stopped and the LCD holder on the top of the car broke, so I took it.

Is there any documentation or advice I could use to get this working with an Arduino mega or clone of similar power? I couldn't find anything after looking through Google.

I.e. I'm looking for a way to get a pinout or idea of what those wires on the jack are so that I might be able to get text and/or basic graphics on the screen. Maybe to make an Arduino PC or something idk.

Any advice on either figuring out the connections by hand and how to get a simple connection to the Arduino to get bsic stuff working or a place I can find pinout and such or where someone else has done something similar would be helpful.

**Update 2** A quick Google search reveals that it's made by sharp I believe. I'm looking into it.

**Update** Here's is the back. It's got quite a few numbers on it. Maybe one of those can help?

Top Numbers: D 09399847 LQ070T5CRQ2 46009355

And the one on the bottom: K4013TP

# Answer
I realize this is an ancient question, but just in case someone else has one of these things, I'll share what I know. I have one of these Sharp LCDs that I typically use as a monitor for a Commodore 64. I believe mine was originally from a rear seat DVD player in a Ford Explorer.

Looking at the rear of the unit, with the two connectors on the bottom, the leftmost connector is CN2 and the rightmost is CN1. I know nothing of CN2, but here's what I know about CN1:

Pins 1 through 15, from left to right:

1. NTSC composite video in
2. ground
3. ground
4. ?
5. +12VDC in
6. ?
7. ?
8. ?
9. ?
10. ?
11. ?
12. +12VDC in
13. +12VDC in
14. ground
15. ground

I'm sure the other pins have additional functionality, but I'm not aware of it. Hopefully this helps someone.

EDIT: I found the datasheet in my files: https://byteshiftmusic.com/media/Sharp\_LQ070T5CRQ2.pdf
> 4 votes

# Answer
Your best bet is to try to take the casing off until you find a company name so that you can get a lead on where to look for documentation. Because until you find out more about how that screen works, it's a black box to you and you don't know what to put in it. No one else will be able to help you until you provide more information to this extent because no one else can hold it in their hands, and the photo of the socket that you showed us doesn't look like a common display format either.

Also, you're very unlikely to make a PC-type thing out of this. That depends on the power of the computer behind the display and an arduino isn't that powerful. You want a Pi. Or maybe I'm misunderstanding what you want. You could easily get a scrolling text type thing going or maybe even a game (if you figure out how to make it work).

Edit: I just looked up a sample LCD screen and it has 6 signal pins and power and ground. Yours looks like it has a lot more. So you definitely have some digging to do.
> 3 votes

---
Tags: arduino-mega, lcd, communication, teensy
---


# Question
Title: I want to program multiple arduino at once
I am aware that using a USB Hub you can attach multiple arduino to one computer and either upload code one by one or use bash script to upload code on all arduinos together. But you can attach only as many arduino to a computer. I need to prgram around 100 arduinos/atmega ICs at once. Is there a way to do so? There are other methods that I found online like programming ICs over Wifi network. But that require a lot of WiFi chips connected to arduino. I cant setup that. Also that doesn't seems cost effective. Also Arduino sells their uno and other boards with pre-installed blink program. They must be doing batch programming only (multiple ICs at once). Any idea how they do this?

# Answer
Arduino, the company, may sell on enough volume to make it worthwhile to get the microcontroller manufacturer to program the microcontrollers durin the production process This wouldn't cost them extra if they already get the bootloader pre-programmed. I've read programming ICs is a service available to high volume customers.

I guess low volume makers use fixtures that use the ICSP headers, pogo sticks or IC clips and which trigger the programming on contact using a microswitch etc.

I suspect Adafruit do something of this sort, see GIFs and video discussing testing at

https://www.adafruit.com/product/2458
> 1 votes

# Answer
I recommend using optiloader, which uses a standalone arduino to program an arduino connected to it. You can therefore create as many arduino programmers as you want, each of which can run without connecting to a host computer. This is how firmware is loaded for high volume production.
> 1 votes

# Answer
> Any idea how they do this?

You can buy gadgets that let you upload code in a second or so. For example, here. You plug in the target board, press a button, and it's done.

These program a board in a couple of seconds. While this is hardly literally "at once" it would take time anyway to connect 100 Arduinos to "something" so connecting and disconnecting every couple of seconds is roughly the same thing.

That board mentioned above uses code I wrote which can run on an ordinary Arduino. In other words, use one to program another, where the code to be uploaded is stored on a micro-SD card.
> 0 votes

---
Tags: arduino-uno, programming, uploading
---


# Question
Title: Unable to find headers from installed platformio library
I wrote a library that I intend to use in several project and I published it via platform.io's library management system.

https://platformio.org/lib/show/12820/FastLED-SectionManager

This is the first time I've published via platform.io (first time I've published any c++ library). I read over platform.io's docs on creating a library and structured my library accordingly with my headers in the `include` directory and the implementation files in the `src` directory:

And created the following library.json file:

```
{
  "name": "FastLED-SectionManager",
  "version": "1.0.2",
  "description": "A led strip index manager that allows for logical groupings of strip sections.",
  "repository": {
    "type": "git",
    "url": "git@github.com:chris-schmitz/FastLED-Section-Manager.git"
  },
  "authors": [
    {
      "name": "Christopher Schmitz",
      "email": "schmitz.chris@gmail.com",
      "url": "https://light-inspiration.com/"
    }
  ],
  "homepage": "https://github.com/chris-schmitz/FastLED-Section-Manager",
  "license": "MIT",
  "dependencies": {
    "fastled/FastLED": "^3.4.0"
  },
  "frameworks": "*",
  "platforms": "*"
}

```

The problem that I'm running into is that when I install the library in a different project via platform.io and try to include a header, the header can't be found:

I double checked in the `pio` directory for the project and I can definitely see the header and implementation files:

So I'm not sure why platform.io can't find the headers.

I can't quite tell what I'm doing wrong. any ideas?

# Answer
> 1 votes
I woke up this morning and looked back at the documentation.

A part I mis-read was this:

> We recommend to use src folder for your C/C++ source files and **include folder for your headers**. You can also have nested sub-folders in src or include.

I had my headers stored in the `lib` folder :facepalm:

I tried to search around in the platformio docs for the explanation of the lib vs include vs src folders (I knew I saw it at one point) but couldn't find it.

I then remembered that I read the purpose of each directory in the Readme files in the project structure itself generated when you create a new platformio project:

The gist being:

* `src`: your compiled files, i.e. your `cpp` files
    + It's worth noting that you could just shove all of the files in here and it would work
* `lib`: libraries private to your project/library itself
* `include`: declaration and macro definition files, i.e. your header files

This explains how the header files in the `lib` directory worked in the SectionManager project itself but didn't work when using the SectionManager as an installed library; the `lib` directory is only "visible" local to a project, so when I tried to include the header files from another project they couldn't be found.

So in my SectionManager project I moved the headers to the `include` directory, bumped the version number, and published:

Then I switched to my main project that I'm pulling the SectionManager library into, adjusted the dependency version to include the minor bump, updated, and now it works!

Makes sense, I'm just still getting used to c++ and platform.io.

---
Tags: library, platformio
---


title: Changing single bit in byte array

text:
# Question
Title: Changing single bit in byte array
So I have a `byte`-array representing the display attached to my Arduino:

```
byte theDisplay[8] = {
    B00000000,
    B00000000,
    B00000000,
    B00000000,
    B00000000,
    B00000000,
    B00000000,
    B00000000
};

```

Now I want to flip a single bit at an arbitrary position:

```
theDisplay[3][6] = 1;

```

This (probably) faulty method produces these errors:

```
In function 'void setup()':
sketch_sep14c:13:18: error: invalid types 'byte {aka unsigned char}[int]' for array subscript
   theDisplay[3][6] = 1;
                  ^
exit status 1
invalid types 'byte {aka unsigned char}[int]' for array subscript

```

Is there an easy way to flip a single bit working with indexes like shown above?

# Answer
> 1 votes
The error occurs, because you try to use the syntax for a 2 dimensional array with a 1 dimensional array (since you have an array of bytes, not bits, and a microcontroller always works with at least one byte). For accessing the individual bits you need to use bitwise operators. For example this:

```
theDisplay[3] |= (1 << bitnumber); // for setting the bit
theDisplay[3] &= ~(1 << bitnumber); // for clearing the bit

```

with `bitnumber` being the number of the bit to change counted from least significant bit (in the binary representation in your code the rightmost digit) to most significant bit (the leftmost digit).

If you want to know, what exactly this does, you can google for bitwise operators in C++.

---
Tags: arduino-uno, bit, bytes
---


title: GSM and GPS module don't work together

text:
# Question
Title: GSM and GPS module don't work together
I am trying to create a project which involves getting latitude and longitude via GPS Module and send it via GSM Module. My problem here is that individual code is working perfectly. However, if am to initialize both together, none will work.

```
#include "GSM.h"//wrapper class for Sim800l library
#include "GPS.h"//wrapper class for TinyGPS library
GSM *gsm;
GPS *gps;
void setup()
{
    Serial.begin(9600); // Debugging only
    gsm = new GSM();//initializes SIM800l
    //gps = new GPS(11,10 );//initializes NEO6MV2//uncommmenting this line won't make both modules work
}
String telNum;
int i = 1;
void loop()
{
    /*
    Serial.println(gps->getLongitude(),6);
    Serial.println(gps->getLatitude(),6);
    */

    Serial.println(gsm->read(i,telNum));
    Serial.println(telNum);
     ++i;
}

```

# Answer
> 1 votes
I got it working by initializing and deleting the pointer to the GPS and GSM object.

Initialization and freeing of the objects are made in the loop function. I initialize the GPS, run it in a loop for sometime, destroy it and initialize the GSM and same procedure as GPS.

Though I don't know if it'll have any effects but its working perfectly

```
#include "GSM.h"
#include "GPS.h"
GSM *gsm;
GPS *gps;
void setup()
{
    Serial.begin(9600); // Debugging only
}

unsigned long previousMillis = 0;//could be any value depending on how quick you want it to elapse
const long interval = 100; //could be any value depending on how long you want it to run
void loop()
{
    gps = new GPS(6, 7);//initialization <SoftwareSerial::begin() function called here>
    while (previousMillis <= interval)
    {
        //GPS codes here
        ++previousMillis;
    }
    delete gps;         //destory initialized object
    previousMillis = 0; //reset value

    gsm = new GSM();    //initialization <SoftwareSerial::begin() function called here>
    while (previousMillis <= interval)
    {

        //GSM codes here
        ++previousMillis;
    }
    delete gsm;//destory initialized object

    previousMillis = 00;//reset value
}

```

# Answer
> 0 votes
You can't use two softwareserial devices together (or not reliably, and not without knowing exactly what you are doing).

It's not even easy using one software and one hardware serial together unless you know what you are doing.

SoftwareSerial blocks everything else from happening while it's sending or receiving, so using it for things that send unsolicited messages (as GPSs do all the time) causes havoc.

The best you can hope for is to use HardwareSerial for the GPS and SoftwareSerial for the GSM, which is call-and-response most of the time.

Better would be to use a better board that has multiple hardware serial ports.

# Answer
> 0 votes
You can use Listen function for example:

```
First_softwareserial.listen();// when you need gsm serial

```

```
Second_softwareserial.listen();// when you need gps serial

```

---
Tags: arduino-uno, gsm, softwareserial, gps
---


# Question
Title: Accidentally plugged in Arduino Uno before installing software, now it's not recognized by Windows 10, only powered by usb port
Just got a new Arduino Uno, accidentally plugged it in before installing the IDE and windows installed its drivers and had it under ports as a generic device on COM3 (it wasn't named Arduino Uno on device manager).

When I installed the IDE, I couldn't upload sketches to the board because it wasn't recognized. So I uninstalled the device from device manager and also the IDE. I pressed the reset button on the Uno, restarted my PC, reinstalled the IDE, then plugged in the Uno. Since then however, the device isn't read by Windows at all; device manager doesn't show it anywhere, nor does it even refresh when plugged in.

I tried this restarting/reinstalling process multiple times, it's also not a cable issue because I checked for that as well. The power LED is still on, and the pin 13 LED is blinking, but the Arduino isn't being recognized.

I've also tried using the Hardware Install Wizard, but that gives me

> This Device Cannot Start (Code 10)

I've been trying to run this for a while now.

# Answer
> 1 votes
You do not need to install drivers in Windows 10 (unless you have a CH340G based Chinese clone, in which case it wouldn't have detected before installing the drivers).

Windows 10 has its own CDC/ACM drivers built in - something every other operating system has had for years and Windows has only just caught up with them. That is why it detected COM3 fine before.

It should have worked fine without installing drivers. It may have been the IDE with the wrong port selected or something else interfering with the port that was stopping you using it.

Uninstall the Arduino drivers and revert to using the Windows built-in ones and work on diagnosing why it wasn't working with those.

# Answer
> 1 votes
You can always remove a unknown device in device manager (yellow exclamation point), reinstall the software, then plug the device in.

# Answer
> 0 votes
If you go to device manager and right-click the Arduino (it will probably have a yellow exclamation mark next to it). You can click update drivers. This fixed the problem for me.

---
Tags: arduino-uno, usb, windows
---


# Question
Title: Circuit to get highest reading value from multiple thermistors?
I need to measure temperature of 6 battery cells. I don't care much about individual cell readings, I just want to sound a buzzer as soon as at least one of the temperatures is above a certain threshold.

I can see the most straightforward way to do it using 6 thermistors, but that's a lot of wires going between Arduino and all these sensors. Is there any other approach that would be more lightweight? Trying to save both space and weight.

If I understand correctly, best I can do with 6 thermistors is share the GND wire and resistor between them, but then I'm still stuck with 6 * 2 + 1 = 13 wires.

# Answer
> 0 votes
DS18b20 digital thermometers use the 1-Wire protocol which requires only a single data line for a network of devices - so +V (3.3 - 5 Volts), Gnd, and Data, shared among all of them. You can even wire them in "Parasitic mode", skipping the +V, and they will get their power from the data line, so only 2 wires and 1 pin required.
From the DS18b20 Datasheet:

---
Tags: sensors, temperature-sensor, thermistor
---


# Question
Title: Two-Wire Interface (TWI) Frequency and SMBus Compatibility
Have I understood the ATmega328P datasheet correctly regarding the TWI clock frequency?

From §21.5.2 Bit Rate Generator Unit, the TWI clock frequency is calculated as follows:

Then solving for `TWBR`:

However, §8.12.2 CLKPR – Clock Prescale Register mentions that the CPU frequency is prescaled by `CLKPR`. So should the equation be:

And solving for `TWBR`:

Is the following code a correct implementation of the equations?

```
void SetFrequency(uint32_t twi_freq)
{
    if (smbus)
    {
        // SMBus clock frequency is 10 kHz to 100 kHz.
        if (twi_freq > 100000u)
        {
            twi_freq = 100000u;
        }
        else if twi_freq < 10000u)
        {
            twi_freq = 10000u;
        }
    }
    else if (twi_freq > 400000u)
    {
        // Up to 400 kHz data transfer speed.
        // §21.1 Features
        twi_freq = 400000u;
    }

    // TWI prescaler of 1.
    // Table 21-8. TWI Bit Rate Prescaler
    // TWPS1 = 0, TWPS0 = 0
    TWSR &= B11111100;

    // Achievable maximum TWI frequency with current CPU frequency, CLK prescaler and minimum TWBR with TWI prescaler of 1.
    // Rounded down to nearest integer.
    const uint32_t TWI_FREQ_MAX = F_CPU / ( ( 1 << CLKPR ) * ( 16 + 2 * 0x00 * 1 ) );

    // Achievable minimum TWI frequency with current CPU frequency, CLK prescaler and maximum TWBR with TWI prescaler of 1.
    // Rounded up to nearest integer.
    const uint32_t DIVISOR = ( ( 1 << CLKPR  ) * ( 16 + 2 * 0xFF * 1 ) );
    const uint32_t TWI_FREQ_MIN = (F_CPU + (DIVISOR - 1)) / DIVISOR;

    if (twi_freq > TWI_FREQ_MAX)
    {
        twi_freq = TWI_FREQ_MAX;
    }
    else if (twi_freq < TWI_FREQ_MIN)
    {
        twi_freq = TWI_FREQ_MIN;
    }

    // TWI bit rate.
    // §21.5.2 Bit Rate Generator Unit
    // §8.12.2 CLKPR – Clock Prescale Register
    byte bit_rate = (F_CPU / (1 << CLKPR) / twi_freq - 16) / 2

    TWBR = bit_rate;

    // Check.
    const uint32_t twi_freq = F_CPU / ( ( 1 << CLKPR ) * ( 16 + 2 * TWBR * 1 ) );
}

```

Note that `smbus` is a flag set elsewhere (global or class member) to indicate SMBus mode.

# Answer
> 0 votes
Just to confirm, in case anyone else is wondering, the second pair of equations in my question are the correct ones which take the CPU clock prescaler (`CLKPR`) into account.

TWI clock frequency:

And solving for `TWBR`:

---
Tags: i2c, atmega328, code-review
---


# Question
Title: First I2C project - Unable to get any servo movement with PCA9685
I'm working on a project where I need to run multiple servos. For now though, I'm trying to get a single MG90S servo running with a PCA9685 servo driver but I'm unable to get any movement from the servo.

What I have setup is as follows;

* Servo power is 5v 2A in the form of a standalone power supply.
* Arduino UNO GND to shield GND
* Arduino 5v to shield VCC
* Arduino A4 to shield SDA
* Arduino A5 to shield SCL (Ive also tried SDA and SCL on the uno)

The code I'm running is just the standard adafruit library example (see below) with the only change being the I2C address is set to 0x41 as I have soldiered across the first pair of pads (I have verified the new address with an I2C scanner program).

Ive tried multiple servos, two PCA9685s and two different arduinos. The servos work without the PCA9685 and I can see println info when viewing the Serial Monitor. Any ideas?

```
/***************************************************
  This is an example for our Adafruit 16-channel PWM & Servo driver
  Servo test - this will drive 8 servos, one after the other on the
  first 8 pins of the PCA9685

  Pick one up today in the adafruit shop!
  ------> http://www.adafruit.com/products/815

  These drivers use I2C to communicate, 2 pins are required to
  interface.

  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.
  BSD license, all text above must be included in any redistribution
 ****************************************************/

#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>

// called this way, it uses the default address 0x40
//Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
// you can also call it with a different address you want
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x41);
// you can also call it with a different address and I2C interface
//Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x41, Wire);

// Depending on your servo make, the pulse width min and max may vary, you
// want these to be as small/large as possible without hitting the hard stop
// for max range. You'll have to tweak them as necessary to match the servos you
// have!
#define SERVOMIN  400 // this is the 'minimum' pulse length count (out of 4096)
#define SERVOMAX  600 // this is the 'maximum' pulse length count (out of 4096)

// our servo # counter
uint8_t servonum = 0;

void setup() {
  Serial.begin(9600);
  Serial.println("8 channel Servo test!");

  pwm.begin();

  pwm.setPWMFreq(60);  // Analog servos run at ~60 Hz updates

  delay(10);
}

// you can use this function if you'd like to set the pulse length in seconds
// e.g. setServoPulse(0, 0.001) is a ~1 millisecond pulse width. its not precise!
void setServoPulse(uint8_t n, double pulse) {
  double pulselength;

  pulselength = 1000000;   // 1,000,000 us per second
  pulselength /= 60;   // 60 Hz
  Serial.print(pulselength); Serial.println(" us per period");
  pulselength /= 4096;  // 12 bits of resolution
  Serial.print(pulselength); Serial.println(" us per bit");
  pulse *= 1000000;  // convert to us
  pulse /= pulselength;
  Serial.println(pulse);
  pwm.setPWM(n, 0, pulse);
}

void loop() {
  // Drive each servo one at a time
  Serial.println(servonum);
  for (uint16_t pulselen = SERVOMIN; pulselen < SERVOMAX; pulselen++) {
    pwm.setPWM(servonum, 0, pulselen);
  }

  delay(500);
  for (uint16_t pulselen = SERVOMAX; pulselen > SERVOMIN; pulselen--) {
    pwm.setPWM(servonum, 0, pulselen);
  }

  delay(500);

  servonum ++;
  if (servonum > 7) servonum = 0;
}

```

# Answer
> 3 votes
Thanks for the reply Rowan. Current draw from the power supply with a blank arduino sketch and the pwm example sketch are 0A which is clearly the issue. I've had a look back at the website I bought these PCA9685 boards from and there is a comment from another buyer with the exact same issue in the last week. They had no voltage to the servo connectors. I've checked and mine is the same. I get a pwm signal and I can see that changing as the script runs, but no 5v. I'm going to return the boards and buy from somewhere else. Many thanks.

---
Tags: i2c, servo, pwm
---


# Question
Title: I can change value of only one register on 8-Bit Register integrated circuit (74hc273 / DM74LS273)?
First, please be patient, I'm not electronical person. I am learning Arduino and electronics for hobby and this is my fist time with integrated circuits.

* Situation: I'm want to extend the Arduino Nano pins (De/Multiplexer) and keep the state (High/Low) of the new pins until I decide to change it again. For keep the states I think that D-type Flipflop memory-based system can help .
* **Question 1**: On this system can I change only one bit with a unique signal or need to set all bit states ?
* Example (reference image):

1. Memory, previous state: `Q0=0, Q1=1, Q2=1, Q3=0`
2. Arduino: **Set pin17** (D2) **to High** -\> Memory: Waiting new data.
3. Arduino: **Set pin16** (D3) **to High** -\> Mux: Pass the value to memory at **D0**
4. Memory: **Read 1 on D0** (this is my doubt. D1, D2 and D3 don't matter ?)
5. Arduino: **Set pin17** (D2) **to LOW** -\> Memory: Save new data
6. Memory, new state: `Q0=1, Q1=1, Q2=1, Q3=0` ? ***or*** `Q0=1, Q1=0, Q2=0, Q3=0` ?

**Question 2**: Are this correct ? **Question 3**: Are there a more efficient way to do this?

**Notes:**

* I used a simulator to diagramed the memory based on this datasheet: https://pdf1.alldatasheet.com/datasheet-pdf/view/8337/NSC/74273.html It seems that it is possible, but I want to be sure.
* My currently solution is use separated flipflops, but I want to simplify it.
* Connections on reference image are simplified.
* Sorry about the poor diagram, I don't know programs for beautiful electronical diagrams.
* Sorry about typos, not-native English person here.

# Answer
> 1 votes
**Question 1** and **Question 2**: I was wrong, this is not the correct way. *@jsotola* and *@the\_busybe*e, thanks for the clarification

**Question 3**: *@Nick\_Gammon* and *@Majenko* I think you are right, using i2c are more efficient ways to do. But, the *@StarCat* proposal is more compatible with my current solution. **74hc259** allows me set the state one by one and keep it until I change it again.

---
Tags: arduino-nano, memory, multiplexer
---


title: How to increase life of EEPROM?

text:
# Question
Title: How to increase life of EEPROM?
I want to store a few (8 as of now) IR codes into my Board's EEPROM. It would be great if someone could suggest a few tips to maximize the lifetime.

The IR codes in my sketch are saved in array of unsigned longs.

I know that the count of times that I will be writing to EEPROM will \<\< 100,000 times, but still would like to optimize my sketch. + would help in future projects

# Answer
I can think of a few:

1. don't power it on unless you have to;
2. don't write to it unless you have to;
3. write as little data to you as you can - compress the data; only write to it during brown out or power down, ...;
4. level the writes to as many cells as possible - increment the write address with subsequent writes;
5. use a big eeprom;
6. use fram;
7. use sram + battery back-up;

...

3 - 7 are really examples of implementating #2.
> 5 votes

# Answer
The other answer mentioned some general ideas; here are a couple of more-specific notes.

• You can direct your writes of single bytes through a routine that reads the EEPROM cell before writing to it, and if its value isn't changing, doesn't write.

• For load-leveling, you can divide the EEPROM address space into k buckets, where k =⌊E/(n+1)⌋, with n = data array size and E = EEPROM size. Initialize a directory, an array of m bytes all set to k, with m = E-n·k. When your device starts up, it reads through the directory until it finds current entry, a byte not equal to k. \[If all directory entries equal k, initialize the first to 0, and go on from there.\] If the current directory entry contains j, then bucket j contains current data. When you need to write new data, you store j+1 into the current directory entry; if that makes it equal to k, initialize the next directory entry to 0, and go on from there. Note that directory bytes get about the same amount of wear as bucket bytes because 2·k \> m ≥ k.
> 7 votes

# Answer
If your data occupies only a small fraction of your EEPROM, you could use one of the wear leveling algorithms. The essence of these algorithms is to write to a different location each time, so writes are spread across several locations while each location stays below the 100,000 writes limit.

There are several such algorithms discussed here, which you could implement yourself. Alternatively, you could just use a library like this one.
> 3 votes

# Answer
I believe there's a simple way to use only n cells and a single dedicated bit pattern to achieve n/2 increase in durability.

The dedicated bit pattern (e.g. 0xffff) is a marker which indicates an unused cell, and in normal operation at most one cell at a time has this value:

```
uint16_t readWord (const uint16_t *address);
void writeWord (uint16_t *address, uint16_t value);

#define CELL_COUNT   42
#define BASE_ADDRESS 12
#define MARKER       0xffff  // Best to use EEPROM default for this

static uint8_t curCell = 0;

static void wlInit (void)
{
  for ( uint8_t ii = 0 ; ii < CELL_COUNT ; ii++ ) {
    if ( readWord (BASE_ADDRESS + ii) != MARKER ) {
      curCell = ii;
      // No early return/break here to keep init() execution time
      // constant.  Could also check for corruption here by checking for
      // > 1 cells with MARKER (see below).
    }
  }
  // If we didn't find a non-marker cell we'll end up with curCell = 0
  // per the initial value of curCell
}

static uint16_t wlRead (void)
{
  return readWord (BASE_ADDRESS + curCell);
}

static void wlWrite (uint16_t value)
{
  assert (value != MARKER);   // Storing marker value is big no-no

  uint8_t nextCell = (curCell + 1) % CELL_COUNT;
  writeWord (BASE_ADDRESS + nextCell, value);
  writeWord (BASE_ADDRESS + curCell, MARKER);
  curCell = nextCell;
}

```

The same approach can be used with structured data provided a bit pattern can be reserved (either in a dedicated byte or from some other field that has a spare pattern).

This approach also has a useful property with respect to interrupted (e.g. power drop) writes: if there are ever two cells without the MARKER value an incomplete (i.e. corrupted) write has occurred. This seems useful, because e.g. the ATmega328P datasheet contains the following unclear and not-particularly-reassuring paragraph about using brown-out detection to avoid corruption:

> Keep the AVR RESET active (low) during periods of insufficient power supply voltage. This can be done by enabling the internal Brown-out Detector (BOD). If the detection level of the internal BOD does not match the needed detection level, an external low V CC reset Protection circuit can be used. If a reset occurs while a write operation is in progress, the write operation will be com- pleted provided that the power supply voltage is sufficient.
> 0 votes

---
Tags: arduino-uno, eeprom, code-optimization
---