# Question
Title: what is the difference between array of uint16_t data versus an array of uint16_t variables?
I've been struggling with weird behavior, crashes and general problems when trying to use an array of four uint16\_t groups of data. When I create four separate variables and load that into an array, it works OK and is smaller.

This is for use with the irlib2 SendBase and HashRaw components.

What's going on here?

The code utterly fails with crashes, unresponsive hardware when I use the following variable assignment with an arduino micro. Additionally this version uses about 400 bytes more of memory than the second example

**failed variable assignemnt**

```
uint16_t sources[4][RAW_DATA_LEN] = {
  {8550, 4306, 530, 1606, 530, 566, 502, 1610, //POWER ON/OFF
  530, 566, 502, 574, 506, 1630, 506, 566,
  506, 1630, 506, 566, 502, 1610, 530, 566,
  502, 1634, 506, 1606, 530, 570, 498, 1634,
  506, 570, 510, 562, 506, 566, 502, 1634,
  506, 1606, 530, 1610, 530, 562, 538, 538,
  530, 542, 538, 1598, 538, 1570, 558, 542,
  538, 538, 530, 542, 538, 1598, 530, 1578,
  558, 1578, 562, 1000},

  {8546, 4310, 558, 1578, 562, 538, 498, 1638, //sourceCD
  530, 542, 506, 570, 502, 1634, 502, 570,
  498, 1638, 534, 538, 498, 1638, 530, 542,
  506, 1606, 554, 1582, 558, 538, 510, 1602,
  554, 546, 506, 566, 502, 570, 510, 1602,
  554, 1582, 558, 538, 510, 566, 502, 1606,
  554, 546, 502, 1610, 558, 1574, 554, 546,
  502, 570, 510, 1602, 526, 1610, 526, 574,
  506, 1602, 526, 1000},

  {8550, 4306, 530, 1606, 534, 566, 502, 1606,  //sourceCDR
  534, 566, 502, 570, 510, 1602, 526, 570,
  510, 1602, 534, 566, 502, 1606, 534, 566,
  506, 1602, 530, 1606, 534, 566, 502, 1610,
  530, 570, 498, 574, 506, 566, 502, 570,
  510, 1602, 526, 570, 510, 566, 502, 570,
  510, 1602, 526, 1610, 526, 1606, 534, 1602,
  534, 566, 502, 1610, 530, 1602, 534, 1602,
  526, 574, 506, 1000},

  {8550, 4310, 526, 1634, 506, 566, 502, 1634,  //sourceAUX
  506, 566, 502, 574, 506, 1626, 510, 566,
  506, 1630, 506, 566, 502, 1634, 506, 566,
  502, 1634, 506, 1606, 530, 566, 506, 1630,
  506, 566, 502, 1634, 506, 1630, 506, 1630,
  510, 1602, 526, 570, 510, 566, 502, 1634,
  502, 570, 502, 570, 510, 566, 502, 570,
  510, 562, 506, 1630, 506, 1630, 510, 562,
  506, 1630, 510, 1000}
} ;

```

When I instead assign each grouping to a variable and then create an array of those variables, the code is significantly smaller (about 400 bytes) and appears to run as expected without crashes. **Successful variable assignment**

```
#define RAW_DATA_LEN 68
uint16_t powerOnOff[RAW_DATA_LEN] = {
  8550, 4306, 530, 1606, 530, 566, 502, 1610,
  530, 566, 502, 574, 506, 1630, 506, 566,
  506, 1630, 506, 566, 502, 1610, 530, 566,
  502, 1634, 506, 1606, 530, 570, 498, 1634,
  506, 570, 510, 562, 506, 566, 502, 1634,
  506, 1606, 530, 1610, 530, 562, 538, 538,
  530, 542, 538, 1598, 538, 1570, 558, 542,
  538, 538, 530, 542, 538, 1598, 530, 1578,
  558, 1578, 562, 1000
};

uint16_t sourceCD[RAW_DATA_LEN] = {
  8546, 4310, 558, 1578, 562, 538, 498, 1638,
  530, 542, 506, 570, 502, 1634, 502, 570,
  498, 1638, 534, 538, 498, 1638, 530, 542,
  506, 1606, 554, 1582, 558, 538, 510, 1602,
  554, 546, 506, 566, 502, 570, 510, 1602,
  554, 1582, 558, 538, 510, 566, 502, 1606,
  554, 546, 502, 1610, 558, 1574, 554, 546,
  502, 570, 510, 1602, 526, 1610, 526, 574,
  506, 1602, 526, 1000
};

uint16_t sourceAUX[RAW_DATA_LEN] = {
  8550, 4310, 526, 1634, 506, 566, 502, 1634,
  506, 566, 502, 574, 506, 1626, 510, 566,
  506, 1630, 506, 566, 502, 1634, 506, 566,
  502, 1634, 506, 1606, 530, 566, 506, 1630,
  506, 566, 502, 1634, 506, 1630, 506, 1630,
  510, 1602, 526, 570, 510, 566, 502, 1634,
  502, 570, 502, 570, 510, 566, 502, 570,
  510, 562, 506, 1630, 506, 1630, 510, 562,
  506, 1630, 510, 1000
};

uint16_t sourceCDR[RAW_DATA_LEN] = {
  8550, 4306, 530, 1606, 534, 566, 502, 1606,
  534, 566, 502, 570, 510, 1602, 526, 570,
  510, 1602, 534, 566, 502, 1606, 534, 566,
  506, 1602, 530, 1606, 534, 566, 502, 1610,
  530, 570, 498, 574, 506, 566, 502, 570,
  510, 1602, 526, 570, 510, 566, 502, 570,
  510, 1602, 526, 1610, 526, 1606, 534, 1602,
  534, 566, 502, 1610, 530, 1602, 534, 1602,
  526, 574, 506, 1000
};

//Set up array of codes
uint16_t sources[4] = {powerOnOff, sourceCD, sourceCDR, sourceAUX};

```

This is the code as it stands in an unfinished state. In an effort to trace back the crashes and odd behavior I systematically removed most of the code to the point where the last if statement is sending the IR codes.

**Entire Code**

```
#include <movingAvg.h>    // moving average library
#include <IRLibSendBase.h>    //We need the base code
#include <IRLib_HashRaw.h>    //Only use raw sender
#include <elapsedMillis.h>    //measure elapsed time

// ====REMOTE CODES====
//define the IR Sender
IRsendRaw mySender;
#define RAW_DATA_LEN 68
uint16_t powerOnOff[RAW_DATA_LEN] = {
  8550, 4306, 530, 1606, 530, 566, 502, 1610,
  530, 566, 502, 574, 506, 1630, 506, 566,
  506, 1630, 506, 566, 502, 1610, 530, 566,
  502, 1634, 506, 1606, 530, 570, 498, 1634,
  506, 570, 510, 562, 506, 566, 502, 1634,
  506, 1606, 530, 1610, 530, 562, 538, 538,
  530, 542, 538, 1598, 538, 1570, 558, 542,
  538, 538, 530, 542, 538, 1598, 530, 1578,
  558, 1578, 562, 1000
};

uint16_t sourceCD[RAW_DATA_LEN] = {
  8546, 4310, 558, 1578, 562, 538, 498, 1638,
  530, 542, 506, 570, 502, 1634, 502, 570,
  498, 1638, 534, 538, 498, 1638, 530, 542,
  506, 1606, 554, 1582, 558, 538, 510, 1602,
  554, 546, 506, 566, 502, 570, 510, 1602,
  554, 1582, 558, 538, 510, 566, 502, 1606,
  554, 546, 502, 1610, 558, 1574, 554, 546,
  502, 570, 510, 1602, 526, 1610, 526, 574,
  506, 1602, 526, 1000
};

//uint16_t sourceAUX[RAW_DATA_LEN] = {
//  8550, 4310, 526, 1634, 506, 566, 502, 1634,
//  506, 566, 502, 574, 506, 1626, 510, 566,
//  506, 1630, 506, 566, 502, 1634, 506, 566,
//  502, 1634, 506, 1606, 530, 566, 506, 1630,
//  506, 566, 502, 1634, 506, 1630, 506, 1630,
//  510, 1602, 526, 570, 510, 566, 502, 1634,
//  502, 570, 502, 570, 510, 566, 502, 570,
//  510, 562, 506, 1630, 506, 1630, 510, 562,
//  506, 1630, 510, 1000
//};

uint16_t sourceCDR[RAW_DATA_LEN] = {
  8550, 4306, 530, 1606, 534, 566, 502, 1606,
  534, 566, 502, 570, 510, 1602, 526, 570,
  510, 1602, 534, 566, 502, 1606, 534, 566,
  506, 1602, 530, 1606, 534, 566, 502, 1610,
  530, 570, 498, 574, 506, 566, 502, 570,
  510, 1602, 526, 570, 510, 566, 502, 570,
  510, 1602, 526, 1610, 526, 1606, 534, 1602,
  534, 566, 502, 1610, 530, 1602, 534, 1602,
  526, 574, 506, 1000
};

//Set up array of codes
uint16_t *sources[3] = {powerOnOff, sourceCD, sourceCDR};//, sourceAUX};

//This causes some sort of horrible crash - maybe an overflow of the uint16 data type?
//#define RAW_DATA_LEN 68
//uint16_t sources[4][RAW_DATA_LEN] = {
//  {8550, 4306, 530, 1606, 530, 566, 502, 1610, //POWER ON/OFF
//  530, 566, 502, 574, 506, 1630, 506, 566,
//  506, 1630, 506, 566, 502, 1610, 530, 566,
//  502, 1634, 506, 1606, 530, 570, 498, 1634,
//  506, 570, 510, 562, 506, 566, 502, 1634,
//  506, 1606, 530, 1610, 530, 562, 538, 538,
//  530, 542, 538, 1598, 538, 1570, 558, 542,
//  538, 538, 530, 542, 538, 1598, 530, 1578,
//  558, 1578, 562, 1000},
//
//  {8546, 4310, 558, 1578, 562, 538, 498, 1638, //sourceCD
//  530, 542, 506, 570, 502, 1634, 502, 570,
//  498, 1638, 534, 538, 498, 1638, 530, 542,
//  506, 1606, 554, 1582, 558, 538, 510, 1602,
//  554, 546, 506, 566, 502, 570, 510, 1602,
//  554, 1582, 558, 538, 510, 566, 502, 1606,
//  554, 546, 502, 1610, 558, 1574, 554, 546,
//  502, 570, 510, 1602, 526, 1610, 526, 574,
//  506, 1602, 526, 1000},
//
//
//  {8550, 4306, 530, 1606, 534, 566, 502, 1606,  //sourceCDR
//  534, 566, 502, 570, 510, 1602, 526, 570,
//  510, 1602, 534, 566, 502, 1606, 534, 566,
//  506, 1602, 530, 1606, 534, 566, 502, 1610,
//  530, 570, 498, 574, 506, 566, 502, 570,
//  510, 1602, 526, 570, 510, 566, 502, 570,
//  510, 1602, 526, 1610, 526, 1606, 534, 1602,
//  534, 566, 502, 1610, 530, 1602, 534, 1602,
//  526, 574, 506, 1000},
//
//  {8550, 4310, 526, 1634, 506, 566, 502, 1634,  //sourceAUX
//  506, 566, 502, 574, 506, 1626, 510, 566,
//  506, 1630, 506, 566, 502, 1634, 506, 566,
//  502, 1634, 506, 1606, 530, 566, 506, 1630,
//  506, 566, 502, 1634, 506, 1630, 506, 1630,
//  510, 1602, 526, 570, 510, 566, 502, 1634,
//  502, 570, 502, 570, 510, 566, 502, 570,
//  510, 562, 506, 1630, 506, 1630, 510, 562,
//  506, 1630, 510, 1000}
//} ;

// ====PIN ASSIGNMENTS====
const int audioPin1 = A1;     //Channel 1
const int audioPin2 = A2;
const int debugPin = A3;     //when low, run in debug mode
const int statusLight = 10;   //active channel indicator light

//  ====CHANNEL MEASUREMENTS====
# define CHANNELS 3     //number of channels to sample from
int audioChannels[CHANNELS] = {audioPin1, audioPin1, audioPin2};      //element 0 will be ignored
int channelValues[CHANNELS] = {0, 0, 0};
const int SAMPLES = 300;
movingAvg audioAverages[CHANNELS] = {movingAvg(SAMPLES), movingAvg(SAMPLES), movingAvg(SAMPLES)};

//  ====CHANNEL VARIABLES====
int currentChannel = 0;     //channel that is currently active (0 is off)
int previousChannel = 0;    //channel that was active before change (0 is off)
const int audioThreshold = 15;      //minimum value for an "active" channel

//  ====TIMERS===
int counter = 0;
const int heartBeat = 500;
int channelReleaseTimeOut = 5000;      //time to wait before releasing an inactive timer
int powerTimeOut = 10000;       //time to wait before turnning off
int powerOnDelay = 7000;
elapsedMillis channelReleaseTimer = 0;
elapsedMillis powerTimer = 0;

// ====CONTROL VARIABLES====
bool debugMode = true;

void sendCode(int myChannel=0) {
//  debug("sending code", -1);
  for (int i=0; i < 20; i++) {
//  INCLUDING THE FOLLOWING LINE BREAKS THE DEBUG FUNCTION AND CAUSES OTHER STRANGE BEHAVIOR
//    mySender.send(sources[myChannel], RAW_DATA_LEN, 36);
    Serial.println("send code here");
    delay(2);
  }
} //END sendCode()

int findActiveChannel() {   //returns first active channel in the array or 0 if none are active
  int myChannel = 0;
  for (int i = 0; i < CHANNELS; i++) {
    if (channelValues[i] >= audioThreshold) {
      myChannel = i;
      break;
    }
  }
  return myChannel;
} //END findActiveChannel()

void debug(String message, int val) {

  if (debugMode) {
    Serial.print(message);
    Serial.println(val);
  }
} //END debug()

void setup() {
  delay(1000); //delay in case of runaway loop - allow programmer time to interrupt
  //  ====PIN SETUP====
  pinMode(statusLight, OUTPUT);
  pinMode(debugPin, INPUT);
  pinMode(audioPin1, INPUT);
  pinMode(audioPin2, INPUT);

  if (debugMode) {
    Serial.begin(9600);
    delay(2000);
    debug("starting up ", -1);
  }

  // ====INIT VARIABLES====
  for (int i = 0; i < CHANNELS; i++) { //init and reset the moving averages
    audioAverages[i].begin();
    audioAverages[i].reset();
  }
}

void loop() {
  int activeChannel = 0;
  for (int i=0; i < CHANNELS; i++) {      //sample channels
    int audioValue = 0;
    if (i > 0) {      //only sample channels > 0
      audioValue = analogRead(audioChannels[i]) - 512;      //voltage divider on amp circuit shifts all values +512 (2.5V)
      audioValue = abs(audioValue);     //abs() funciton is actually a macro; needs to be on own line
      channelValues[i] = audioAverages[i].reading(audioValue);    //update and store the moving average for each channel
    }

//    if (counter >= heartBeat) {
//      debug("channel: ", i);
//      debug("    audioValue: ", audioValue);
//      debug("           avg: ", channelValues[i]);
//    }
  }     //end sample channels

//  if (counter >= heartBeat) {
//    debug("======================", -1);
//  }

  if (channelValues[currentChannel] >= audioThreshold) {      //reset the channel release timer if the current channel is active
    channelReleaseTimer = 0;
    powerTimer = 0;
  } else {
    activeChannel = findActiveChannel();

    //DEBUGGING - show countdown to channel release
    if(channelReleaseTimer < channelReleaseTimeOut and counter >= 500) {
      debug("Channel became inactive: ", currentChannel);
      debug("     releasing in: ", channelReleaseTimeOut - channelReleaseTimer);
    }
    //END DEBUGGING

    if (activeChannel != currentChannel and channelReleaseTimer >=channelReleaseTimeOut) {      //change channel
      debug("Changing channel from: ", currentChannel);
      debug("Changing channel to: ", activeChannel);
      currentChannel = activeChannel;
      powerTimer = 0;
    }
  }
  //END else find active channel

  if (currentChannel > 0) {     //reset the power timeout if there is an active channel
    powerTimer = 0;
  }

  if (previousChannel != currentChannel) {      //check for a channel change and send appropriate codes
    if (previousChannel == 0) {     //state change from off to on
      digitalWrite(statusLight, true);
      debug("power state change -> ON ", -1);
      sendCode(0);
      debug("     delaying for reciver to power up: ", powerOnDelay);
      delay(powerOnDelay);
      previousChannel = currentChannel;
    }

    if (currentChannel < 1 and powerTimer >= powerTimeOut) {
      digitalWrite(statusLight, false);
      debug("power state change -> OFF ", -1);
      sendCode(0);
      previousChannel = currentChannel;
    }

    if (currentChannel > 0) {
      sendCode(currentChannel);
      previousChannel = currentChannel;
    }

  }

  if (counter >= heartBeat) {
    debug("\nheartBeat ", -1);
    counter = 0;
  }

  counter++;
  delay(2);

}

```

Including the line `mySender.send(sources[myChannel], RAW_DATA_LEN, 36);` in the `sendCode()` function causes the `debug()` function to behave erratically and the arduino to get stuck in a variety of states that require a hard reset, sometimes disconnecting the power.

This is the expected output from the serial console:

```
20:18:20.188 -> Channel became inactive: 2
20:18:20.188 ->      releasing in: 4666
20:18:20.188 ->
20:18:20.188 -> heartBeat -1
20:18:21.377 -> Channel became inactive: 2
20:18:21.377 ->      releasing in: 3492
20:18:21.377 ->
20:18:21.377 -> heartBeat -1
20:18:22.528 -> Channel became inactive: 2
20:18:22.528 ->      releasing in: 2317
20:18:22.528 ->
20:18:22.528 -> heartBeat -1
20:18:23.713 -> Channel became inactive: 2
20:18:23.713 ->      releasing in: 1144
20:18:23.713 ->
20:18:23.713 -> heartBeat -1
20:18:24.864 -> Changing channel from: 2
20:18:24.864 -> Changing channel to: 1
20:18:24.864 -> send code here

```

When including the mysender line indicated above, the serial output becomes as follows for a similar situation:

```
0:21:14.965 -> 1
20:21:14.965 -> 4984
20:21:14.965 -> -1
20:21:16.121 -> 1
20:21:16.121 -> 4986
20:21:16.121 -> -1
20:21:17.299 -> 1
20:21:17.299 -> 3814
20:21:17.299 -> -1
20:21:18.463 -> 1
20:21:18.463 -> 2640
20:21:18.463 -> -1
20:21:19.650 -> 1
20:21:19.650 -> 1468
20:21:19.650 -> -1
20:21:20.804 -> 1
20:21:20.804 -> 294
20:21:20.804 -> -1
20:21:21.116 -> 1
20:21:21.116 -> 0
20:21:21.998 -> -1

```

# Answer
I have no solution for you, but I would argue that your problem has nothing to do the choice between an array of arrays and an array of pointers. You will have to search somewhere else.

I tried a minimal test by removing everything that is not central to the question. Assuming you are using this library, the prototype of `IRsendRaw::send()` is

```
void IRsendRaw::send(uint16_t *buf, uint8_t len, uint8_t khz)

```

I thus wrote this dummy test class to replace the library:

```
class IRsendRaw {
public:
    void send(uint16_t *buf, uint8_t len, uint8_t khz) {
        Serial.print(F("Sending at "));
        Serial.print(khz);
        Serial.println(F(" kHz"));
        for (int i = 0; i < len; i++) {
            Serial.print(" ");
            Serial.print(buf[i]);
        }
        Serial.println();
    }
};

```

and used it in the following test program:

```
// Comment this line out to use an array of arrays instead:
#define ARRAY_OF_POINTERS

// ====REMOTE CODES====
//define the IR Sender
IRsendRaw mySender;

#define RAW_DATA_LEN 68

#ifdef ARRAY_OF_POINTERS

uint16_t powerOnOff[RAW_DATA_LEN] = {
  // ...
};

// And so on sourceCD[], sourceCDR[]...

//Set up array of codes
uint16_t *sources[3] = {powerOnOff, sourceCD, sourceCDR};//, sourceAUX};

#else

//This causes some sort of horrible crash
//- maybe an overflow of the uint16 data type?
uint16_t sources[4][RAW_DATA_LEN] = {
  {8550, 4306, 530, 1606, 530, 566, 502, 1610, //POWER ON/OFF
  // ...
  506, 1630, 510, 1000}
};

#endif

void setup()
{
    Serial.begin(9600);
#ifdef ARRAY_OF_POINTERS
    Serial.println(F("== Using an array of pointers =="));
#else
    Serial.println(F("== Using an array of arrays =="));
#endif
    for (int myChannel = 0; myChannel < 3; myChannel++) {
        Serial.print(F("\nChannel "));
        Serial.println(myChannel);
        mySender.send(sources[myChannel], RAW_DATA_LEN, 36);
    }
}

void loop(){}

```

The parts with ellipses (“...”) are just copied from your question. Now, this test program works as expected, both in “array of pointers” and in “array of arrays” mode.

It would then seem your problem comes from somewhere else. How full is the memory of your Arduino? Quite often memory problems lead to strange behaviors, where a crash can be triggered by a piece of code that is perfectly legitimate and has nothing to do with the root cause of the crash.
> 1 votes

---
Tags: ir, variables
---


title: Arduino micro not recognized

text:
# Question
Title: Arduino micro not recognized
I have an Arduino micro for some time and everything always worked well. Today, when I was uploading a code on this board using Arduino IDE, I accidentally started the Arduino Board update and the upload failed. After a while I retried again and again and again but upload always failed. Now my PC doesn't recognize my board and, looking at *Windows Device Manager*, when I connect my board, appears this screen:

What should I do? Do I have to reflash bootloader?

# Answer
> 1 votes
So I was facing this issue for the past few hours and this is how I managed to get it to work. After reading similar issues on knockoff NANOS, I downloaded and installed this as many knockoff NANOS uses a different Serial CHIPSET.

After that, on the IDE side, just press compile to ensure your code is good to go. And then when you hit upload, wait for it to finish compiling and the second it says UPLOADING, hit the reset button. It should upload now and be available in your COM port.

# Answer
> 1 votes
I had this issue a while back and in order to fix it as suggested above I had to re flash the boot loader using a 2nd Arduino as an ISP. I used this page as a guide:

https://schou.dk/linux/arduino/isp/

Before connecting the wiring I first updated the UNO with the "ArduinoISP" Sketch, connected the wiring, then flashed the boot loader.

---
Tags: arduino-ide, arduino-micro
---


# Question
Title: Enable and disable individual interrupts
I am working on timer interrupts and external interrupts. for external interrupts I understood the functions like attachInterrupt. detachinterrupt for individual interrupts ,noInterrupts() and interrupts() can be used to enable and disable all interrupts at a time.

But How to enable and disable timer interrupts??

I am writing a code for alarm clock and snooze button. So what I want is 1) whenever alarm time is equal to watch time, start a timer for 5 minutes and a buzzer buzzes. 2) whenever I press the snooze button, another timer starts and after 30 seconds a buzzer beeps. again I press snooze and again the timer starts and after 30 seconds buzzer beeps. 3) But after 5 minutes of the first timer, both timer interrupts gets disabled as now I dont want any buzzer.

I know how to initialize the timer in setup function, and I am getting the buzzes every 30 seconds. I also know that interrupts will come according to the timer value and I need to call the function after a fix number of counts or 30 seconds or 5 minutes.

But I dont know how to disable and enable timer interrupts wherever I want in code.

# Answer
* Step 1: Read the datasheet for the chip.
* Step 2: Find the registers that control the timers and their interrupts.
* Step 3: Set or clear the relevant bits in those registers.

For example, the ATMega328P has the `TIMSK1` register for Timer 1, which has three bits related to interrupts:

> * **Bit 2 – OCIE1B: Timer/Counter1, Output Compare B Match Interrupt Enable**
>
> When this bit is written to one, and the I-flag in the status register is set (interrupts globally enabled), the Timer/Counter1 output compare B match interrupt is enabled. The corresponding interrupt vector (see Section 11. “Interrupts” on page 49) is executed when the OCF1B flag, located in TIFR1, is set.
>
> * **Bit 1 – OCIE1A: Timer/Counter1, Output Compare A Match Interrupt Enable**
>
> When this bit is written to one, and the I-flag in the status register is set (interrupts globally enabled), the Timer/Counter1 output compare A match interrupt is enabled. The corresponding interrupt vector (see Section 11. “Interrupts” on page 49) is executed when the OCF1A flag, located in TIFR1, is set.
>
> * **Bit 0 – TOIE1: Timer/Counter1, Overflow Interrupt Enable**
>
> When this bit is written to one, and the I-flag in the status register is set (interrupts globally enabled), the Timer/Counter1 overflow interrupt is enabled. The corresponding interrupt vector (see Section 11. “Interrupts” on page 49) is executed when the TOV1 flag, located in TIFR1, is set.

So to turn off the Compare B Match interrupt you can use:

```
TIMSK1 &= ~(1 << 2);

```

And to turn it on again:

```
TIMSK1 |= (1 << 2);

```

Both Timer 0 and Timer2 have a `TIMSKx` register which works in the same way.
> 4 votes

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


# Question
Title: need to get values from a function with structure pointer argument and print on serial terminal
I am developing a code in which I need to print value of structure pointer on serial terminal. Below is my code snippet:

```
typedef struct
{
  uint8_t AB;     ///< Address byte (Start byte)
  uint8_t CB;     ///< Command (index) "ASCII-byte"
  uint8_t SI;     ///< Action (sub index) "ASCII-byte"
  uint8_t PH_1;    ///< Payload "ASCII-byte" of the high nibble of the high byte of the raw payload
  uint8_t PH_2;    ///< Payload "ASCII-byte" of the low nibble of the high byte of the raw payload
  uint8_t PL_1;    ///< Payload "ASCII-byte" of the high nibble of the low byte of the raw payload
  uint8_t PL_2;    ///< Payload "ASCII-byte" of the low nibble of the low byte of the raw payload
  uint8_t CS1;    ///< Checksum "ASCII-byte" of the high nibble of the raw checksum
  uint8_t CS0;    ///< Checksum "ASCII-byte" of the low nibble of the raw checksum
} rs485_message_t;

int proto485ComposeMsg(rs485_message_t* msg, uint8_t address, uint8_t command, uint8_t action, uint16_t value){
  msg->AB = address;
  msg->CB = command;
  msg->SI = action;
  msg->PH_1 = (int)((value & 0xF000) >> 12) ;
  msg->PH_2 = (int)((value & 0x0F00) >> 8);
  msg->PL_1 = (int)((value & 0x00F0) >> 4) ;
  msg->PL_2 = (int)(value & 0x000F);
  int checksumRaw = (msg->CB) + (msg->SI) + (msg->PH_1) + (msg->PH_2) + (msg->PL_1) + (msg->PL_2);
  setCheckSum(msg);
}

uint8_t proto485Write(uint8_t address, uint8_t command, uint8_t action, uint16_t value)
{
  int i = 0;
  int stringOne[9] = {int(0x00), int(0x00), int(0x00), int(0x00), int(0x00), int(0x00), int(0x00), int(0x00), int(0x00)}; ;
  rs485_message_t rs485Msg;
  proto485ComposeMsg(&rs485Msg, address, command, action, value); // value is passed in "raw" format
  Serial.write(rs485Msg);       // getting error on this line
}

```

Please help... Thank you

# Answer
You can't just print a structure. After all, how is the program supposed to know how it is supposed to be displayed?

Do you want just the raw data, or do you want it formatted in a human readable form?

For just the raw data you need to cast the pointer to a type that can be printed as an array. For example:

```
Serial.write((uint8_t *)&rs485Msg, sizeof(struct rs485_message_t));

```

To print it in a human readable form you will need to take each value that you want to see and print it separately with any data manipulation that you may want. For example:

```
Serial.print("Checksum 0: ");
Serial.println(rs485Msg.CS0, HEX);

```

Another thing you can do is to change your structure into a class and inherit the `Printable` class. You can then implement the `size_t printTo(Print &p);` member function which sends the data to the `p` object for printing in the format you want. Then you can just print it directly as you are trying to do in your code.
> 2 votes

---
Tags: c++
---


# Question
Title: Program to run two motors with Motor driver
I'm trying to make a program that would run two motors clockwise and then anticlockwise. But my program is causing my motors to only run clockwise everytime . It doesn't run anticlockwise at all. Can anyone help me find the bug?

Main code:

```
void loop()
{
  // turn on motor A
  digitalWrite(In1, HIGH);
  digitalWrite(In2, LOW);
  // set speed to 150 out 255
  analogWrite(EnA, 150);
  // turn on motor B
  digitalWrite(In3, HIGH);
  digitalWrite(In4, LOW);
  // set speed to 150 out 255
  analogWrite(EnB, 150);
  delay(2000);
   digitalWrite(In1, LOW);
  digitalWrite(In2, HIGH);
   digitalWrite(In3,LOW);
  digitalWrite(In4, HIGH);
  // now turn off motors
  digitalWrite(In1, LOW);
  digitalWrite(In2, LOW);
  digitalWrite(In3, LOW);
  digitalWrite(In4, LOW);
  delay(2000);
}

```

# Answer
check this one

```
void loop()
{
  // turn on motor A
  digitalWrite(In1, HIGH);
  digitalWrite(In2, LOW);
  // set speed to 150 out 255
  analogWrite(EnA, 150);
  // turn on motor B
  digitalWrite(In3, HIGH);
  digitalWrite(In4, LOW);
  // set speed to 150 out 255
  analogWrite(EnB, 150);
  delay(2000);
   digitalWrite(In1, LOW);
  digitalWrite(In2, HIGH);
   digitalWrite(In3,LOW);
  digitalWrite(In4, HIGH);
  // now turn off motors
  delay(5000);
  digitalWrite(In1, LOW);
  digitalWrite(In2, LOW);
  digitalWrite(In3, LOW);
  digitalWrite(In4, LOW);
  delay(2000);
}

```
> 0 votes

---
Tags: arduino-uno, motor
---


# Question
Title: Unable to store data in variable from Serial.read()
I have a relay and bluetooth module connected to Arduino Uno. I send data such as digit 1 to the bluetooth module and I view it in the Serial Monitor. If I send 1 from serial monitor I get 4910 printed.

I would like to turn on the relay and have it stay on until I send a different digit. However, in my code below it doesnt work, the relay doesnt stay on.

Only, if I put the digital.write under **while(Serial.available())** it works.

```
const int ledPin =  11;
int relayOn;

void setup() {

  //initialize serial port for logs
  Serial.begin(9600);

  pinMode(ledPin, OUTPUT);

}

void loop() {

  while (Serial.available()) {

      Serial.println("Data: ");

      Serial.println(Serial.read());

      if(Serial.read())
      {
        relayOn = Serial.parseInt();
      }

      while (relayOn > 1)
      {
        digitalWrite(ledPin, HIGH);

      }

    }

}

```

# Answer
Your input is "5\n" with '\n' as line ending setting in Serial Monitor.

In the code you have first `Serial.println(Serial.read());`. It will read and print the '5'. Then you have `if(Serial.read())`. It will read the '\n'. It is not 0 so the next line is `relayOn = Serial.parseInt()`. It will find no input and times out returning 0.

if you want to use parseInt():

```
void loop() {
  if (Serial.available()) {
    Serial.print("Data: ");
    relayOn = Serial.parseInt();
    Serial.println(relayOn);
    if (relayOn > 1) {
      digitalWrite(ledPin, HIGH);
    }
  }
}

```
> 1 votes

# Answer
You could try something like (not tested):

```
void loop() {
 if(Serial.available()){
   input = Serial.parseInt();
   Serial.print("Data: ");
   Serial.println(input);
   if(input == 1){
      digitalWrite(RELAY, HIGH);
      digitalWrite(LED, HIGH);
   }
   else if(input == 2{
      digitalWrite(RELAY, LOW);
      digitalWrite(LED, LOW);
   }
 }
}

```

don't forget to declare input variable, use 1 to turn on, 2 off :)
> 3 votes

# Answer
Try using serial interrupt in arduino

```
void loop() {
}

void serialEvent()
{
  while (Serial.available())
    {
       char inChar = (char)Serial.read();
      Serial.print("Data: ");
      Serial.println(inChar);
       if (inChar == '1')
        {
              digitalWrite(ledPin,HIGH);
              break;
        }
       else
        {
              digitalWrite(ledPin,LOW);
              break;
        }
     }
}

```
> 0 votes

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


# Question
Title: Pass structure pointer as an argument to a function in c
I am developing a code in which I need to pass a structure pointer value to a function as a parameter. I am calling function "proto485Compare()" in "RS485TaskSlave()". "rs485Msg" contains my data for which I need to verify for checksum, I am checking it in "RS485TaskSlave()" using "if(proto485ValidCheckSum(rs485\_message\_t ((uint8\_t\*)message)))" but it is showing error on this line.

Please help me to get the values of "rs485Msg" & check for checksum on this line

Below is my code snippet:

```
 typedef struct
    {
      uint8_t AB;     ///< Address byte (Start byte)
      uint8_t CB;     ///< Command (index) "ASCII-byte"
      uint8_t SI;     ///< Action (sub index) "ASCII-byte"
      uint8_t PH1;    ///< Payload "ASCII-byte" of the high nibble of the high byte of the raw payload
      uint8_t PH0;    ///< Payload "ASCII-byte" of the low nibble of the high byte of the raw payload
      uint8_t PL1;    ///< Payload "ASCII-byte" of the high nibble of the low byte of the raw payload
      uint8_t PL0;    ///< Payload "ASCII-byte" of the low nibble of the low byte of the raw payload
      uint8_t CS1;    ///< Checksum "ASCII-byte" of the high nibble of the raw checksum
      uint8_t CS0;    ///< Checksum "ASCII-byte" of the low nibble of the raw checksum
    } rs485_message_t;

    uint8_t proto485ValidCheckSum(rs485_message_t message)
    {
      uint8_t rawChecksum = (message.CB - OFFSET_ASCII) + (message.SI - OFFSET_ASCII) +
        (message.PH1 - OFFSET_ASCII) + (message.PH0 - OFFSET_ASCII) +
          (message.PL1 - OFFSET_ASCII) + (message.PL0 - OFFSET_ASCII);

      uint8_t res = (((rawChecksum & 0xF0) >> 4) + OFFSET_ASCII) == message.CS1 &&
        ((rawChecksum & 0x0F) + OFFSET_ASCII) == message.CS0;

      return res;
    }

    void RS485TaskSlave(void *p_arg) //b - RS485 communication Task
    {
        uint8_t res;
        rs485_message_t rs485Msg;
        uint8_t command, action, value;

        (void)p_arg;
        while(1)
        {
          res = driver485Read((uint8_t *)&rs485Msg, RS485_MSG_LENGTH);
          if(RS485_MSG_LENGTH == 9)
         {
            res =  proto485Compare((uint8_t *)&rs485Msg, command, action, value);
         }
        }
    }

    int16_t proto485Compare(uint8_t* message, uint8_t* comparec, uint8_t* comparea, uint8_t* comaprev)
    { int j = 0;
      rs485_message_t rs485Msg;
      char res;
      uint8_t FWmsg[9] = {0x09,0x31,0x30,0x30,0x30,0x30,0x33,0x30,0x34};
      uint8_t arduinodata[9] = {0x09,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30};

     if(proto485ValidCheckSum(rs485_message_t ((uint8_t*)message))) //
/*GETTING ERRORVON THIS LINE please help how to pass message value to verify checksum at this line*/
      {
      printf("compare command..........");

        for (j=0; j<9; j++)
        {
          arduinodata[j] = message[j];
          printf("%d ",arduinodata[j]);
        }
        printf("\n");

        if(compareArray(FWmsg,arduinodata,7)==0)
        {
          uint8_t add, fwc, fwa;
          uint16_t fwv;
          res = GetABFWversion(&add, &fwc, &fwa, &fwv);
          res = proto485OnlyWrite(add,fwc, fwa, fwv);
        }
      }
      else
      {
        printf("Arrays have different elements.\n");
      }
      return res;
    }

```

# Answer
Remove your casting, and change your `message` parameter to be `rs485_message_t *`:

```
int16_t proto485Compare(rs485_message_t * message, uint8_t* comparec, uint8_t* comparea, uint8_t* comaprev) {
    int j = 0;
    rs485_message_t rs485Msg;
    char res;
    uint8_t FWmsg[9] = {0x09,0x31,0x30,0x30,0x30,0x30,0x33,0x30,0x34};
    uint8_t arduinodata[9] = {0x09,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30};

    if(proto485ValidCheckSum(message))) { ...

```

And when you call it, simply:

```
res =  proto485Compare(&rs485Msg, command, action, value);

```

To get at the individual bytes you can then cast a new variable:

```
uint8_t *messageAsBytes = (uint8_t *)message;

```

Then you can use:

```
messageAsBytes[i]

```

etc.

However another cleaner way is to create a `union` in your structure:

```
struct rs485_message_t {
    union {
        uint8_t bytes[9];
        struct {
            uint8_t AB;     ///< Address byte (Start byte)
            uint8_t CB;     ///< Command (index) "ASCII-byte"
            uint8_t SI;     ///< Action (sub index) "ASCII-byte"
            uint8_t PH1;    ///< Payload "ASCII-byte" of the high nibble of the high byte of the raw payload
            uint8_t PH0;    ///< Payload "ASCII-byte" of the low nibble of the high byte of the raw payload
            uint8_t PL1;    ///< Payload "ASCII-byte" of the high nibble of the low byte of the raw payload
            uint8_t PL0;    ///< Payload "ASCII-byte" of the low nibble of the low byte of the raw payload
            uint8_t CS1;    ///< Checksum "ASCII-byte" of the high nibble of the raw checksum
            uint8_t CS0;    ///< Checksum "ASCII-byte" of the low nibble of the raw checksum
        };
    };
};

```

So you can now access `message->CS0`, etc, as well as `message->bytes[3]`.

You should also pass a pointer when you call `proto485ValidCheckSum` \- purely to save memory.

```
uint8_t proto485ValidCheckSum(rs485_message_t *message)
{
  uint8_t rawChecksum = (message->CB - OFFSET_ASCII) + (message->SI - OFFSET_ASCII) +
    (message->PH1 - OFFSET_ASCII) + (message->PH0 - OFFSET_ASCII) +
      (message->PL1 - OFFSET_ASCII) + (message->PL0 - OFFSET_ASCII);

  uint8_t res = (((rawChecksum & 0xF0) >> 4) + OFFSET_ASCII) == message->CS1 &&
    ((rawChecksum & 0x0F) + OFFSET_ASCII) == message->CS0;

  return res;
}

```

And again call it with a pointer, which the first block of code does anyway.

In general, it's better to pass a single pointer to a struct around from function to function instead of cloning it each time.

You can also use "pass by reference" if you like, but I find it's better to stick to pointers when passing something around alot like this.
> 0 votes

---
Tags: c
---


# Question
Title: Data Logging without Interfacing SD Card module
I want to log data to a text document without connecting the SD card module. I don't want to print the data on Serial Monitor I want to store it in a file. Is it possible? Can someone help me with it? I am using a Arduino Nano on a Windows 10 system, and I want to know if there is an Arduino library to write logs to a file.

# Answer
> 1 votes
The simplest answer is to install a program that handles serial connection and can write everything into a logfile. On Linux, CuteCom is a program like that. On Windows, putty can handle serial (as well as SSH and telnet), and has logging.

The more advanced soulution is to write a program (or a simple script) that can do that. You could make it to do some other stuff as well (like configuring the Arduino side), and you can run it in the background without user interaction.

---
Tags: arduino-nano
---


# Question
Title: How to control DC motor speed with L298N and Node MCU?
I want to control an RC car with a joystick in mobile. Currently, I can only make the motor move forward and backward but not able to control the speed. Node mcu is used as a processor to receive the message.

Here is the code below:-

```
#include <ESP8266WiFi.h>
#define PubNub_BASE_CLIENT WiFiClient
#include <PubNub.h>
#define PUBNUB_DEFINE_STRSPN_AND_STRNCASECMP
#include <L298N.h>

const char *ssid =  "mym404";     // replace with your wifi ssid and wpa2 key
const char *pass =  "786110786";

const char * pubkey = "";
const char * subkey = "";

const char * subchannel = "base";

#define ENB D6
#define IN1 D3
#define IN2 D4

L298N motorL(ENB, IN1, IN2);

#define ENA D5
#define IN3 D1
#define IN4 D7

L298N motorR(ENA, IN3, IN4);

void setup() {
    /* For debugging, set to speed of your choice */
    Serial.begin(115200);

       Serial.println("Connecting to ");
       Serial.println(ssid);

       WiFi.begin(ssid, pass);
       while (WiFi.status() != WL_CONNECTED)
          {
            delay(500);
            Serial.print(".");
          }
      Serial.println("");
      Serial.println("WiFi connected");

    /* Start the Pubnub library by giving it a publish and subscribe
       keys */
    PubNub.begin(pubkey, subkey);

}

void loop() {

  int tim = millis();

    PubSubClient *sclient = PubNub.subscribe(subchannel);
    if (!sclient) return; // error
    String msg;
    SubscribeCracker ritz(sclient);
    if (!ritz.finished()) {
        ritz.get(msg);
        if (msg.length() > 0) {
            Serial.print("Received: "); Serial.println(msg);

            String X = getStringPartByNr(msg, ':', 0);
            String Y = getStringPartByNr(msg, ':', 1);

            X.remove(0,1);

            int Xcord = X.toInt();
            int Ycord = Y.toInt();

            Serial.print("X: "); Serial.println(Xcord);
            Serial.print("Y: "); Serial.println(Ycord);

            int angle;
            int throttle = (Xcord + Ycord)/2;

            if ((Xcord > 100) && (Ycord > 100)) {
              angle = round(atan2(Ycord-100,Xcord-100)*(180/3.14));
              motorR.forward();
              motorL.forward();
              motorR.setSpeed(abs(int(throttle*sin(angle))));
              motorL.setSpeed(throttle);
              Serial.print("R speed: "); Serial.println(abs(int(throttle*sin(angle))));
              Serial.print("L speed: "); Serial.println(throttle);
              //motorR.forward();
              //motorL.forward();
            }
            else if ((Xcord < 100) && (Ycord > 100)) {
              angle = 180 - round(atan2(Ycord-100,100-Xcord)*(180/3.14));

              motorR.setSpeed(throttle);
              motorL.setSpeed(abs(int(throttle*sin(angle))));
              Serial.print("R speed: "); Serial.println(throttle);
              Serial.print("L speed: "); Serial.println(abs(int(throttle*sin(angle))));
              motorR.forward();
              motorL.forward();
            }
            else if ((Xcord < 100) && (Ycord < 100)) {
              angle = 180 + round(atan2(100-Ycord,100-Xcord)*(180/3.14));

              motorR.setSpeed(200-throttle);
              motorL.setSpeed(abs(int((200-throttle)*sin(angle)*(-1))));
              Serial.print("R speed: "); Serial.println(200-throttle);
              Serial.print("L speed: "); Serial.println(abs(int((200-throttle)*sin(angle)*(-1))));
              motorR.backward();
              motorL.backward();
            }
            else if ((Xcord > 100) && (Ycord < 100)) {
              angle = 270 + round(atan2(Xcord-100,100-Ycord)*(180/3.14));
              motorR.setSpeed(abs(int((200-throttle)*sin(angle)*(-1))));
              motorL.setSpeed(200-throttle);
              Serial.print("R speed: "); Serial.println(abs(int((200-throttle)*sin(angle)*(-1))));
              Serial.print("L speed: "); Serial.println(200-throttle);
              motorR.backward();
              motorL.backward();
            }

            Serial.print("Angle: "); Serial.println(angle);
            //Serial.print("time: "); Serial.println(tim);

        }
    }

    sclient->stop();

}

String getStringPartByNr(String data, char separator, int index)
{
    // splitting a string and return the part nr index
    // split by separator

    int stringData = 0;        //variable to count data part nr
    String dataPart = "";      //variable to hole the return text

    for(int i = 0; i<data.length()-1; i++) {    //Walk through the text one letter at a time

      if(data[i]==separator) {
        //Count the number of times separator character appears in the text
        stringData++;

      }else if(stringData==index) {
        //get the text when separator is the rignt one
        dataPart.concat(data[i]);

      }else if(stringData>index) {
        //return text and stop if the next separator appears - to save CPU-time
        return dataPart;
        break;

      }

    }
    //return text if this is the last part
    return dataPart;
}

```

Port Reading:-

What can the problem be?

# Answer
> 1 votes
That's because the l298n library are used for the arduino or other microcontroller that have hardware PWM in their systems. The library using hardware pwm by generating pulses and make variations of the cyclic rapport aka "alpha" . Esp8266 have no pwm in their systems So try to use software pwm library for the esp8266

> this is the link. https://www.arduinolibraries.info/libraries/soft-pwm

Also don't include that library and try to make it work using easy lines of codes.

---
Tags: motor, wifi, nodemcu, l298n
---


# Question
Title: Arduino help adding a second mpu 6050 sensor my working code
Background information: I currently have this arduino code that uses one mpu 6050 sensor to get angles in the x, y, and z directions and then display them to the user nicely. Code can be found here basic MPU 6050 code

The problem: **I would like to add a second mpu 6050** to my project and average the values from the two mpu 6050s.

I know how to physically wire the second sensor into the project but don't know how to do the coding side of things. The code I have is below. Any help is greatly appreciated. This is a very fun tool.

```
#include<Wire.h>
const int MPU_addr=0x68;
int16_t axis_X,axis_Y,axis_Z;
int minVal=265;
int maxVal=402;
double x;
double y;
double z;

void setup(){
  Wire.begin();
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x6B);
  Wire.write(0);
  Wire.endTransmission(true);
  Serial.begin(9600);
}
void loop(){
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x3B);
  Wire.endTransmission(false);
  Wire.requestFrom(MPU_addr,14,true);
  axis_X=Wire.read()<<8|Wire.read();
  axis_Y=Wire.read()<<8|Wire.read();
  axis_Z=Wire.read()<<8|Wire.read();
    int xAng = map(axis_X,minVal,maxVal,-90,90);
    int yAng = map(axis_Y,minVal,maxVal,-90,90);
    int zAng = map(axis_Z,minVal,maxVal,-90,90);
       x= RAD_TO_DEG * (atan2(-yAng, -zAng)+PI);
       y= RAD_TO_DEG * (atan2(-xAng, -zAng)+PI);
       z= RAD_TO_DEG * (atan2(-yAng, -xAng)+PI);
     Serial.print("Angle of inclination in X axis = ");
     Serial.print(x);
     Serial.println((char)176);
     Serial.print("Angle of inclination in Y axis= ");
     Serial.print(y);
     Serial.println((char)176);
     Serial.print("Angle of inclination in Z axis= ");
     Serial.print(z);
     Serial.println((char)176);
     Serial.println("-------------------------------------------");
     delay(1000);
}

```

# Answer
> 1 votes
Ok first did YOU wiring theme correctly? Because the mpu use i2c BUS . Second this code from gitlab it may help you . https://gitlab.com/shuvashish/batikkrom.com/blob/master/MuttipleMPU/MuttipleMPU.ino Check it . And use it

---
Tags: i2c, mpu6050
---


title: Powering arduino with battery

text:
# Question
Title: Powering arduino with battery
I haven't tried so don't know if it works or not. So I got a 6v battery AA, is it possible to run my arduino uno which already got a code in it if I plug + pin to vin and - to GND? Without its USB?

# Answer
Get a 5 battery holder and put 5 alkaline batteries into it. (5 battery holders are sometimes used to provide 6 volts from ni-cat or NiMh batteries, which provide ≈1.2V.

5 alkaline AA batteries would give you ≈7.5V, which gives you more "wiggle room" for the voltage regulator.

## EDIT:

As Gerben pointed out in their comment, 5 AA batteries will drop below the minium voltage input to the Arduino's voltage regulator well before they are depleted. A 6 battery holder would let you use more of the total battery capacity. (At the cost of wasting the excess voltage as heat.)
> 1 votes

# Answer
The UNO recommends at least 7 Volts on the Vin. 6 Volt is the absolute minimum. As the AA batteries drain, the voltage will be below this 6 Volts very quickly.

I tend to use a 3xAA battery holder, giving around 4.5Volt, and connect that straight to the Vcc pin (bypassing the voltage regulator). This works just fine in most cases.
> 1 votes

# Answer
Go and buy some 9v Duracell battery and use it . Put the plus in Vin and the negative in gnd . Also i noticed that you are a newbie to arduino so be aware. 5v pin in arduino it's an output voltage. 3.3 v also output voltage. Vin is the vcc is An electronics designation that refers to voltage from a power supply connected to the "collector" terminal of a bipolar transistor. In an NPN bipolar (BJT) transistor, it would be +Vcc, while in a PNP transistor, it would be -Vcc. Gnd mean ground . Read this please. https://www.pcmag.com/encyclopedia/term/53705/vcc
> 0 votes

---
Tags: arduino-uno, battery
---


title: Maintaining time in Arduino

text:
# Question
Title: Maintaining time in Arduino
I am working on development of alarm clock using Arduino.

No doubt RTC will be the best but it increases the Price of the project. Also I opened a digital clock (which I purchased online) and I see that there is only one IC (obviously it is covered with something black wax). But there was that one patch only. So it seems it used only a controller or RTC. But with only RTC its not possible to control LCD. So it must be only a microcontroller

Now I have three options for maintaining time

1. I use RTC like DS3231
2. I use millis() function
3. I use timer and timer interrupts of micro controller for free running timer.

Can I get accurate time using micro controller.

# Answer
I see from eBay that you can get the DS1307 for around 10 cents. Is that really too much to pay? You also need a crystal and a backup battery (eg. CR2032). Without a battery the device cannot possibly remember the time if it is powered off.

If your device is battery powered then you could conceivably just use millis(), however you would need to have a way of setting the time. The resonator used on a Uno is not as accurate as a crystal, however that might be good enough depending on your project.

If you are trying to save money I wouldn't use a Uno or Micro, but the bare chip, with a few extra components (eg. decoupling capacitors, a couple of resistors, and a crystal).
> 2 votes

---
Tags: arduino-uno, arduino-micro, rtc, ds3231-alarms
---


title: How to use Serial.setTimeout()

text:
# Question
Title: How to use Serial.setTimeout()
I am just playing with the UART interface of my board to learn about how it works. Since I have only one board, I send data out just to receive them by my own board, which is working so far.

Now I wanted to find out what Serial.setTimeout() is for. As per description on the Arduino homepage, it sets the maximum time for to wait for data. The description says, upon others Serial.find() will use it.

So I set Serial.setTimeout() to 100ms, and between sending and trying to receive data, I put a delay of 500ms. Therefore my expectation would be, Serial.find() will not detect a message, since there is more than 100ms no traffic on the bus. But I am still recieving data, it seems that the Serial.setTimeout() has no effect.

What is wrong in my understanding/usage of Serial.setTimeout()?

Here is my example sketch:

```
#include <M5Stack.h> // needed for my board M5Stack

HardwareSerial Serial2(2); // R2: Recieve Serial2, 17: Transmit Serial2  --> connnect pin R2 and 17

unsigned char buf_recive[1];
unsigned char buf_transmit[2] = {0x42, 0x00};

void setup()
{
  M5.begin();
  Serial.begin(9600);    // setting baud rate for COM3
  Serial2.begin(9600);   // setting baud rate for M5Stack2M5Stack communication
  Serial2.setTimeout(100);    //set the Timeout to 100ms
}

void loop()
{
  delay(500);
  // send buf_transmit
  Serial2.write(buf_transmit, 2);
  delay(500);
  // detect first byte of recieve message
  if (Serial2.find(0x42))
  { //start to read when detect 0x42
    Serial2.readBytes(buf_recive, 1);
    Serial.println(buf_recive[0]);
  }
  buf_transmit[1] = buf_transmit[1] + 0x01; // just to see that something's going on
}

```

And here some prove, that I am still receiving data:

# Answer
> 3 votes
The bytes are received to rx buffer with interrupt in the core. The find() function finds them there after the 500 millis delay. Timeout is to wait for the next byte if the rx buffer is empty.

The timeout is good if you know that the other side sends a collection of characters or bytes. Like for example a line sent from Serial Monitor or a Http request on networking client. The transmition has small gaps between bytes, but you want to receive it at once. So a function waiting a little for the next byte is useful.

Serial, networking Client classes and other Arduino stream classes inherit reading functions from the Stream class. This class has all the read and parse functions. There are 3 non blocking functions `available`, `read` and `peek`. All other read and parse functions use the timeout and wait for the next byte if the rx buffer is empty.

try this sketch with Serial Monitor

```
void setup() {
  Serial.begin(115200);
  Serial.setTimeout(10000);
}

void loop() {
  if (Serial.available()) {
    String s = Serial.readString();
    s.trim();
    Serial.println(s);
  }
}

```

send a line from Serial Monitor. a couple of characters. then send fast another line and then wait longer then 10 secs and send one more.

---
Tags: serial, uart
---


# Question
Title: Code test the duration press of the button
I wrote code that tracks the duration of a button click. It has bounce protection and frequent clicks. (Freeze)

My code:

```
bool freeze_time, btn_read, debounce;
unsigned int freeze_timer, btn_timer;

#define BTN 6

void setup() {
  Serial.begin(9600);
  pinMode(BTN, INPUT);
}

void loop() {
  /* Freeze Timer Protection */
  if(freeze_time) {
    if((millis() - freeze_timer) >= 2500) {
      freeze_time = false;
      btn_read = false;
    }
  }
  /* Read Button State */
  if(digitalRead(BTN) == HIGH) {
    if(!btn_read) {
      btn_timer = millis();
      debounce = true;
      btn_read = true;
    }
  }
  /* BTN Read Process */
  if(btn_read) {
    /* Debounce Protection */
    if(debounce) {
      if((millis() - btn_timer) >= 1000) {
        if(digitalRead(BTN) == HIGH) {
          Serial.println("Debounce ok.");
          btn_timer = millis();
          debounce = false;
        } else {
          Serial.println("Debounce fail.");
          freeze_time = true;
          debounce = false;
        }
      }
    }
    /* BTN Read Process */
    else if(!freeze_time) {
      if((millis() - btn_timer) >= 1500) {
        if(digitalRead(BTN) == HIGH) {
          Serial.println("Ok. Button Pressed > 1500ms");
          freeze_timer = millis();
          freeze_time = true;
        } else {
          Serial.println("Ok. Button Pressed < 1500ms");
          freeze_timer = millis();
          freeze_time = true;
        }
      }
    }
  }
}

```

I checked it on real Arduino UNO and Tinkercad simulator. Initially, everything works well, but if I press the button indefinitely, the system will fail (every time you press the serial port, messages appear as if all flags were lost and the timers did not work. I filmed the behavior:

1) Initially: http://recordit.co/lVlR1z1CUq 2) System is broken: http://recordit.co/lhvzM100DI

What could be the problem and how to make it fault tolerant?

# Answer
# Why did the timers stop working?

The main issue seems to be that `freeze_timer` and `btn_timer` are of type `unsigned int`, while `millis`, as stated in its documentation, returns an `unsigned long`.

As you may know, `unsigned int` is normally be able to hold a much smaller range of values than `unsigned long`. In the case of whatever compiler Tinkercad uses for the Arduino Uno, I checked and `unsigned int` can hold values from 0 to 65535, while `unsigned long` can hold values from 0 to 4294967295. Whenever you save an `unsigned long` into an `unsigned int`, it will be reduced modulo 65536.

This means that once you pass 65.536 seconds checks such as the `(millis() - freeze_timer) >= 2500` will always be true (at least until `millis` wraps back around after 4294967.296 seconds - around 50 days).

If you would like to learn a bit more about integer conversions, I think this Stack Overflow question covers it.

The simplest solution is, of course, to declare `freeze_timer` and `btn_timer` to be of the appropriate type, `unsigned long`.

# Use simpler code

All of the above being said, like Gerben said, the code seems overly complex.

There also seem to be other issues. For instance, I would expect the debounce behavior should not ignore presses that last less than 1 second. Like Gerben said, 10 ms should be enough to discard any bounces.

Furthermore, I think it would be more appropriate to not even discard presses that last less than 10 ms. I would say the debouncer should trigger "press" regardless of whether the press lasted less than 10 ms. It's role should just be to ignore *multiple* presses within that 10 ms window (although to be fair, ignoring short presses is not a terribly big issue).

Although one could make some guesses, to really help you with this, we would need a description of your intended behavior. What is the purpose of freezing? Is it intended to allow multiple presses to be triggered when you never release the button (or maybe you should wait until release before triggering one again)?
> 4 votes

---
Tags: timers, button, debounce
---


# Question
Title: Operating AD5780 EVAL Board Via MicroController
OK, so thanks in advance because I am new here. I am reading the AD57XX drivers here https://wiki.analog.com/resources/tools-software/uc-drivers/renesas/ad5780 and am struggling to understand how to get the device working and understanding it properly.

I am using code here https://github.com/maxgerhardt/arduino-ad57xx-driver/blob/master/src/main.cpp in order to test the DAC. I have several questions about the drivers and operation in general. I will itemize them if that is ok

1. Where in the drivers am I performing Slave Select and where am I determining Clock Speed? I have looked through the C in the drivers library, and it seems that each command, whether reading or writing selects the Slave/Master each time? I see no reference to which pins on my microcontroller it is reference though so I do not know if any of this is right.
2. Why do I need to be reading in the Control Register or anything from the DAC at all? Why does this matter? All I want is to output a voltage
3. How do I perform the right conversion to a voltage that I want? The command " AD57XX\_SetDacValue() " takes a long, but I do not understand how that relates to a float value of voltage. Say I want 2.35 Volts, or a Sine Function from -2 to 2 Volts, how do I do this conversion?
4. I don't know how to debug the system in general. When I run the example code, which is supposed to output a triangle wave function, I get a sin function, which seems to just be noise.

# Answer
> 0 votes
> Where in the drivers am I performing Slave Select and where am I determining Clock Speed? I have looked through the C in the drivers library, and it seems that each command, whether reading or writing selects the Slave/Master each time? I see no reference to which pins on my microcontroller it is reference though so I do not know if any of this is right.

The slave select is controlled within the `SPI_Write()` function. It uses the `PinMgt_PinWrite()` function to do the slave select control, which in turn selects a pin from the `pinMapping[]` lookup table.

The clock speed is set in `AD5780_Init()`.

> Why do I need to be reading in the Control Register or anything from the DAC at all? Why does this matter? All I want is to output a voltage

You don't. The code is just for demonstration purposes. It shows you how you could query those registers. If you don't need to, then don't.

> How do I perform the right conversion to a voltage that I want? The command " AD57XX\_SetDacValue() " takes a long, but I do not understand how that relates to a float value of voltage. Say I want 2.35 Volts, or a Sine Function from -2 to 2 Volts, how do I do this conversion?

That value is the raw value to set the DAC to. You refer to the DAC datasheet to know what that value equates to. In this case the range is from \\$V\_{REFN}\\$ to \\$V\_{REFP}\\$. Divide that range by 218 and you have the voltage per bit.

> I don't know how to debug the system in general. When I run the example code, which is supposed to output a triangle wave function, I get a sin function, which seems to just be noise.

You need some debugging tools. Things like a logic analyser to be able to acually see what the IO pins of your MCU are doing. An oscilloscope can be used to see if a signal is present, but to see all the SPI signals together you really want a logic analyser.

---
Tags: digital-analog-conversion
---


# Question
Title: I'm getting NaN for readings on my DHT22 sensor when using 3v3 pin, but not 5v pin
I have a DHT22 temperature sensor and DS1302 RTC module connected to the 3v3 pins on an Arduino Nano. Both the sensor and the RTC module are rated to work on either 3.3V or 5V, but the recommendation is 3.3V. For some reason though, when I connect the sensor and RTC to 3.3V power on the Nano, the sensor just returns NaN even though the RTC module works. When I change the sensor to use 5V and leave the RTC on 3.3V, I get a proper temp and humidity value on the DHT22. What is wrong?

Turns out the solder joint for the 3v3 pin on the nano was not properly done. I figured this out after I swapped out the nano for another nano and it worked. Resoldering the 3v3 pin fixed the problem.

# Answer
> 1 votes
Sometimes the problem is simply that you didn't properly solder the headers onto the Arduino. You should check to make sure that your solder joints are all good.

---
Tags: sensors, power
---


title: Issues with CO2 sensor SEN0159

text:
# Question
Title: Issues with CO2 sensor SEN0159
I followed the sketch example for the SEN0159 CO2 sensor as precised in the data sheet https://www.dfrobot.com/wiki/index.php/CO2\_Sensor\_SKU:SEN0159. It's powered by a 9V/2A DC power supply more than 48h and it still reads 2.81V on the analog ouput pin even if i exhaust on the sensor during long time, nothing happen, giving - 1ppm CO2 value.

Can you explain me why i cannot observe CO2 variations ? Is there troubles with the board ?

Thanks!

# Answer
> 1 votes
Yes, i made a mistake... The arduino board should be powered by a 7-12V power supply to support high current from 5V pinout in order to power the sensor card... I'm very lucky, my sensor is not broken. I have powered it with 5V and it works fine!!! Thanks

---
Tags: arduino-mega
---


title: Not sure which Arduino to pick

text:
# Question
Title: Not sure which Arduino to pick
Is the Arduino Uno the best one to purchase for a complete beginner?

I eventually want to get into building Nodebots since I already have experience writing Nodejs web-based applications.

Or should I go directly to purchasing an Arduino Starter Kit? SparkFun Inventors Kit? Adafruit ARDX Experimentation Kit for Arduino? Seeed Studio ARDX starter kit? or Freetronics Experimenter’s Kit for Arduino?

I don't know the difference between these and based off what I have shared about my situation so far, which one should I start with to A. Learn the Basics, B. Evolve into developing Nodebots.

# Answer
> 0 votes
NodeBots does external control of Arduino with Java Script. The controlling computer is a PC or a SOC like Raspberry PI. (Eventually Raspberry can run NodeBots without Arduino.)

For NodeBots, Arduino board runs a firmware called Firmata which executes the commands sent by the Johnny-Five Java Script firmata master library.

I would recommend you to learn C++ and Arduino functions and libraries and code the Arduino directly without Firmata and a controlling computer.

---
Tags: arduino-uno, node.js
---


# Question
Title: Why LCD 16x2 cannot display "water leaking" when rain sensor detects water?
```
#include <SoftwareSerial.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
SoftwareSerial mySerial(0, 1);

int gas_sensor = A5;
int water_sensor = 8;
int buzzer = 9;
int fan = 13;
int sms_count = 0;

void setup() {
  pinMode(gas_sensor, INPUT);
  pinMode(water_sensor, INPUT);
  pinMode(buzzer, OUTPUT);
  pinMode(fan, OUTPUT);
  mySerial.begin(9600);
  Serial.begin(9600);
  lcd.begin(16, 2);
  delay(500);
}

void loop() {
  if (digitalRead(water_sensor) == LOW && analogRead(gas_sensor)) {
    CheckWater_and_Gas();
  }
  else if (digitalRead(water_sensor) == LOW) {
    CheckWater();
  }
  else if (analogRead(gas_sensor)) {
    CheckGas();
  }
  else {
  }
}

void CheckWater_and_Gas() {
  int sensorValue = analogRead(gas_sensor);
  Serial.println(sensorValue);
  delay(1000);
  if ( digitalRead(water_sensor) == LOW && sensorValue > 150 ) {
    digitalWrite(buzzer, HIGH);
    digitalWrite(fan, HIGH);
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print(" Water and ");
    lcd.setCursor(0, 1);
    lcd.print(" Gas Leaking ! ");
    SetAlertWater_and_Gas();
  }
  else {
    digitalWrite(buzzer, LOW);
    digitalWrite(fan, LOW);
    lcd.clear();
  }
}

void CheckWater() {
  if ( digitalRead(water_sensor) == LOW ) {
    digitalWrite(buzzer, HIGH);
    lcd.clear();
    lcd.setCursor(0, 1);
    lcd.print(" Water Leaking ! ");
    SetAlertWater();
  }
  else {
    digitalWrite(buzzer, LOW);
    lcd.clear();
  }
}

void CheckGas() {
  int sensorValue = analogRead(gas_sensor);
  Serial.println(sensorValue);
  delay(1000);
  if (sensorValue > 150) {
    digitalWrite(buzzer, HIGH);
    digitalWrite(fan, HIGH);
    lcd.clear();
    lcd.setCursor(0, 1);
    lcd.print("Gas Leaking !");
    SetAlertGas();
  }
  else {
    digitalWrite(buzzer, LOW);
    digitalWrite(fan, LOW);
    lcd.clear();
  }
}

```

# Answer
You schould start searching the root cause for your error: code, display, sensor, … step by step.

Check if your display is working by 1.) reducing your loop() to

```
void loop() {
    CheckWater();
}

```

and 2.) change

```
void CheckWater() {
  if ( digitalRead(water_sensor) == LOW ) {
    digitalWrite(buzzer, HIGH);
    ...

```

to

```
void CheckWater() {
  if ( true ) {
    digitalWrite(buzzer, HIGH);
   ...

```

This allows you to check if your LCD is working properly. If not, start looking for the fault in wiring or maybe you are using a different LCD which has to be setup in a different mode as the sketch from online.

If this works, search for the rootcause in the sensor. Go back to the orignial code and put the input of the rain sensor to low. If your display shows: Water Leaking! something with your water sensor or it's Connection to your board seems to be wrong.
> 1 votes

---
Tags: arduino-mega, sensors, lcd
---


# Question
Title: Distance Sensor. Calculating running median and average
I'm trying to smooth out values for my IR distance sensor through running median filtering and a running average. I've tried to do the averaging, but my values don't seem correct and I am confused about how I would do the median filtering. I am also using timer interrupts and I don't want to use libraries when calculating the average and median. I've attached the code where I attempted to calculate the average.

```
int analogpin = 5;
int sum = 0;
int index = 0;
int averead = 0;
const int numreadings = 9;
int i;
int timer1_counter;
int adc_val;
int int_flag;
int int_array[9];
float V;

void setup() {
  int_flag = 0;
  Serial.begin(9600);
  pinMode(analogpin, OUTPUT);
  for (i = 0; i <= 8; i++) {
    int_array[i] = 0;
  }

  noInterrupts();
  TCCR1A = 0;
  TCCR1B = 0;
  timer1_counter = 59286;
  TCNT1 = timer1_counter;
  TCCR1B |= (1 << CS12);
  TIMSK1 |= (1 << TOIE1);
  interrupts();
}

ISR(TIMER1_OVF_vect) {
  TCNT1 = timer1_counter;
  int_flag = 1;
}

void loop() {
  if (int_flag == 1) {
    adc_val = analogRead(A2);
    V = 5.0 * adc_val / 1023.0;
    analogWrite(analogpin, adc_val / 4);
  }
  sum = sum - int_array[i];
  int_array[i] = analogRead(A2);
  sum = sum + int_array[i];
  index = index++;
  if (i == 9) {
    i = 0;
  }
  averead = sum / numreadings;
  Serial.print("\n"); Serial.print("Average Filter Reading: ");
  Serial.println(averead);
  delay(1);
}

```

# Answer
> 1 votes
There are two main problems with your program. The first is noted in Gerben's comment: you (attempt to) increment `index` (with a bad syntax), while you should be incrementing `i` instead. The second problem is these lines:

```
for (i = 0; i <= 8; i++) {
    int_array[i] = 0;
}

```

Fix the `index` vs. `i` confusion, remove the lines above, and your program should work.

**Explanation**: The first point should be obvious, I hope. I am discussing here the second issue. At the end of the loop above, the index `i` has the value 9. Later, in `loop()`, and assuming you fixed the first issue, the program does

```
i++;
if (i == 9) {
    i = 0;
}

```

and `i` has the value 10. From there `i` will continue incrementing, and you are always writing outside of the array.

The root of the problem is that you used the same variable `i` for two different purposes. There are several solutions to this:

* use different variable names for different purposes
* use local variables whenever applicable (here: in `setup()`)
* be defensive in your tests: instead of `if (i == 9)` write `if (i >= 9)`, but note that this alleviates but does not completely solve the problem
* remove the initialization of the array altogether.

I suggest removing the initialization because the array is a global variable and, per the C++ standard, if not explicitly initialized it is implicitly initialized to zero, so your initialization is redundant.

# Answer
> 0 votes
`analogRead()` returns an integer and therefore your calculation `V=adc_val*(5.0/1023.0)` will be casted as int as well. I suggest changing it to `V=5.0*adc_val/1023.0`.

In general a running mean can be calculated like this:

```
#define buffer_size 9
#define analog_pin 5

int ring_buffer[buffer_size];
uint8_t index=0;
float running_mean() {
  ring_buffer[index]=analogRead(analog_pin);
  float mean=0;
  for (uint8_t i=0;i<buffer_size;i++) {
    mean+=ring_buffer[i];
  }
  if (++index>=buffer_size) index=0;
  return mean/buffer_size;
}

```

You should flush the buffer during initialization, otherwise you don't get proper readings before the 9th iteration.

# Answer
> 0 votes
Here is a simple alternative suggestion: Assuming you already know the average distance *d* and a new reading *v* comes in. The difference *v-d* can be used to update the average. But since you want you want to smooth this out over several readings, you only update *d* by a fraction of the difference: *d += 0.8\*(v-d)*. The factor controls the smoothing.

To get this started, you estimate that the first value you read is the average. This does not require an array to keep past readings around.

---
Tags: arduino-leonardo
---


title: 7 LED Number Display

text:
# Question
Title: 7 LED Number Display
I need to write a string of number such as 1234567 on a 7 LED display. For example 1 will be lit up on display for 0.5 seconds, it will turn off then 2 will light up and so on. In the end I need to display "-" for 2 seconds. I also added the image of the given task.

The following is the code I wrote. I would like to ask if it is the correct, and are there any flaws.

```
  const int LEDa=13;
  const int LEDb=12;
  const int LEDc=11;
  const int LEDd=10;
  const int LEDe=9;
  const int LEDf=8;
  const int LEDg=7;

  int i;
  int a;

  void setup() {

    pinMode(LEDa, OUTPUT);
    pinMode(LEDb, OUTPUT);
    pinMode(LEDc, OUTPUT);
    pinMode(LEDd, OUTPUT);
    pinMode(LEDe, OUTPUT);
    pinMode(LEDf, OUTPUT);
    pinMode(LEDg, OUTPUT);

  }

  void loop() {
    int array[7]= {1,8,0,5,1,0,0};
    for(i=0;i<8;i++){
      a= array[i];
      }
        switch(a){
          case 1:
          digitalWrite(LEDb,HIGH);
          digitalWrite(LEDc,HIGH);
          delay(500);
          digitalWrite(LEDb,LOW);
          digitalWrite(LEDc,LOW);
          break;
          case 2:
          digitalWrite(LEDa,HIGH);
          digitalWrite(LEDb,HIGH);
          digitalWrite(LEDg,HIGH);
          digitalWrite(LEDe,HIGH);
          digitalWrite(LEDd,HIGH);
          delay(500);
          digitalWrite(LEDa,LOW);
          digitalWrite(LEDb,LOW);
          digitalWrite(LEDg,LOW);
          digitalWrite(LEDe,LOW);
          digitalWrite(LEDd,LOW);
          break;
          case 3:
          digitalWrite(LEDa,HIGH);
          digitalWrite(LEDb,HIGH);
          digitalWrite(LEDc,HIGH);
          digitalWrite(LEDg,HIGH);
          digitalWrite(LEDd,HIGH);
          delay(500);
          digitalWrite(LEDa,LOW);
          digitalWrite(LEDb,LOW);
          digitalWrite(LEDc,LOW);
          digitalWrite(LEDg,LOW);
          digitalWrite(LEDd,LOW);
          break;
          case 4:
          digitalWrite(LEDf,HIGH);
          digitalWrite(LEDg,HIGH);
          digitalWrite(LEDb,HIGH);
          digitalWrite(LEDc,HIGH);
          delay(500);
          digitalWrite(LEDf,LOW);
          digitalWrite(LEDg,LOW);
          digitalWrite(LEDb,LOW);
          digitalWrite(LEDc,LOW);
          break;
          case 5:
          digitalWrite(LEDf,HIGH);
          digitalWrite(LEDg,HIGH);
          digitalWrite(LEDd,HIGH);
          digitalWrite(LEDc,HIGH);
          digitalWrite(LEDa,HIGH);
          delay(500);
          digitalWrite(LEDf,LOW);
          digitalWrite(LEDg,LOW);
          digitalWrite(LEDd,LOW);
          digitalWrite(LEDc,LOW);
          digitalWrite(LEDa,LOW);
          break;
          case 6:
          digitalWrite(LEDf,HIGH);
          digitalWrite(LEDg,HIGH);
          digitalWrite(LEDa,HIGH);
          digitalWrite(LEDc,HIGH);
          digitalWrite(LEDe,HIGH);
          digitalWrite(LEDd,HIGH);
          delay(500);
          digitalWrite(LEDf,LOW);
          digitalWrite(LEDg,LOW);
          digitalWrite(LEDa,LOW);
          digitalWrite(LEDc,LOW);
          digitalWrite(LEDe,LOW);
          digitalWrite(LEDd,LOW);
          break;
          case 7:
          digitalWrite(LEDa,HIGH);
          digitalWrite(LEDb,HIGH);
          digitalWrite(LEDc,HIGH);
          delay(500);
          digitalWrite(LEDa,LOW);
          digitalWrite(LEDb,LOW);
          digitalWrite(LEDc,LOW);
          break;
          case 8:
          digitalWrite(LEDa,HIGH);
          digitalWrite(LEDb,HIGH);
          digitalWrite(LEDc,HIGH);
          digitalWrite(LEDd,HIGH);
          digitalWrite(LEDe,HIGH);
          digitalWrite(LEDf,HIGH);
          digitalWrite(LEDg,HIGH);
          delay(500);
          digitalWrite(LEDa,LOW);
          digitalWrite(LEDb,LOW);
          digitalWrite(LEDc,LOW);
          digitalWrite(LEDd,LOW);
          digitalWrite(LEDe,LOW);
          digitalWrite(LEDf,LOW);
          digitalWrite(LEDg,LOW);
          break;
          case 9:
          digitalWrite(LEDa,HIGH);
          digitalWrite(LEDb,HIGH);
          digitalWrite(LEDc,HIGH);
          digitalWrite(LEDd,HIGH);
          digitalWrite(LEDf,HIGH);
          digitalWrite(LEDg,HIGH);
          delay(500);
          digitalWrite(LEDa,LOW);
          digitalWrite(LEDb,LOW);
          digitalWrite(LEDc,LOW);
          digitalWrite(LEDd,LOW);
          digitalWrite(LEDf,LOW);
          digitalWrite(LEDg,LOW);
          break;
          case 0:
          digitalWrite(LEDa,HIGH);
          digitalWrite(LEDb,HIGH);
          digitalWrite(LEDc,HIGH);
          digitalWrite(LEDd,HIGH);
          digitalWrite(LEDe,HIGH);
          delay(500);
          digitalWrite(LEDa,LOW);
          digitalWrite(LEDb,LOW);
          digitalWrite(LEDc,LOW);
          digitalWrite(LEDd,LOW);
          digitalWrite(LEDe,LOW);
          digitalWrite(LEDf,LOW);
          break;
          }
          if(i=8){
            digitalWrite(LEDg,HIGH);
            delay(2000);
            digitalWrite(LEDg,LOW);
            }
          }

```

# Answer
I see 3 errors:

1. You define the array to have 7 elements, but in the `for` loop, you count 8 elements, by using `i<8` (Array indizes start at 0, so 0 will be the first and 6 will be the last element). Currently you try to access an array element, that does not exist.
2. The `if` statement is also not useful here. In your current code you check for `i` being equal to 8, but it will never be 8 inside of the `for` loop, because you used the condition `i<8`. To display the last `-` after the number, you should put the code after the `for` loop.
3. In the same `if` statement you write `i=8`, but a single equality sign means assignment. The value 8 will be assigned to the variable `i` and this assignment is true everytime. If you want to test equality use `==` (double equality signs)

---

Tip: You can make your code smaller by defining functions for codes parts, that get repeated often (for example the code to turn off all LEDs).

Tip2: If you want the code to be very efficient, you can change the pins to use one single port. Then you can change all the pins of the port at once, by assigning a single byte to it. You can save these bytes in an array. This will make your code way shorter, but you also need a deeper understanding about port manipulations. You can choose, what you want to do.
> 2 votes

# Answer
It looks like it is mostly correct, although that is a very long-winded way to set 7 segments to multiple values. I would be more inclined to set up an array of bytes where 7 bits of each byte contain ones/zeros to control the LEDs. Then you could skip the massive switch statement and simply loop through the array of bytes.

One mistake: `if(i=8)` should be `if (i == 8)`. (`=` is an assignment. You want the `==` comparison operator.) Your code won't work correctly until you fix that.
> 0 votes

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


title: How to stop motor after a desired time?

text:
# Question
Title: How to stop motor after a desired time?
I am trying to stop a dc motor after a desired amount of time !! And the motor starts upon settling on a condition !! From that very moment i want my motor to just run for 5 seconds and stop!! Below is the pseudocode:

```
 #define max 150
 #define min -150
 #define pin1 3
 void setup()
    {
        Serial.begin(9600);
         mpu.initialise();
     }
   void loop()
     {
        x= some_accelerometer_values;
         If (x>250)
            {
                analogWrite(pin1,255);
                delay(5000);
                exit(0);
             }
      }

```

I tried using millis() but it starts time with execution of program and i can't get to implement it just before the motor starts running!

# Answer
> 0 votes
Assuming you turn your motor on with `analogWrite(pin1, 255);` just write `analogWrite(pin1, 0);` after the `delay(5000);`.

And using `exit(0);` isn't as bad as people will most likely say. Using exit(0) is the same as `cli();` \+ `while(1)`. So it disables interrupts and stucks your code in a while loop till your reset the arduino.

---
Tags: arduino-nano, motor
---


title: Basic Arduino Airplane Control

text:
# Question
Title: Basic Arduino Airplane Control
I have a task where I need to control the airplanes thrust and altitude direction(Up-Down). For the thrust I thought of using a DC Motor and a Servo for the other. Control of servo will be from the buttons and the thrust value will be given from the serial port. (This is not a project of a real vehicle, only thing I need to do is the code, rest is imaginary.)

I have wrote the following code. I would like to ask is there any flaws and how can I further improve it? Thanks in advance. With my regards...

```
#include <Servo.h>
  Servo servo1;
  int pos = 0;
  const int buttonSUP = 2;
  const int buttonSDOWN = 3;

  int buttonStateUP = 0;
  int buttonStateDOWN = 0;

  int motorPin = 4;

  void setup() {

  servo1.attach(9);
  pinMode( buttonSUP, INPUT);
  pinMode( buttonSDOWN, INPUT);

  pinMode(motorPin, OUTPUT);
    Serial.begin(9600);
    while (! Serial);
    Serial.println("Speed 0 to 255");

  }

  void loop() {
   buttonStateUP =digitalRead(buttonSUP);
   if(buttonStateUP=HIGH){
      servo1.write(90);
      Serial.println("UP");
    }
    if(buttonStateDOWN=HIGH){
      servo1.write(0);
     Serial.println("DOWN");
      }
    else{
        servo1.write(45);
        Serial.println("STABLE");
        }

    if (Serial.available())
    {
      int speed = Serial.parseInt();
      if (speed >= 0 && speed <= 255)
      {
        analogWrite(motorPin, speed);
        Serial.println(speed);
      }
    }

    }

```

# Answer
> 0 votes
`while (! Serial);` Is not needed if you have a board with USB-\> Serial bridge Chip (arduino uno for example)

```
if(buttonStateDOWN=HIGH){
}

```

In every condition you used `=` instead of `==`. Your "condition" actually assigns `HIGH` to `buttonStateDOWN`. If you want to compare integers, use `==`.

And according to the question, I think you have misunderstood the speed buttons (or maybe I have). I think, they want you to code it so while the button is pressed or every time the button is pressed, the speed changes by +1 or -1.

Assuming the rest works fine, there could be a problem with your serial output, since you just spam messages.

Read about the `millis();`, it can help you so you only send something every x amount of seconds, without using `delay();` Here

---
Tags: arduino-uno, motor, servo
---


# Question
Title: Problem opening multiple text files simultaneously/in-order using <SD.h>
I am looking to log analog sensor data using 3 pins, A1, A2, A3. My project requires continuous mapping of data, and hence an SD card shield was necessary. However, I need to log the incoming data into 3 different text files, and for that purpose I assumed that opening the 3 files simultaneously might or might not be possible as indicated here (I am a beginner, so I wasn't able to comprehend everything, and I am short on resources:)

So for the time being, I worked my way around with opening the three files in order. Rather than opening them all at once,writing the data on to each file and then closing them, I did all three tasks in 1) separate functions for all three files and calling them in the loop() function, 2)keeping all the stuff in the loop() function itself.The result for method-1 was no file was ever created, and that for method-2 was only the first file was created and the rest, nope. Here's the code for both the versions. What could I be doing wrong? Thanks in advance!

My board is an Arduino Uno. Yes, I have formatted the SD card with FAT32. My wiring is in place, my code is the only possible problem I see.

**Method 1**

```
#include <SD.h>
File Cu_volt;
File Gunmet_volt;
File Al_volt;
static float volt_Cu, volt_Gunmet, volt_Al;

void setup() {
  Serial.begin(9600);
  analogReference(INTERNAL);
  pinMode(A1, INPUT);
  pinMode(A2, INPUT);
  pinMode(A3, INPUT);

  //Initialize SD card module, CS pin set at 4
  Serial.println("INITIALIZING SD CARD...");
  //check for SD errors
  if ( !SD.begin(4)) {
    Serial.println("INITIALIZATION FAIL...");
    while (1);
    return;
  }
  Serial.println("INITIALIZATION DONE");
}

void loop() {
  // read the input on analog pin 0 copper electrode:
  // Convert the analog reading (which goes from 0 - 1023) to a voltage (0 to VRef=INTERNAl)
 copperFile();
 gunmetalFile();
 aluminiumFile();
 delay(3000);

```

}

```
void copperFile() {
  Cu_volt = SD.open("Copper.txt", O_RDWR | O_APPEND);
  if (!Cu_volt) {
    Cu_volt = SD.open("Copper.txt", O_RDWR | O_CREAT);
    if (!Cu_volt) {
      Serial.println("Failed to open file at all");
    }
  }
  volt_Cu = analogRead(A1) * (1.1 / 1023.0);
  // print out the value read(COPPER):
  Serial.print("Copper voltage=");
  Serial.println(volt_Cu);
  if (Cu_volt) {
    Cu_volt.println(volt_Cu);
    Cu_volt.close();
  }
}

void gunmetalFile() {
  Gunmet_volt = SD.open("Gun_metal.txt", O_RDWR | O_APPEND);
  if (!Gunmet_volt) {
    Gunmet_volt = SD.open("Gun_metal.txt", O_RDWR | O_CREAT);
    if (!Gunmet_volt) {
      Serial.println("Failed to open file at all");
    }
  }
  volt_Gunmet = analogRead(A2) * (1.1 / 1023.0);
  // print out the value you read(GUNMETAL):
  Serial.print("Gun metal voltage=");
  Serial.println(volt_Gunmet);
  if (Gunmet_volt) {
    Gunmet_volt.println(volt_Gunmet);
    Gunmet_volt.close();
  }
}

void aluminiumFile(){
  //opening aluminium file
  Al_volt = SD.open("Aluminium.txt", O_RDWR | O_APPEND);
  if (!Al_volt) {
    Al_volt = SD.open("Aluminium.txt", O_RDWR | O_CREAT);
    if (!Al_volt) {
      Serial.println("Failed to open file at all");
    }
  }
   volt_Al = analogRead(A3) * (1.1 / 1023.0);
  // print out the value you read(ALUMINIUM):
  Serial.print("Aluminium voltage=");
  Serial.println(volt_Al);
  if (Al_volt) {
    Al_volt.println(volt_Al);
    Al_volt.close();
  }
}

```

**Method 2**

```
#include <SD.h>
File Cu_volt;
File Gunmet_volt;
File Al_volt;
static float volt_Cu, volt_Gunmet, volt_Al;

void setup() {
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
  analogReference(INTERNAL);
  pinMode(A1, INPUT);
  pinMode(A2, INPUT);
  pinMode(A3, INPUT);
  //Initialize SD card module, CS pin set at 4
  Serial.println("INITIALIZING SD CARD...");
  //check for SD errors
  if ( !SD.begin(4)) {
    Serial.println("INITIALIZATION FAIL...");
    while (1);
    return;
  }
  Serial.println("INITIALIZATION DONE");
}

void loop() {
  // read the input on analog pin 0 copper electrode:
  // Convert the analog reading (which goes from 0 - 1023) to a voltage (0 to VRef=INTERNAl)
  volt_Cu = analogRead(A1) * (1.1 / 1023.0);
  // print out the value you read(COPPER):
  Serial.print("Copper voltage=");
  Serial.println(volt_Cu);
  //opening copper file
  Cu_volt = SD.open("Copper.txt", O_RDWR | O_APPEND);
  if (!Cu_volt) {
    Cu_volt = SD.open("Copper.txt", O_RDWR | O_CREAT);
    if (!Cu_volt) {
      Serial.println("Failed to open file at all");
    }
  }
  if (Cu_volt) {
    Cu_volt.println(volt_Cu);
    Cu_volt.close();
  }
  volt_Gunmet = analogRead(A2) * (1.1 / 1023.0);
  // print out the value you read(GUNMETAL):
  Serial.print("Gun metal voltage=");
  Serial.println(volt_Gunmet);
  //opening copper file
  Gunmet_volt = SD.open("Gun_metal.txt", O_RDWR | O_APPEND);
  if (!Gunmet_volt) {
    Gunmet_volt = SD.open("Gun_metal.txt", O_RDWR | O_CREAT);
    if (!Gunmet_volt) {
      Serial.println("Failed to open file at all");
    }
  }
  if (Gunmet_volt) {
    Gunmet_volt.println(volt_Gunmet);
    Gunmet_volt.close();
  }
  volt_Al = analogRead(A3) * (1.1 / 1023.0);
  // print out the value you read(ALUMINIUM):
  Serial.print("Aluminium voltage=");
  Serial.println(volt_Al);
  //opening aluminium file
  Al_volt = SD.open("Aluminium.txt", O_RDWR | O_APPEND);
  if (!Al_volt) {
    Al_volt = SD.open("Aluminium.txt", O_RDWR | O_CREAT);
    if (!Al_volt) {
      Serial.println("Failed to open file at all");
    }
  }
 if (Al_volt) {
    Al_volt.println(volt_Al);
    Al_volt.close();
  }
  delay(3000);
}

```

# Answer
> 1 votes
There are several variations of the SD library - some support multiple files, others do not.

Try calling .begin (and .end) on each write loop, and add in .flush - see below.

If that works with your library then take the (.begin / .end) out of the loop and try again.

```
#define FILENAME "myfile.txt"

void writeToFile() {
    File f;
    // begin and end on each write
    if (SD.begin(10, 11, 12, 13)) { // I use an older library that allows pin reassignment
        f = SD.open(FILENAME, FILE_WRITE);  // This will append and create if not exisiting
        if(f) {
            f.println("a string");  // Your write operations
        }
        f.flush();          // This ensured the write buffer actually went to file
                            // even if less than the block size (512b?)

        f.close();
        }
    SD.end();                   // Do this after every write operation
}

```

# Answer
> 1 votes
For people having similar problems with creating multiple files on an SD card, it may be a memory issue. You need to have a certain amount of unused dynamic memory (about 300 bytes of free space, in my experience) in order to write to an SD card - and more if you are writing multiple files. Following the instructions on this page may help.

---
Tags: arduino-uno, analogread, sd-card, code-review, sd
---


title: MPU-6050 with Arduino - postmortem

text:
# Question
Title: MPU-6050 with Arduino - postmortem
I'm working with MPU-6050 with Arduino Uno.

I copied the code below from Arduino Playground - MPU6050.

Code :

```
  // MPU-6050 Short Example Sketch
  // By Arduino User JohnChi
  // August 17, 2014
  // Public Domain
  #include<Wire.h>
  const int MPU_addr = 0x68; // I2C address of the MPU-6050
  int16_t AcX, AcY, AcZ, Tmp, GyX, GyY, GyZ;
  void setup() {
    Wire.begin();
    Wire.beginTransmission(MPU_addr);
    Wire.write(0x6B);  // PWR_MGMT_1 register
    Wire.write(0);     // set to zero (wakes up the MPU-6050)
    Wire.endTransmission(true);
    Serial.begin(9600);
  }
  void loop() {
    Wire.beginTransmission(MPU_addr);
    Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
    Wire.endTransmission(false);
    Wire.requestFrom(MPU_addr, 14, true); // request a total of 14 registers
    AcX = Wire.read() << 8 | Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
    AcY = Wire.read() << 8 | Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
    AcZ = Wire.read() << 8 | Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
    Tmp = Wire.read() << 8 | Wire.read(); // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L)
    GyX = Wire.read() << 8 | Wire.read(); // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
    GyY = Wire.read() << 8 | Wire.read(); // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
    GyZ = Wire.read() << 8 | Wire.read(); // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)
    Serial.print("AcX = "); Serial.print(AcX);
    Serial.print(" | AcY = "); Serial.print(AcY);
    Serial.print(" | AcZ = "); Serial.print(AcZ);
    Serial.print(" | Tmp = "); Serial.print(Tmp / 340.00 + 36.53); //equation for temperature in degrees C from datasheet
    Serial.print(" | GyX = "); Serial.print(GyX);
    Serial.print(" | GyY = "); Serial.print(GyY);
    Serial.print(" | GyZ = "); Serial.println(GyZ);
    delay(333);
  }

```

Firstly, I want to know every details about this code, **AcX, AcY, AcZ, GyX, GyY, GyZ** what all these mean ?

*It will be nice with some visual representation.*

Secondly, If I change the delay to 500 from 333, will it cause a problem ?

*This type of stupid question because, I can't find any relatable figure with 333 except 1000/3*

# Answer
> 1 votes
```
AcX = Accelerometer data in X axis in floating point.
AcY = Accelerometer data in Y axis in floating point.
AcZ = Accelerometer data in Z axis in floating point.
GyX = Gyroscope data in X axis in floating point.
GyY = Gyroscope data in X axis in floating point.
GyZ = Gyroscope data in X axis in floating point

```

.

Secondly study regarding I2C communication and MPU 6050 datasheet.

Third you have any value for delay as it is how fast you want to fetch data from all axis from IMU.

# Answer
> 1 votes
I think that AcX, AcY, AcZ, GyX, GyY, GyZ are raw acceleration and gyroscopic values recieved from mpu6050 in the corresponding directions. in order to recieve them a procedure is followed.

```
 Wire.read();

```

means two registers are read and stored in the same variable

```
   accelerometer_x = Wire.read()<<8 | Wire.read();

```

reads registers: 0x3B (ACCEL\_XOUT\_H) and 0x3C (ACCEL\_XOUT\_L) that is , it deals with bitwise operation to shift the values 8 bits left (multiplying it by 256). This enables addition ("|" or "ored") of two datas in order to continuously output the accelerometer data !! Without this you would not be able to see the increasing and decreasing sloping values . Further, the print just displays the instantaneous values on screen.

If you want to go in deapth of the code, you can visit this site for line to line description !!

https://www.mschoeffler.de/2017/12/09/example-application-gy-521-module-mpu-6050-breakout-board-and-arduino-uno/

```
 delay(500);

```

Totally depends on your project, i don't see any forecoming issues if you will make 333 go 500 !! It will just stablize the output on screen there for a bit longer (for .5 seconds)

---
Tags: arduino-uno, i2c, accelerometer, mpu6050, gyroscope
---


# Question
Title: connection of led with dht and code combination
Hi again? I saw my last question did not come out well, so let me rephrase it. Ideally, my project is composed of 3 sensors: 2 dht-22 sensors and an mq-7 sensor. **For the dht22 sensors**, I am using data pin connections 9 and 10 PWM on the Arduino mega 2560 board with their respective 10 kilo-ohm resistors, with 5v supply and ground connections. The **issue** is that I want to set limits for both temperature and humidity for both sensors to be: (16

```
#include "DHT.h"

#define DHT1PIN 9     // what pin we're connected to
#define DHT2PIN 10

#define DHT1TYPE DHT22
#define DHT2TYPE DHT22

// Connect pin 1 (on the left) of the sensor to +5V
// Connect pin 2 of the sensor to whatever your DHTPIN is
// Connect pin 4 (on the right) of the sensor to GROUND
// Connect a 10K resistor from pin 2 (data) to pin 1 (power) of the sensor

DHT dht1(DHT1PIN, DHT1TYPE);
DHT dht2(DHT2PIN, DHT2TYPE);

void setup() {
  Serial.begin(115200);
  Serial.println("DHTxx test!");

  dht1.begin();
  dht2.begin();
}

void loop() {
  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h1 = dht1.readHumidity();
  float t1 = dht1.readTemperature();
  float h2 = dht2.readHumidity();
  float t2 = dht2.readTemperature();

  // check if returns are valid, if they are NaN (not a number) then something went wrong!
  if (isnan(t1) || isnan(h1)) {
    Serial.println("Failed to read from DHT #1");
  } else {
    Serial.print("Humidity 1: ");
    Serial.print(h1);
    Serial.print(" %\t");
    Serial.print("Temperature 1: ");
    Serial.print(t1);
    Serial.println(" *C");
  }
  if (isnan(t2) || isnan(h2)) {
    Serial.println("Failed to read from DHT #2");
  } else {
    Serial.print("Humidity 2: ");
    Serial.print(h2);
    Serial.print(" %\t");
    Serial.print("Temperature 2: ");
    Serial.print(t2);
    Serial.println(" *C");
  }
  Serial.println();
}

```

Ps: LEDs used are 10mm. For the **MQ-7 sensor**, this is it's code.

```
/* MQ-7 Carbon Monoxide Sensor Circuit with Arduino */

 const int AOUTpin=0;//the AOUT pin of the CO sensor goes into analog pin A0 of the arduino
 const int DOUTpin=8;//the DOUT pin of the CO sensor goes into digital pin D8 of the arduino
 const int ledPin=13;//the anode of the LED connects to digital pin D13 of the arduino

 int limit;
 int value;

 void setup() {
 Serial.begin(115200);//sets the baud rate
 pinMode(DOUTpin, INPUT);//sets the pin as an input to the arduino
 pinMode(ledPin, OUTPUT);//sets the pin as an output of the arduino
 }

 void loop()
 {
 value= analogRead(AOUTpin);//reads the analaog value from the CO sensor's AOUT pin
 limit= digitalRead(DOUTpin);//reads the digital value from the CO sensor's DOUT pin
 Serial.print("CO value: ");
 Serial.println(value);//prints the CO value
 Serial.print("Limit: ");
 Serial.print(limit);//prints the limit reached as either LOW or HIGH (above or underneath)
 delay(100);
 if (limit == HIGH){
 digitalWrite(ledPin, HIGH);//if limit has been reached, LED turns on as status indicator
 }
 else{
 digitalWrite(ledPin, LOW);//if threshold not reached, LED remains off
 }
 }

```

I am yet to buy a relay circuit to be able to connect it with the circuit using a , but for now I would appreciate it the scenarios highlighted for the sensors could be addressed and also, how the two codes could be combined to be one single code. If there is any question, feel free to ask. The project is for silo monitoring and control.

# Answer
Only thing that gives people problems when combining two simple sketches are "delay" commands. There is just one "delay" so it's perfect.

1. Create new sketch
2. Paste everything that's not in a method from the two sketches.
3. Combine `setup` methods together by pasting first one and second one below.
4. Remove duplicated commands like `Serial.begin(115200);` from the method
5. Combine `loop` methods together by pasting first one and second one below.
6. Move code in `loop` to make the code visually pleasing (it's called the "smell" of code)

This should not be a big problem with those two particular sketches. Please ask more precise questions as soon as you will have problems.
> 2 votes

---
Tags: arduino-mega, led, code-review
---


# Question
Title: Help with parts identification from arduino starter kit from aliexpress
Ordered an arduino starter kit from aliexpress Link

The parts list they provide (as a jpg on the order page) is vague and not very descriptive, I've gone through most of the parts and am down to three they did not list.

1. Capacitor? -- Looks to be a capacitor, labeled HDX and nothing else, rattles when I shake it.
2. Black LED -- I think this is a flame sensor; if it is, what's the difference between this and an infrared receiver (like a 1838B) or photoresistor?
3. They also list something as 'a digital control' near the bottom of the list, not sure what that is? Every other part from the list is matched up and I don't see anything different in the first picture (not parts list picture) from what I have received in the order.

# Answer
1. Those are tilt sensors. The rattling is a metal ball that contacts two pins inside, closing the connection.
2. The 1838B is a full module that partially decodes the received IR so that a MCU can fully decode the rest easily. What you have there is a bare phototransistor with an IR window on the top. You would use it for proximity or presence sensing. Instead of varying its resistance, it varies the amount of current it will pass.
3. Probably the single-digit 7-segment display, as opposed to the 4-digit display they have listed as "4 digital tube".
> 8 votes

# Answer
I recently purchased the arduinotech module learning Kit and contains both components shown above. It does mention an Infrared Photo Diode which it think is your "Black LED".

Thanks for the heads up on the HDX switches. Now I know what they are.:)
> 1 votes

# Answer
The HDX is a "Tilt Switch" Turns on/off depending on the angle.
> 0 votes

---
Tags: hardware, components
---


# Question
Title: Reading inside critical sections from ISR
Is it necessary to protect reads of volatile variables in critical sections when using interrupts? Or are critical sections only required when concurrently writing variables?

Here is an example of a variable written within an ISR which is protected with a critical section:

```
void loop() {
    portENTER_CRITICAL(&mux);
    uint other = variable_written_from_isr + 1;
    portEXIT_CRITICAL(&mux);
}

```

What will happen if an interrupt changes `variable_written_from_isr` while it is being read? Would anything worse that inconsistencies happen?

Here is an opposite example where a variable is written from an interrupt and read from the loop (or a task):

```
void IRAM_ATTR handleInterrupt() {
    portENTER_CRITICAL_ISR(&mux);
    uint other = variable_written_from_loop + 1;
    portEXIT_CRITICAL_ISR(&mux);
}

```

Please note that I aware of *stdatomic*. I am mainly interested in understanding the behavior of concurrent access in the context of interrupts.

# Answer
> 0 votes
You should use critical sections around any operations that could potentially be affected by the execution of an ISR (or which could affect an ISR) *that aren't atomic*.

Simply put, an atomic instruction is one which can be represented by a single assembly language instruction. You can't interrupt during the execution of an assembly instruction, so anything that only takes one instruction can't be interrupted until it's complete.

Examples would be moving a value from one 8-bit variable (assuming an 8-bit architecture) into a register, storing an 8-bit value into memory, etc.

What instructions are likely to be atomic very much depends on the architecture that you are working on. The only real way to be sure is to compile the code into assembly language and examine what is produced. Of course, that means learning the assembly language of your chosen architecture.

However: if in doubt, use a critical section. Better to be safe than sorry. But keep those critical sections as short as possible to not disturb the interrupts more than is needed.

For example, instead of starting a critical section, reading some volatile value, doing some calculations with it, and writing it elsewhere, you should use the critical section just to read the volatile value into a temporary variable. After the critical section, you can then do your calculations and things with it, while the interrupt is then free to be called again.

# Answer
> 0 votes
A non-atomic read in your main code of a 2-or-more-byte variable that can be written in an interrupt routine *does* need to be protected. In this case, the variable itself can't be corrupted, but the value read from it by your main code might be - in the case where the main code is reading the shared variable one byte at a time, and gets interrupted between two of those byte-reads.

---
Tags: interrupt, esp32
---