message:
How do interrupts work on the Arduino Uno and similar boards?

Please explain how interrupts work on the Arduino Uno and related boards using the ATmega328P processor. Boards such as the:

* Uno
* Mini
* Nano
* Pro Mini
* Lilypad

In particular please discuss:

* What to use interrupts for
* How to write an Interrupt Service Routine (ISR)
* Timing issues
* Critical sections
* Atomic access to data

---

*Note: this is a reference question*.

body:
# TL;DR :

When writing an Interrupt Service Routine (ISR):

* Keep it *short*
* Don't use `delay ()`
* Don't do serial prints
* Make variables shared with the main code **volatile**
* Variables shared with main code may need to be protected by "critical sections" (see below)
* Don't try to turn interrupts off or on

---

# What are interrupts?

Most processors have interrupts. Interrupts let you respond to "external" events while doing something else. For example, if you are cooking dinner you may put the potatoes on to cook for 20 minutes. Rather than staring at the clock for 20 minutes you might set a timer, and then go watch TV. When the timer rings you "interrupt" your TV viewing to do something with the potatoes.

---

# Example of interrupts

    const byte LED = 13;
    const byte SWITCH = 2;

    // Interrupt Service Routine (ISR)
    void switchPressed ()
    {
      if (digitalRead (SWITCH) == HIGH)
        digitalWrite (LED, HIGH);
      else
        digitalWrite (LED, LOW);
    }  // end of switchPressed

    void setup ()
    {
      pinMode (LED, OUTPUT);  // so we can update the LED
      pinMode (SWITCH, INPUT_PULLUP);
      attachInterrupt (digitalPinToInterrupt (SWITCH), switchPressed, CHANGE);  // attach interrupt handler
    }  // end of setup

    void loop ()
    {
      // loop doing nothing
    }

This example shows how, even though the main loop is doing nothing, you can turn the LED on pin 13 on or off, if the switch on pin D2 is pressed.

To test this, just connect a wire (or switch) between D2 and Ground. The internal pullup (enabled in setup) forces the pin HIGH normally. When grounded, it becomes LOW. The change in the pin is detected by a CHANGE interrupt, which causes the Interrupt Service Routine (ISR) to be called.

In a more complicated example, the main loop might be doing something useful, like taking temperature readings, and allow the interrupt handler to detect a button being pushed.

---

# Converting pin numbers to interrupt numbers

To simplify converting interrupt vector numbers to pin numbers you can call the function `digitalPinToInterrupt()`, passing a pin number. It returns the appropriate interrupt number, or `NOT_AN_INTERRUPT` (-1).

For example, on the Uno, pin D2 on the board is interrupt 0 (INT0_vect from the table below).

Thus these two lines have the same effect:

      attachInterrupt (0, switchPressed, CHANGE);    // that is, for pin D2
      attachInterrupt (digitalPinToInterrupt (2), switchPressed, CHANGE);

However the second one is easier to read and more portable to different Arduino types.

---

# Available interrupts

Below is a list of interrupts, in priority order, for the Atmega328:

     1  Reset
     2  External Interrupt Request 0  (pin D2)          (INT0_vect)
     3  External Interrupt Request 1  (pin D3)          (INT1_vect)
     4  Pin Change Interrupt Request 0 (pins D8 to D13) (PCINT0_vect)
     5  Pin Change Interrupt Request 1 (pins A0 to A5)  (PCINT1_vect)
     6  Pin Change Interrupt Request 2 (pins D0 to D7)  (PCINT2_vect)
     7  Watchdog Time-out Interrupt                     (WDT_vect)
     8  Timer/Counter2 Compare Match A                  (TIMER2_COMPA_vect)
     9  Timer/Counter2 Compare Match B                  (TIMER2_COMPB_vect)
    10  Timer/Counter2 Overflow                         (TIMER2_OVF_vect)
    11  Timer/Counter1 Capture Event                    (TIMER1_CAPT_vect)
    12  Timer/Counter1 Compare Match A                  (TIMER1_COMPA_vect)
    13  Timer/Counter1 Compare Match B                  (TIMER1_COMPB_vect)
    14  Timer/Counter1 Overflow                         (TIMER1_OVF_vect)
    15  Timer/Counter0 Compare Match A                  (TIMER0_COMPA_vect)
    16  Timer/Counter0 Compare Match B                  (TIMER0_COMPB_vect)
    17  Timer/Counter0 Overflow                         (TIMER0_OVF_vect)
    18  SPI Serial Transfer Complete                    (SPI_STC_vect)
    19  USART Rx Complete                               (USART_RX_vect)
    20  USART, Data Register Empty                      (USART_UDRE_vect)
    21  USART, Tx Complete                              (USART_TX_vect)
    22  ADC Conversion Complete                         (ADC_vect)
    23  EEPROM Ready                                    (EE_READY_vect)
    24  Analog Comparator                               (ANALOG_COMP_vect)
    25  2-wire Serial Interface  (I2C)                  (TWI_vect)
    26  Store Program Memory Ready                      (SPM_READY_vect)

Internal names (which you can use to set up ISR callbacks) are in brackets.

*Warning: If you misspell the interrupt vector name, even by just getting the capitalization wrong (an easy thing to do) the interrupt routine **will not be called**, and you will not get a compiler error.*

---

# Reasons to use interrupts

The main reasons you might use interrupts are:

* To detect pin changes (eg. rotary encoders, button presses)
* Watchdog timer (eg. if nothing happens after 8 seconds, interrupt me)
* Timer interrupts - used for comparing/overflowing timers
* SPI data transfers
* I2C data transfers
* USART data transfers
* ADC conversions (analog to digital)
* EEPROM ready for use
* Flash memory ready

The "data transfers" can be used to let a program do something else while data is being sent or received on the serial port, SPI port, or I2C port.

## Wake the processor

External interrupts, pin-change interrupts, and the watchdog timer interrupt, can also be used to wake the processor up. This can be very handy, as in sleep mode the processor can be configured to use a lot less power (eg. around 10 microamps). A rising, falling, or low-level interrupt can be used to wake up a gadget (eg. if you press a button on it), or a "watchdog timer" interrupt might wake it up periodically (eg. to check the time or temperature).

Pin-change interrupts could be used to wake the processor if a key is pressed on a keypad, or similar.

The processor can also be awoken by a timer interrupt (eg. a timer reaching a certain value, or overflowing) and certain other events, such as an incoming I2C message.

---

# Enabling / disabling interrupts

The "reset" interrupt cannot be disabled. However the other interrupts can be temporarily disabled by clearing the global interrupt flag.

## Enable interrupts

You can enable interrupts with the function call "interrupts" or "sei" like this:

    interrupts ();  // or ...
    sei ();         // set interrupts flag

## Disable interrupts

If you need to disable interrupts you can "clear" the global interrupt flag like this:

    noInterrupts ();  // or ...
    cli ();           // clear interrupts flag

Either method has the same effect, using `interrupts` / `noInterrupts` is a bit easier to remember which way around they are.

The default in the Arduino is for interrupts to be enabled. Don't disable them for long periods or things like timers won't work properly.

## Why disable interrupts?

There may be time-critical pieces of code that you don't want interrupted, for example by a timer interrupt.

Also if multi-byte fields are being updated by an ISR then you may need to disable interrupts so that you get the data "atomically". Otherwise one byte may be updated by the ISR while you are reading the other one.

For example:

    noInterrupts ();
    long myCounter = isrCounter;  // get value set by ISR
    interrupts ();

Temporarily turning off interrupts ensures that isrCounter (a counter set inside an ISR) does not change while we are obtaining its value.

**Warning:** if you are not sure if interrupts are already on or not, then you need to save the current state and restore it afterwards. For example, the code from the millis() function does this:

    unsigned long millis()
    {
      unsigned long m;
      uint8_t oldSREG = SREG;    // <--------- save status register

      // disable interrupts while we read timer0_millis or we might get an
      // inconsistent value (e.g. in the middle of a write to timer0_millis)
      cli();
      m = timer0_millis;
      SREG = oldSREG;            // <---------- restore status register including interrupt flag

      return m;
    }

Note the indicated lines save the current SREG (status register) which includes the interrupt flag. After we have obtained the timer value (which is 4 bytes long) we put the status register back how it was.

---

# Tips

## Function names

The functions `cli` / `sei` and the register SREG are specific to the AVR processors. If you are using other processors such as the ARM ones the functions may be slightly different.

## Disabling globally vs disabling one interrupt

If you use `cli()` you disable **all** interrupts (including timer interrupts, serial interrupts, etc.).

However if you just want to disable a **particular** interrupt then you should clear the interrupt-enable flag for that particular interrupt source. For example, for external interrupts, call `detachInterrupt()`.

---

# What is interrupt priority?

Since there are 25 interrupts (other than reset) it is possible that more than one interrupt event might occur at once, or at least, occur before the previous one is processed. Also an interrupt event might occur while interrupts are disabled.

The priority order is the sequence in which the processor checks for interrupt events. The higher up the list, the higher the priority. So, for example, an External Interrupt Request 0 (pin D2) would be serviced before External Interrupt Request 1 (pin D3).

---

# Can interrupts occur while interrupts are disabled?

Interrupts **events** (that is, noticing the event) can occur at any time, and most are remembered by setting an "interrupt event" flag inside the processor. If interrupts are disabled, then that interrupt will be handled when they are enabled again, in priority order.

---

# How do you use interrupts?

* You write an ISR (interrupt service routine). This is called when the interrupt occurs.
* You tell the processor when you want the interrupt to fire.

## Writing an ISR

Interrupt Service Routines are functions with no arguments. Some Arduino libraries are designed to call your own functions, so you just supply an ordinary function (as in the examples above), eg.

    // Interrupt Service Routine (ISR)
    void switchPressed ()
    {
     flag = true;
    }  // end of switchPressed

However if a library has not already provided a "hook" to an ISR you can make your own, like this:

    volatile char buf [100];
    volatile byte pos;

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

      // add to buffer if room
      if (pos < sizeof buf)
        {
        buf [pos++] = c;
        }  // end of room available
    }  // end of interrupt routine SPI_STC_vect

In this case you use the "ISR" macro, and supply the name of the relevant interrupt vector (from the table earlier on). In this case the ISR is handling an SPI transfer completing. (Note, some old code uses SIGNAL instead of ISR, however SIGNAL is deprecated).

## Connecting an ISR to an interrupt

For interrupts already handled by libraries, you just use the documented interface. For example:

    void receiveEvent (int howMany)
     {
      while (Wire.available () > 0)
        {
        char c = Wire.receive ();
        // do something with the incoming byte
        }
    }  // end of receiveEvent

    void setup ()
      {
      Wire.onReceive(receiveEvent);
      }

In this case the I2C library is designed to handle incoming I2C bytes internally, and then call your supplied function at the end of the incoming data stream. In this case receiveEvent is not strictly an ISR (it has an argument) but it is called by an inbuilt ISR.

Another example is the "external pin" interrupt.

    // Interrupt Service Routine (ISR)
    void switchPressed ()
    {
      // handle pin change here
    }  // end of switchPressed

    void setup ()
    {
      attachInterrupt (digitalPinToInterrupt (2), switchPressed, CHANGE);  // attach interrupt handler for D2
    }  // end of setup

In this case the attachInterrupt function adds the function switchPressed to an internal table, and in addition configures the appropriate interrupt flags in the processor.

## Configuring the processor to handle an interrupt

The next step, once you have an ISR, is to tell the processor that you want this particular condition to raise an interrupt.

As an example, for External Interrupt 0 (the D2 interrupt) you could do something like this:

    EICRA &= ~3;  // clear existing flags
    EICRA |= 2;   // set wanted flags (falling level interrupt)
    EIMSK |= 1;   // enable it

More readable would be to use the defined names, like this:

    EICRA &= ~(bit(ISC00) | bit (ISC01));  // clear existing flags
    EICRA |= bit (ISC01);    // set wanted flags (falling level interrupt)
    EIMSK |= bit (INT0);     // enable it

EICRA (External Interrupt Control Register A) would be set according to this table from the Atmega328 datasheet.
That defines the exact type of interrupt you want:

* 0: The low level of INT0 generates an interrupt request (LOW interrupt).
* 1: Any logical change on INT0 generates an interrupt request (CHANGE interrupt).
* 2: The falling edge of INT0 generates an interrupt request (FALLING interrupt).
* 3: The rising edge of INT0 generates an interrupt request (RISING interrupt).

EIMSK (External Interrupt Mask Register) actually enables the interrupt.

Fortunately you don't need to remember those numbers because attachInterrupt does that for you. However that is what is actually happening, and for other interrupts you may have to "manually" set interrupt flags.

---

# Low-level ISRs vs. library ISRs

To simplify your life some common interrupt handlers are actually inside library code (for example INT0_vect and INT1_vect) and then a more user-friendly interface is provided (eg. attachInterrupt). What attachInterrupt actually does is save the address of your wanted interrupt handler into a variable, and then call that from INT0_vect / INT1_vect when needed. It also sets the appropriate register flags to call the handler when required.

---

# Can ISRs be interrupted?

In short, no, not unless you want them to be.

When an ISR is entered, **interrupts are disabled**. Naturally they must have been enabled in the first place, otherwise the ISR would not be entered. However to avoid having an ISR itself be interrupted, the processor turns interrupts off.

When an ISR exits, then **interrupts are enabled again**. The compiler also generates code inside an ISR to save registers and status flags, so that whatever you were doing when the interrupt occurred will not be affected.

However you **can** turn interrupts on inside an ISR if you absolutely must, eg.

    // Interrupt Service Routine (ISR)
    void switchPressed ()
    {
      // handle pin change here
      interrupts ();  // allow more interrupts

    }  // end of switchPressed

Normally you would need a pretty good reason to do this, as another interrupt now could result in a recursive call to pinChange, with quite possibly undesirable results.

---

# How long does it take to execute an ISR?

According to the datasheet, the minimal amount of time to service an interrupt is 4 clock cycles (to push the current program counter onto the stack) followed by the code now executing at the interrupt vector location. This normally contains a jump to where the interrupt routine really is, which is another 3 cycles. Examination of the code produced by the compiler shows that an ISR made with the "ISR" declaration can take around 2.625 µs to execute, plus whatever the code itself does. The exact amount depends on how many registers need to be saved and restored. The minimum amount would be 1.1875 µs.

The external interrupts (where you use attachInterrupt) do a bit more and take around 5.125 µs in total (running with a 16 MHz clock).

---

# How long before the processor starts entering an ISR?

This varies somewhat. The figures quoted above are the ideal ones where the interrupt is immediately processed. A few factors may delay that:

* If the processor is asleep, there are designated "wake-up" times, which could be quite a few milliseconds, while the clock is spooled back up to speed. This time would depend on fuse settings, and how deep the sleep is.

* If an interrupt service routine is already executing, then further interrupts cannot be entered until it either finishes, or enables interrupts itself. This is why you should keep each interrupt service routine short, as every microsecond you spend in one, you are potentially delaying the execution of another one.

* Some code turns interrupts off. For example, calling millis() briefly turns interrupts off. Therefore the time for an interrupt to be serviced would be extended by the length of time interrupts were turned off.

* Interrupts can only be serviced at the end of an instruction, so if a particular instruction takes three clock cycles, and has just started, then the interrupt will be delayed at least a couple of clock cycles.

* An event that turns interrupts back on (eg. returning from an interrupt service routine) is guaranteed to execute at least one more instruction. So even if an ISR ends, and your interrupt is pending, it still has to wait for one more instruction before it is serviced.

* Since interrupts have a priority, a higher-priority interrupt might be serviced before the interrupt you are interested in.

---

# Performance considerations

Interrupts can increase performance in many situations because you can get on with the "main work" of your program without having to constantly be testing to see if switches have been pressed. Having said that, the overhead of servicing an interrupt, as discussed above, would actually be more than doing a "tight loop" polling a single input port. You can barely respond to an event within, say, a microsecond. In that case you might disable interrupts (eg. timers) and just loop looking for the pin to change.

---

# How are interrupts queued?

There are two sorts of interrupts:

* Some set a flag and they are handled in priority order, even if the event that caused them has stopped. For example, a rising, falling, or changing level interrupt on pin D2.

* Others are only tested if they are happening "right now". For example, a low-level interrupt on pin D2.

The ones that set a flag could be regarded as being queued, as the interrupt flag remains set until such time as the interrupt routine is entered, at which time the processor clears the flag. Of course, since there is only one flag, if the same interrupt condition occurs again before the first one is processed, it won't be serviced twice.

Something to be aware of is that these flags can be set before you attach the interrupt handler. For example, it is possible for a rising or falling level interrupt on pin D2 to be "flagged", and then as soon as you do an attachInterrupt the interrupt immediately fires, even if the event occurred an hour ago. To avoid this you can manually clear the flag. For example:

    EIFR = bit (INTF0);  // clear flag for interrupt 0
    EIFR = bit (INTF1);  // clear flag for interrupt 1

However the "low level" interrupts are continuously checked, so if you are not careful they will keep firing, even after the interrupt has been called. That is, the ISR will exit, and then the interrupt will immediately fire again. To avoid this, you should do a detachInterrupt immediately after you know that the interrupt fired.

---

# Hints for writing ISRs

In brief, keep them short! While an ISR is executing other interrupts cannot be processed. So you could easily miss button presses, or incoming serial communications, if you try to do too much. In particular, you should not try to do debugging "prints" inside an ISR. The time taken to do those is likely to cause more problems than they solve.

A reasonable thing to do is set a single-byte flag, and then test that flag in the main loop function. Or, store an incoming byte from a serial port into a buffer. The inbuilt timer interrupts keep track of elapsed time by firing every time the internal timer overflows, and thus you can work out elapsed time by knowing how many times the timer overflowed.

Remember, inside an ISR interrupts are disabled. Thus hoping that the time returned by millis() function calls will change, will lead to disappointment. It is valid to **obtain** the time that way, just be aware that the timer is not incrementing. And if you spend too long in the ISR then the timer may miss an overflow event, leading to the time returned by millis() becoming incorrect.

A test shows that, on a 16 MHz Atmega328 processor, a call to micros() takes 3.5625 µs. A call to millis() takes 1.9375 µs. Recording (saving) the current timer value is a reasonable thing to do in an ISR. Finding the elapsed milliseconds is faster than the elapsed microseconds (the millisecond count is just retrieved from a variable). However the microsecond count is obtained by adding the current value of the Timer 0 timer (which will keep incrementing) to a saved "Timer 0 overflow count".

**Warning:** Since interrupts are disabled inside an ISR, and since the latest version of the Arduino IDE uses interrupts for Serial reading and writing, and also for incrementing the counter used by "millis" and "delay" you should not attempt to use those functions inside an ISR. To put it another way:

* Don't attempt to delay, eg: `delay (100);`
* You can get the time from a call to millis, however it won't increment, so don't attempt to delay by waiting for it to increase.
* Don't do serial prints (eg. `Serial.println ("ISR entered");` )
* Don't try to do serial reading.

---

# Pin change interrupts

There are two ways you can detect external events on pins. The first is the special "external interrupt" pins, D2 and D3. These general discrete interrupt events, one per pin. You can get to those by using attachInterrupt for each pin. You can specify a rising, falling, changing or low-level condition for the interrupt.

However there are also "pin change" interrupts for all pins (on the Atmega328, not necessarily all pins on other processors). These act on groups of pins (D0 to D7, D8 to D13, and A0 to A5). They are also lower priority than the external event interrupts. However they are a bit more fiddly to use than the external interrupts because they are grouped into batches. So if the interrupt fires you have to work out in your own code exactly which pin caused the interrupt.

Example code:

    ISR (PCINT0_vect)
     {
     // handle pin change interrupt for D8 to D13 here
     }  // end of PCINT0_vect

    ISR (PCINT1_vect)
     {
     // handle pin change interrupt for A0 to A5 here
     }  // end of PCINT1_vect

    ISR (PCINT2_vect)
     {
     // handle pin change interrupt for D0 to D7 here
     }  // end of PCINT2_vect

    void setup ()
      {
      // pin change interrupt (example for D9)
      PCMSK0 |= bit (PCINT1);  // want pin 9
      PCIFR  |= bit (PCIF0);   // clear any outstanding interrupts
      PCICR  |= bit (PCIE0);   // enable pin change interrupts for D8 to D13
      }

To handle a pin change interrupt you need to:

* Specify which pin in the group. This is the PCMSKn variable (where n is 0, 1 or 2 from the table below). You can have interrupts on more than one pin.
* Enable the appropriate group of interrupts (0, 1 or 2)
* Supply an interrupt handler as shown above

## Table of pins -> pin change names / masks

    D0   PCINT16 (PCMSK2 / PCIF2 / PCIE2)
    D1   PCINT17 (PCMSK2 / PCIF2 / PCIE2)
    D2   PCINT18 (PCMSK2 / PCIF2 / PCIE2)
    D3   PCINT19 (PCMSK2 / PCIF2 / PCIE2)
    D4   PCINT20 (PCMSK2 / PCIF2 / PCIE2)
    D5   PCINT21 (PCMSK2 / PCIF2 / PCIE2)
    D6   PCINT22 (PCMSK2 / PCIF2 / PCIE2)
    D7   PCINT23 (PCMSK2 / PCIF2 / PCIE2)
    D8   PCINT0  (PCMSK0 / PCIF0 / PCIE0)
    D9   PCINT1  (PCMSK0 / PCIF0 / PCIE0)
    D10   PCINT2  (PCMSK0 / PCIF0 / PCIE0)
    D11   PCINT3  (PCMSK0 / PCIF0 / PCIE0)
    D12   PCINT4  (PCMSK0 / PCIF0 / PCIE0)
    D13   PCINT5  (PCMSK0 / PCIF0 / PCIE0)
    A0   PCINT8  (PCMSK1 / PCIF1 / PCIE1)
    A1   PCINT9  (PCMSK1 / PCIF1 / PCIE1)
    A2   PCINT10 (PCMSK1 / PCIF1 / PCIE1)
    A3   PCINT11 (PCMSK1 / PCIF1 / PCIE1)
    A4   PCINT12 (PCMSK1 / PCIF1 / PCIE1)
    A5   PCINT13 (PCMSK1 / PCIF1 / PCIE1)

## Interrupt handler processing

The interrupt handler would need to work out which pin caused the interrupt if the mask specifies more than one (eg. if you wanted interrupts on D8/D9/D10). To do this you would need to store the previous state of that pin, and work out (by doing a digitalRead or similar) if this particular pin had changed.

---

# You are probably using interrupts anyway ...

A "normal" Arduino environment already is using interrupts, even if you don't personally attempt to. The millis() and micros() function calls make use of the "timer overflow" feature. One of the internal timers (timer 0) is set up to interrupt roughly 1000 times a second, and increment an internal counter which effectively becomes the millis() counter. There is a bit more to it than that, as adjustment is made for the exact clock speed.

Also the hardware serial library uses interrupts to handle incoming and outgoing serial data. This is very useful as your program can be doing other things while the interrupts are firing, and filling up an internal buffer. Then when you check Serial.available() you can find out what, if anything, has been placed in that buffer.

---

# Executing the next instruction after enabling interrupts

After a bit of discussion and research on the Arduino forum, we have clarified exactly what happens after you enable interrupts. There are three main ways I can think of that you can enable interrupts, which were previously not enabled:

      sei ();  // set interrupt enable flag
      SREG |= 0x80;  // set the high-order bit in the status register
      reti  ;   // assembler instruction "return from interrupt"

In all cases, the processor guarantees that the **next** instruction after interrupts are enabled (if they were previously disabled) will always be executed, even if an interrupt event is pending. (By "next" I mean the next one in program sequence, not necessarily the one physically following. For example, a RETI instruction jumps back to where the interrupt occurred, and then executes one more instruction).

This lets you write code like this:

    sei ();
    sleep_cpu ();

If not for this guarantee, the interrupt might occur **before** the processor slept, and then it might never be awoken.

---

# Empty interrupts

If you merely want an interrupt to wake the processor, but not do anything in particular, you can use the EMPTY_INTERRUPT define, eg.

    EMPTY_INTERRUPT (PCINT1_vect);

This simply generates a "reti" (return from interrupt) instruction. Since it doesn't try to save or restore registers this would be the fastest way to get an interrupt to wake it up.

---

# Critical sections (atomic variable access)

There are some subtle issues regarding variables which are shared between interrupt service routines (ISRs) and the main code (that is, the code not in an ISR).

Since an ISR can fire at any time when interrupts are enabled, you need to be cautious about accessing such shared variables, as they may be being updated at the very moment you access them.

## First ... when do you use "volatile" variables?

A variable should only be marked volatile if it is used both inside an ISR, and outside one.

* Variables **only** used outside an ISR should **not** be volatile.
* Variables **only** used inside an ISR should **not** be volatile.
* Variables used both inside and outside an ISR **should** be volatile.

eg.

    volatile int counter;

Marking a variable as volatile tells the compiler to not "cache" the variables contents into a processor register, but always read it from memory, when needed. This may slow down processing, which is why you don't just make every variable volatile, when not needed.

## Turn interrupts off while accessing a volatile variable

For example, to compare `count` to some number, turn interrupts off during the compare in case one byte of `count` has been updated by the ISR and not the other byte.

    volatile unsigned int count;

    ISR (TIMER1_OVF_vect)
      {
      count++;
      } // end of TIMER1_OVF_vect

    void setup ()
      {
      pinMode (13, OUTPUT);
      }  // end of setup

    void loop ()
      {
      noInterrupts ();    // <------ critical section
      if (count > 20)
         digitalWrite (13, HIGH);
      interrupts ();      // <------ end critical section
      } // end of loop

---

# Read the data sheet!

More information about interrupts, timers, etc. can be obtained from the data sheet for the processor.

   <http://www.atmel.com/images/Atmel-8271-8-bit-AVR-Microcontroller-ATmega48A-48PA-88A-88PA-168A-168PA-328-328P_datasheet_Complete.pdf>

---

# Further examples

Space considerations (post size limit) prevent my listing more example code. For more example code see [my page about interrupts](http://www.gammon.com.au/interrupts).


sender: user

message:
Problems reading I2C sensor when using a Xbee module

I'm developing a project where I can control a RC boat with GPS and a magnetometer. How ever, I was developing everything connected to my computer and worked pretty well. When I was going to make some test with a battery and a couple of Xbee's (PC and "Arduino"), the magnetometer signal was not updating. So, I read the first value and continued to transmit the same value (thing that never happened on computer). Has someone had the same issue before? How can I solve this? Oh, one thing. The GPS and magnetometer comes in the same module, and I'm having no problems with GPS coordinates. And even if I power de MCU with my computer and transmitting with the Xbee's it doesn't work either. Seems like a communication problem.

Hardware used:

[GPS Module + Compass][1]

[ATmega1284P][2]

**UPDATE:**

I want to share also the code I'm using for the I2C reading.

    #include <Wire.h> //I2C Arduino Library
    #define address 0x1E //0011110b, I2C 7bit address of HMC5883

    void setup(){
      //Initialize Serial and I2C communications
      Serial.begin(9600);
      Wire.begin();

      //Put the HMC5883 IC into the correct operating mode
      Wire.beginTransmission(address); //open communication with HMC5883
      Wire.send(0x02); //select mode register
      Wire.send(0x00); //continuous measurement mode
      Wire.endTransmission();
    }

     void loop(){

      int x,y,z; //triple axis data

      //Tell the HMC5883L where to begin reading data
      Wire.beginTransmission(address);
      Wire.send(0x03); //select register 3, X MSB register
      Wire.endTransmission();

     //Read data from each axis, 2 registers per axis
      Wire.requestFrom(address, 6);
      if(6<=Wire.available()){
        x = Wire.receive()<<8; //X msb
        x |= Wire.receive(); //X lsb
        z = Wire.receive()<<8; //Z msb
        z |= Wire.receive(); //Z lsb
        y = Wire.receive()<<8; //Y msb
        y |= Wire.receive(); //Y lsb
      }

      //Print out values of each axis
      Serial.print("x: ");
      Serial.print(x);
      Serial.print("  y: ");
      Serial.print(y);
      Serial.print("  z: ");
      Serial.println(z);

    }

  [1]: https://www.amazon.com/Readytosky-NEO-7M-Compass-Folding-Antenna/dp/B01D79ZSPM/ref=sr_1_1?ie=UTF8&qid=1478575123&sr=8-1&keywords=neo 7m gps
  [2]: https://www.amazon.com/ATMEL-ATMEGA1284P-PU-ATMEGA-20MHZ-DIP-40/dp/B00AS6D95O/ref=sr_1_1?ie=UTF8&qid=1478575344&sr=8-1&keywords=atmega1284p

sender: assistant

body:
There are 2 possible problems:

Lack of power or libraries not supporting each other.

1 - Try powering the circuit with some USB 5V. Make sure that your other modules can support 5V. Also check your clock speed. High clock speeds with low voltages might cause your ATmega to function incorrectly.

2 - Some libraries for certain module / breakout uses software I2C which pretty much emulate I2C. They might not be compatible with another module that needs the `wire` library to function proprely. To debug it, test out 1 module at the time with the battery.


body:
I have solved the problem by adding a delay just before I select the continuous measurement mode.

    void setup(){
      //Initialize Serial and I2C communications
      Serial.begin(9600);
      Wire.begin();

      //Put the HMC5883 IC into the correct operating mode
      Wire.beginTransmission(address); //open communication with HMC5883
      Wire.send(0x02); //select mode register
      Wire.send(0x00); //continuous measurement mode
      delay(100);
      Wire.endTransmission();
    }


message:
how to communicate MPU-6050 ( on arduino micro) wirelessly using nrf24l01 to arduino uno?

I have an Arduino Micro and MPU-6050. I'm trying to transfer the data obtained from the MPU-6050 wirelessly to my computer using an Arduino Uno at the other end. I'm not sure how to make this happen.

    // I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class using DMP (MotionApps v2.0)
    // 6/21/2012 by Jeff Rowberg <jeff@rowberg.net>
    // Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
    //
    // Changelog:
    //      2013-05-08 - added seamless Fastwire support
    //                 - added note about gyro calibration
    //      2012-06-21 - added note about Arduino 1.0.1 + Leonardo compatibility error
    //      2012-06-20 - improved FIFO overflow handling and simplified read process
    //      2012-06-19 - completely rearranged DMP initialization code and simplification
    //      2012-06-13 - pull gyro and accel data from FIFO packet instead of reading directly
    //      2012-06-09 - fix broken FIFO read sequence and change interrupt detection to RISING
    //      2012-06-05 - add gravity-compensated initial reference frame acceleration output
    //                 - add 3D math helper file to DMP6 example sketch
    //                 - add Euler output and Yaw/Pitch/Roll output formats
    //      2012-06-04 - remove accel offset clearing for better results (thanks Sungon Lee)
    //      2012-06-01 - fixed gyro sensitivity to be 2000 deg/sec instead of 250
    //      2012-05-30 - basic DMP initialization working

    /* ============================================
    I2Cdev device library code is placed under the MIT license
    Copyright (c) 2012 Jeff Rowberg

    Permission is hereby granted, free of charge, to any person obtaining a copy
    of this software and associated documentation files (the "Software"), to deal
    in the Software without restriction, including without limitation the rights
    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the Software is
    furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in
    all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    THE SOFTWARE.
    ===============================================
    */

    // I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files
    // for both classes must be in the include path of your project
    #include "I2Cdev.h"

    #include "MPU6050_6Axis_MotionApps20.h"
    //#include "MPU6050.h" // not necessary if using MotionApps include file

    // Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation
    // is used in I2Cdev.h
    #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
        #include "Wire.h"
    #endif

    // class default I2C address is 0x68
    // specific I2C addresses may be passed as a parameter here
    // AD0 low = 0x68 (default for SparkFun breakout and InvenSense evaluation board)
    // AD0 high = 0x69
    MPU6050 mpu;
    //MPU6050 mpu(0x69); // <-- use for AD0 high

    /* =========================================================================
       NOTE: In addition to connection 3.3v, GND, SDA, and SCL, this sketch
       depends on the MPU-6050's INT pin being connected to the Arduino's
       external interrupt #0 pin. On the Arduino Uno and Mega 2560, this is
       digital I/O pin 2.
     * ========================================================================= */

    /* =========================================================================
       NOTE: Arduino v1.0.1 with the Leonardo board generates a compile error
       when using Serial.write(buf, len). The Teapot output uses this method.
       The solution requires a modification to the Arduino USBAPI.h file, which
       is fortunately simple, but annoying. This will be fixed in the next IDE
       release. For more info, see these links:

       http://arduino.cc/forum/index.php/topic,109987.0.html
       http://code.google.com/p/arduino/issues/detail?id=958
     * ========================================================================= */

    // uncomment "OUTPUT_READABLE_QUATERNION" if you want to see the actual
    // quaternion components in a [w, x, y, z] format (not best for parsing
    // on a remote host such as Processing or something though)
    //#define OUTPUT_READABLE_QUATERNION

    // uncomment "OUTPUT_READABLE_EULER" if you want to see Euler angles
    // (in degrees) calculated from the quaternions coming from the FIFO.
    // Note that Euler angles suffer from gimbal lock (for more info, see
    // http://en.wikipedia.org/wiki/Gimbal_lock)
    //#define OUTPUT_READABLE_EULER

    // uncomment "OUTPUT_READABLE_YAWPITCHROLL" if you want to see the yaw/
    // pitch/roll angles (in degrees) calculated from the quaternions coming
    // from the FIFO. Note this also requires gravity vector calculations.
    // Also note that yaw/pitch/roll angles suffer from gimbal lock (for
    // more info, see: http://en.wikipedia.org/wiki/Gimbal_lock)
    #define OUTPUT_READABLE_YAWPITCHROLL

    // uncomment "OUTPUT_READABLE_REALACCEL" if you want to see acceleration
    // components with gravity removed. This acceleration reference frame is
    // not compensated for orientation, so +X is always +X according to the
    // sensor, just without the effects of gravity. If you want acceleration
    // compensated for orientation, us OUTPUT_READABLE_WORLDACCEL instead.
    //#define OUTPUT_READABLE_REALACCEL

    // uncomment "OUTPUT_READABLE_WORLDACCEL" if you want to see acceleration
    // components with gravity removed and adjusted for the world frame of
    // reference (yaw is relative to initial orientation, since no magnetometer
    // is present in this case). Could be quite handy in some cases.
    //#define OUTPUT_READABLE_WORLDACCEL

    // uncomment "OUTPUT_TEAPOT" if you want output that matches the
    // format used for the InvenSense teapot demo
    //#define OUTPUT_TEAPOT

    #define LED_PIN 13 // (Arduino is 13, Teensy is 11, Teensy++ is 6)
    bool blinkState = false;

    // MPU control/status vars
    bool dmpReady = false;  // set true if DMP init was successful
    uint8_t mpuIntStatus;   // holds actual interrupt status byte from MPU
    uint8_t devStatus;      // return status after each device operation (0 = success, !0 = error)
    uint16_t packetSize;    // expected DMP packet size (default is 42 bytes)
    uint16_t fifoCount;     // count of all bytes currently in FIFO
    uint8_t fifoBuffer[64]; // FIFO storage buffer

    // orientation/motion vars
    Quaternion q;           // [w, x, y, z]         quaternion container
    VectorInt16 aa;         // [x, y, z]            accel sensor measurements
    VectorInt16 aaReal;     // [x, y, z]            gravity-free accel sensor measurements
    VectorInt16 aaWorld;    // [x, y, z]            world-frame accel sensor measurements
    VectorFloat gravity;    // [x, y, z]            gravity vector
    float euler[3];         // [psi, theta, phi]    Euler angle container
    float ypr[3];           // [yaw, pitch, roll]   yaw/pitch/roll container and gravity vector

    // packet structure for InvenSense teapot demo
    uint8_t teapotPacket[14] = { '$', 0x02, 0,0, 0,0, 0,0, 0,0, 0x00, 0x00, '\r', '\n' };

    // ================================================================
    // ===               INTERRUPT DETECTION ROUTINE                ===
    // ================================================================

    volatile bool mpuInterrupt = false;     // indicates whether MPU interrupt pin has gone high
    void dmpDataReady() {
        mpuInterrupt = true;
    }

    // ================================================================
    // ===                      INITIAL SETUP                       ===
    // ================================================================

    void setup() {
        // join I2C bus (I2Cdev library doesn't do this automatically)
        #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
            Wire.begin();
            TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz)
        #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
            Fastwire::setup(400, true);
        #endif

        // initialize serial communication
        // (115200 chosen because it is required for Teapot Demo output, but it's
        // really up to you depending on your project)
        Serial.begin(115200);
        while (!Serial); // wait for Leonardo enumeration, others continue immediately

        // NOTE: 8MHz or slower host processors, like the Teensy @ 3.3v or Ardunio
        // Pro Mini running at 3.3v, cannot handle this baud rate reliably due to
        // the baud timing being too misaligned with processor ticks. You must use
        // 38400 or slower in these cases, or use some kind of external separate
        // crystal solution for the UART timer.

        // initialize device
        Serial.println(F("Initializing I2C devices..."));
        mpu.initialize();

        // verify connection
        Serial.println(F("Testing device connections..."));
        Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));

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

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

        // supply your own gyro offsets here, scaled for min sensitivity
        mpu.setXGyroOffset(220);
        mpu.setYGyroOffset(76);
        mpu.setZGyroOffset(-85);
        mpu.setZAccelOffset(1788); // 1688 factory default for my test chip

        // make sure it worked (returns 0 if so)
        if (devStatus == 0) {
            // turn on the DMP, now that it's ready
            Serial.println(F("Enabling DMP..."));
            mpu.setDMPEnabled(true);

            // enable Arduino interrupt detection
            Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)..."));
            attachInterrupt(0, dmpDataReady, RISING);
            mpuIntStatus = mpu.getIntStatus();

            // set our DMP Ready flag so the main loop() function knows it's okay to use it
            Serial.println(F("DMP ready! Waiting for first interrupt..."));
            dmpReady = true;

            // get expected DMP packet size for later comparison
            packetSize = mpu.dmpGetFIFOPacketSize();
        } else {
            // ERROR!
            // 1 = initial memory load failed
            // 2 = DMP configuration updates failed
            // (if it's going to break, usually the code will be 1)
            Serial.print(F("DMP Initialization failed (code "));
            Serial.print(devStatus);
            Serial.println(F(")"));
        }

        // configure LED for output
        pinMode(LED_PIN, OUTPUT);
    }

    // ================================================================
    // ===                    MAIN PROGRAM LOOP                     ===
    // ================================================================

    void loop() {
        // if programming failed, don't try to do anything
        if (!dmpReady) return;

        // wait for MPU interrupt or extra packet(s) available
        while (!mpuInterrupt && fifoCount < packetSize) {
            // other program behavior stuff here
            // .
            // .
            // .
            // if you are really paranoid you can frequently test in between other
            // stuff to see if mpuInterrupt is true, and if so, "break;" from the
            // while() loop to immediately process the MPU data
            // .
            // .
            // .
        }

        // reset interrupt flag and get INT_STATUS byte
        mpuInterrupt = false;
        mpuIntStatus = mpu.getIntStatus();

        // get current FIFO count
        fifoCount = mpu.getFIFOCount();

        // check for overflow (this should never happen unless our code is too inefficient)
        if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
            // reset so we can continue cleanly
            mpu.resetFIFO();
            Serial.println(F("FIFO overflow!"));

        // otherwise, check for DMP data ready interrupt (this should happen frequently)
        } else if (mpuIntStatus & 0x02) {
            // wait for correct available data length, should be a VERY short wait
            while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();

            // read a packet from FIFO
            mpu.getFIFOBytes(fifoBuffer, packetSize);

            // track FIFO count here in case there is > 1 packet available
            // (this lets us immediately read more without waiting for an interrupt)
            fifoCount -= packetSize;

            #ifdef OUTPUT_READABLE_QUATERNION
                // display quaternion values in easy matrix form: w x y z
                mpu.dmpGetQuaternion(&q, fifoBuffer);
                Serial.print("quat\t");
                Serial.print(q.w);
                Serial.print("\t");
                Serial.print(q.x);
                Serial.print("\t");
                Serial.print(q.y);
                Serial.print("\t");
                Serial.println(q.z);
            #endif

            #ifdef OUTPUT_READABLE_EULER
                // display Euler angles in degrees
                mpu.dmpGetQuaternion(&q, fifoBuffer);
                mpu.dmpGetEuler(euler, &q);
                Serial.print("euler\t");
                Serial.print(euler[0] * 180/M_PI);
                Serial.print("\t");
                Serial.print(euler[1] * 180/M_PI);
                Serial.print("\t");
                Serial.println(euler[2] * 180/M_PI);
            #endif

            #ifdef OUTPUT_READABLE_YAWPITCHROLL
                // display Euler angles in degrees
                mpu.dmpGetQuaternion(&q, fifoBuffer);
                mpu.dmpGetGravity(&gravity, &q);
                mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
                Serial.print("ypr\t");
                Serial.print(ypr[0] * 180/M_PI);
                Serial.print("\t");
                Serial.print(ypr[1] * 180/M_PI);
                Serial.print("\t");
                Serial.println(ypr[2] * 180/M_PI);
            #endif

            #ifdef OUTPUT_READABLE_REALACCEL
                // display real acceleration, adjusted to remove gravity
                mpu.dmpGetQuaternion(&q, fifoBuffer);
                mpu.dmpGetAccel(&aa, fifoBuffer);
                mpu.dmpGetGravity(&gravity, &q);
                mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity);
                Serial.print("areal\t");
                Serial.print(aaReal.x);
                Serial.print("\t");
                Serial.print(aaReal.y);
                Serial.print("\t");
                Serial.println(aaReal.z);
            #endif

            #ifdef OUTPUT_READABLE_WORLDACCEL
                // display initial world-frame acceleration, adjusted to remove gravity
                // and rotated based on known orientation from quaternion
                mpu.dmpGetQuaternion(&q, fifoBuffer);
                mpu.dmpGetAccel(&aa, fifoBuffer);
                mpu.dmpGetGravity(&gravity, &q);
                mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity);
                mpu.dmpGetLinearAccelInWorld(&aaWorld, &aaReal, &q);
                Serial.print("aworld\t");
                Serial.print(aaWorld.x);
                Serial.print("\t");
                Serial.print(aaWorld.y);
                Serial.print("\t");
                Serial.println(aaWorld.z);
            #endif

            #ifdef OUTPUT_TEAPOT
                // display quaternion values in InvenSense Teapot demo format:
                teapotPacket[2] = fifoBuffer[0];
                teapotPacket[3] = fifoBuffer[1];
                teapotPacket[4] = fifoBuffer[4];
                teapotPacket[5] = fifoBuffer[5];
                teapotPacket[6] = fifoBuffer[8];
                teapotPacket[7] = fifoBuffer[9];
                teapotPacket[8] = fifoBuffer[12];
                teapotPacket[9] = fifoBuffer[13];
                Serial.write(teapotPacket, 14);
                teapotPacket[11]++; // packetCount, loops at 0xFF on purpose
            #endif

            // blink LED to indicate activity
            blinkState = !blinkState;
            digitalWrite(LED_PIN, blinkState);
        }
    }

body:
I'm not sure about the "wirelessly" context, but you can try this steps
1. Make sure you can read the mpu-6050 data
2. You can use bluetooth (HC-05 is the most common) to transfer data to your PC bluetooth directly, or to another arduino, then send it via serial usb cable to PC


body:
This is just a conception plan:

Make sure you can get all the data (YPR) you need from the MPU.

Then, using whatever protocol you want, send the data under the form of something like a byte. [Here][1] is a question I aksed about a similar topic.

For more info, please comment, I'll be happy to help.

  [1]: https://arduino.stackexchange.com/questions/30513/sending-analog-data-with-and-ir-led


body:
You have a few options here for the wireless communication (~ denotes wireless):

 - MPU -> Arduino -> Bluetooth ~ ~ ~> PC
 - MPU -> Arduino -> NRF ~ ~ ~> NRF -> Arduino -> PC
 - MPU -> Arduino -> WiFi (ESP?) ~ ~ ~> PC

I don't think it'd be easy to directly communicate I2C over the NRF, so I'd just _read_ the data over I2C (presumably you're using Jeff Roweburg's library?), then once you have it in an integer or byte, you can use any wireless module to send it over whatever method you prefer. I haven't touched the ESP8266 for WiFi, but I know the HC-05/06 and the NRF24L01 both have fairly simple libraries that can do a simple write command that will buffer a number of bytes and send it all out in the correct order.

**edit:**

This is code I used a long time ago, and it is almost definitely somebody else's. I'm dreadfully sorry I can't find the original author at the moment, else I'd happily link to their page on the NRF. You can split this up into a receive and transmit pair though, and get rid of all the serial printing stuff as that just used the NRFs to 'text' each other.

Two Way Communication:

    #include <SPI.h>
    #include <nRF24L01.h>
    #include <RF24.h>

    RF24 radio(7, 8);
    const int radioNum = 0;
    const byte rxAddr[6] = "00001";
    const byte txAddr[6] = "00002";

    String readSerial() {
        String input;
        while(Serial.available() > 0){
            input.concat((char)Serial.read());
            delay(1);     //allows the buffer to fill with each character
        }
        return input;
    }

    void setup()
    {
      radio.begin();
      Serial.begin(9600);
      radio.setRetries(15, 15);
      if(radioNum){
        radio.openWritingPipe(rxAddr);
        radio.openReadingPipe(1, txAddr);
      }
      else{
        radio.openWritingPipe(txAddr);
        radio.openReadingPipe(1, rxAddr);
      }
      Serial.println("Enter a string of characters:");

    }

    void loop()
    {
      radio.startListening();
      while(Serial.available()==0){
        char output[32];
        radio.read(&output, 32);
        if(output[0]){
          if(radioNum)
             Serial.print("Pong: ");
          else
             Serial.print("Ping: ");
          Serial.println(output);
        }
      }
      radio.stopListening();

      String input = readSerial();
      char text[32];
      input.toCharArray(text,32);
      radio.write(&text, 32);

      if(radioNum)
        Serial.print("Ping: ");
      else
        Serial.print("Pong: ");

      Serial.println(text);
    }
    }


message:
how to measure level shock using vibration sensor and arduino

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

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

My project title is about crash detection, by using this kind of vibration sensor. When the sensor reads the shock (which is when I knock the sensor) more than 50, it assumes it's a crash and will send via SMS the location of the crash to me. The problem is, that I tried to connect the sensor with Arduino, but when I knocked the sensor, the value of the shock did not change. How can I fix this?

VCC I connected to 5V,
GND to Arduino GND,
A0 to analog input Arduino,
D0 is not used

This is my code
**************************

    #include <SoftwareSerial.h>

    #include <TinyGPS.h>

    TinyGPS gps;
    SoftwareSerial ss(2, 3);
    SoftwareSerial GSMx(5, 11);

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

    //-------------------VARIABLE-------------------------------
    float LastLon;
    String dataString = "";
    String DateString = "";
    String TimeString = "";
    int Sens1Pin = 0;
    float Sens1;
    int update=0;
    float LastLat;
    int dummy=0;
    int RQScount;
    int countERROR;
    int countPHONE;
    int countOK;
    int commaPosition;
    int index = 0;
    int SMSx=0;
    int ALARM=0;
    int LOCK=0;
    float latx;
    float lonx;
    int OUTRANGE=0;
    String result[10];
    String USER1 = "\"019*******\"";
    String Data1 = "";
    String Data2 = "";
    String Data3 = "";
    String Data4 = "";
    String head = "";
    String phone = "";
    String pword = "";
    String MESSAGE1="";
    String MESSAGE2="";
    String inputString = "";         // a string to hold incoming data
    boolean stringComplete = true;  // whether the string is complete
    boolean command = true;
    boolean Enabled = false;
    boolean Enabled1 = false;
    boolean Enabled2 = false;
    boolean Enabled3 = false;
    boolean GPS_NoData = false;
    float SHOCK;
    int count;
    float flat, flon;
      unsigned long age, date, time, chars = 0;
      float ExistingSpeed;
    float SpeedGPS;

    //----------------------------------------------------------

    void setup()
    {

      Serial.begin(9600);
      GSMx.begin(9600);
      inputString.reserve(150);
     delay(8000);

      //Serial.println("AT");
      GSMx.println("AT");
      delay(2000);
     // Serial.println("AT+CMGF=1");
      GSMx.println("AT+CMGF=1");
      delay(2000);
     // Serial.println("AT+CMGD=1");
      GSMx.println("AT+CMGD=1");
      delay(2000);
      //Serial.println("AT&W");
      GSMx.println("AT&W");
      delay(2000);

      //Serial.print("AT+CMGS=");
      delay(300);
      //Serial.println(USER1);
      GSMx.print("AT+CMGS=");
      delay(300);
      GSMx.println(USER1);
      delay(1000);
      //Serial.print("GPS-GSM TRACKER---ACTIVATED ");
      GSMx.print("Controller is now ready...");
      delay(200);
      //Serial.println(char(26));
      GSMx.println(char(26));
      delay(4000);

      //Serial.println("Sats HDOP Latitude  Longitude  Fix  Date       Time     Date Alt    Course Speed Card  Distance Course Card  Chars Sentences Checksum");
      //Serial.println("          (deg)     (deg)      Age                      Age  (m)    --- from GPS ----  ---- to London  ----  RX    RX        Fail");
      //Serial.println("-------------------------------------------------------------------------------------------------------------------------------------");

      ss.begin(9600);
      //--------------------------------------

      stringComplete = true;
    }

    void loop()
    {

      Sens1 = analogRead(Sens1Pin);           //read the value from the sensor
      Sens1 = (5.0 * Sens1 * 100.0)/1024.0;  //convert the analog data to digital

      SHOCK = ((390 - Sens1)/390)*100;

      unsigned short sentences = 0, failed = 0;
      static const double LONDON_LAT = 51.508131, LONDON_LON = -0.128002;

     if (SHOCK > 40){
        ALARM=1;
      }

      if (ALARM==1){
        delay(100);

        if (SMSx==0){
         //  Serial.print("AT+CMGS=");
                    GSMx.print("AT+CMGS=");
                   // Serial.println(USER1);
                    GSMx.println(USER1);
                    delay(1000);
                   // Serial.print("ALARM ALERT!! at location, lat:");
                    GSMx.print("EMERGENCY ALERT!!");
                   // Serial.print(flat,5);
                    GSMx.print(TimeString);
                    GSMx.print(" ");
                    GSMx.print(DateString);
                    GSMx.print(" (LAT/LON/SPEED) ");
                    GSMx.print(dataString);

                    GSMx.print("www.google.co.in/maps/place/");
                    GSMx.print(flat,5);
                    GSMx.print(",");
                    GSMx.println(flon,5);

                    delay(200);
                   // Serial.println(char(26));
                    GSMx.println(char(26));
                    delay(4000);

          SMSx=1;
          ALARM=0;
        }
      }

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

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

       if (flat < 0.1){
        GPS_NoData = true;
      }
      if (flat > 0.1){
        GPS_NoData = false;
      }

      if (flat != LastLat){
                   if (GPS_NoData == false){
                     LastLat = flat;
                   }
                 }
                 if (flon != LastLon){
                   if (GPS_NoData == false){
                     LastLon = flon;
                   }
                 }

      //---------------------------------GSM FUNCTION-----------------------------------------

                  Serial.print(TimeString);
                  Serial.print(" ");
                  Serial.print(DateString);
                  Serial.print(" ");
                  Serial.print(flon,5);
                  Serial.print(", ALARM:");
                  Serial.print(ALARM);
                  Serial.print(", DATA:");
                  Serial.print(dataString);
                  Serial.print(", SHOCK LEVEL: ");
                  Serial.println(SHOCK);

    if (stringComplete == true){

      //Serial.println("AT+CMGR=1");
       GSMx.println("AT+CMGR=1");

      count = 0;
      countERROR = 0;
      countPHONE = 0;
      countOK = 0;
      stringComplete = false;
      Enabled = false;
      Enabled1 = false;
      Enabled2 = false;
      Enabled3 = false;
    }

      while (stringComplete == false){
     // count = count + 1;
           while (Serial.available() > 0){

            char inChar = Serial.read();
            inputString += inChar;

            if (Enabled2){
              Data2 += inChar;
              countPHONE = countPHONE + 1;
                if (countPHONE == 10){
                Enabled2 = false;
                }
            }

            if (inChar == 'E'){
              Enabled1 = true;
             }
             if (Enabled1){
              Data1 += inChar;
              countERROR = countERROR + 1;
                    if (countERROR == 5){
                     Enabled1 = false;
                          if (Data1 == "ERROR"){
                            stringComplete = true;
                          }
                          if (Data1 != "ERROR"){
                            countERROR = 0;
                            Data1 += "";
                            Enabled1 = false;
                          }
                    }

            }

            if (inChar == 'O'){
              Enabled3 = true;
             }
             if (Enabled3){
              Data4 += inChar;
              countOK = countOK + 1;
                   if (countOK == 2){
                    if (Data4 == "OK"){
                      stringComplete = true;
                    }
                    if (Data4 != "OK"){
                      countOK = 0;
                      Data4 = "";
                      Enabled3 = false;
                    }
                   }
             }
            if (inChar == '+'){
              if (count > 5){
                Enabled2 = true;
              }
            }
            if (count > 80){
                stringComplete = true;

             }

           }
    }

           if (stringComplete){
             /*

                    */
                // Serial.println(inputString);
                index = 0;
        do
      {
          commaPosition = inputString.indexOf('*');
          if(commaPosition != -1)
          {
              result[index++] = (inputString.substring(0,commaPosition));
              inputString = inputString.substring(commaPosition+1, inputString.length());
          }
        //  else
        //  {  // here after the last comma is found
        //     if(inputString.length() > 0)
        //       Serial.println(inputString);  // SMS message after final splitting
                                 // print it
         // }
       }
       while(commaPosition >=0);
         MESSAGE1 = result[2];
         MESSAGE2 = result[3];

             if (result[1] == "LOCATION") {
        //            Serial.print("AT+CMGS=");
                    GSMx.print("AT+CMGS=");
        //            Serial.println(USER1);
                    GSMx.println(USER1);
                    delay(1000);
        //            Serial.print("DEVICE TRACKING, lat:");
                    GSMx.print("DEVICE TRACKING, lat:");
        //            Serial.print(flat,5);
                    GSMx.print(flat,5);
        //            Serial.print(", lon:");
                    GSMx.print(", lon:");
        //            Serial.println(flon,5);
                    GSMx.println(flon,5);
        //            Serial.print("www.google.co.in/maps/place/");
        //            Serial.print(flat,5);
        //            Serial.print(",");
        //            Serial.println(flon,5);
                    GSMx.println(" SPEED:");
                    GSMx.println(SpeedGPS);
                    GSMx.print("www.google.co.in/maps/place/");
                    GSMx.print(flat,5);
                    GSMx.print(",");
                    GSMx.println(flon,5);

                    delay(200);
        //            Serial.println(char(26));
                    GSMx.println(char(26));
                    delay(4000);
        //            Serial.println("AT+CMGD=1");
                    GSMx.println("AT+CMGD=1");

                    delay(4000);

                }

                                  if (result[1] == "RST") {
        //            Serial.print("AT+CMGS=");
                    GSMx.print("AT+CMGS=");
        //            Serial.println(USER1);
                    GSMx.println(USER1);
                    delay(1000);
        //            Serial.print("Alarm reset...");
                    GSMx.print("Alarm reset..");
                    delay(200);
        //            Serial.println(char(26));
                    GSMx.println(char(26));
                    delay(4000);
        //            Serial.println("AT+CMGD=1");
                    GSMx.println("AT+CMGD=1");
                    ALARM=0;  SMSx=0;

                    delay(4000);

                }

           inputString = "";
           result[1] = "";
           result[2] = "";
           result[3] = "";
           result[4] = "";
           result[5] = "";
           result[6] = "";
           Data1 = "";
           Data2 = "";
           Data3 = "";
           Data4 = "";
          // Serial.flush();

          // stringComplete = true;
      delay(100);
      Sens1 = analogRead(Sens1Pin);           //read the value from the sensor
      Sens1 = (5.0 * Sens1 * 100.0)/1024.0;  //convert the analog data to digital
      SHOCK = ((390 - Sens1)/390)*100;
      if (SHOCK > 50){
        ALARM=1;
      }
      Serial.print("SHOCK LEVEL: ");
      Serial.println(SHOCK);
      delay(100);
      Sens1 = analogRead(Sens1Pin);           //read the value from the sensor
      Sens1 = (5.0 * Sens1 * 100.0)/1024.0;  //convert the analog data to digital
      SHOCK = ((390 - Sens1)/390)*100;
      if (SHOCK > 40){
        ALARM=1;
      }
      Serial.print("SHOCK LEVEL: ");
      Serial.println(SHOCK);
      delay(100);
      Sens1 = analogRead(Sens1Pin);           //read the value from the sensor
      Sens1 = (5.0 * Sens1 * 100.0)/1024.0;  //convert the analog data to digital
      SHOCK = ((390 - Sens1)/390)*100;
      if (SHOCK > 40){
        ALARM=1;
      }
      Serial.print("SHOCK LEVEL: ");
      Serial.println(SHOCK);
      delay(100);
      Sens1 = analogRead(Sens1Pin);           //read the value from the sensor
      Sens1 = (5.0 * Sens1 * 100.0)/1024.0;  //convert the analog data to digital
      SHOCK = ((390 - Sens1)/390)*100;
      if (SHOCK > 40){
        ALARM=1;
      }
      Serial.print("SHOCK LEVEL: ");
      Serial.println(SHOCK);
           }

      delay(100);
     // smartdelay(300);
    }
    //--------------------------------------START OF SUBROUTINES-------------------------------------
    static void smartdelay(unsigned long ms)
    {
      unsigned long start = millis();
      do
      {
        while (ss.available())
          gps.encode(ss.read());
      } while (millis() - start < ms);
    }

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

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

    static void print_date(TinyGPS &gps)
    {
      int year;
      byte month, day, hour, minute, second, hundredths;
      float Speed;
      unsigned long age;
      gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age);
      if (age == TinyGPS::GPS_INVALID_AGE)
       // Serial.print("********** ******** ");
       dummy = 1;

      else
      {

        char sz[32];
        sprintf(sz, "d/d/d d:d:d ",
            month, day, year, hour, minute, second);
       // Serial.print(sz);

      //  hour = hour+8;
      //  sprintf(lcd_buffer,"d/d/d d:d",day,month,year,hour,minute );

        hour = hour + 8;
        if (hour > 23){
          hour = hour - 24;
        }
        dataString="";
        TimeString="";
        DateString="";
        ExistingSpeed = gps.f_speed_kmph();
        Speed = gps.f_speed_kmph();
        SpeedGPS = Speed;

       TimeString = String(hour) + ":" + String(minute) + ":" + String(second);
       DateString = String(day) + "/" + String(month) + "/" + String(year);
       dataString = String(flat,5) + "  " + String(flon,5) + "  " + String(Speed,2);

      }
      print_int(age, TinyGPS::GPS_INVALID_AGE, 5);
      smartdelay(0);

        }

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

body:
From the huge amount of code it's hard to tell what exactly is wrong, but I noticed that you used `0` for the analog pin which is not the same as `A0`.

Your pin number should be defined as:

    int Sens1Pin = A0;


message:
I2C collision detection

I have put together a system that uses multiple Arduinos and a couple of 20x4 LCD displays to monitor my PV sun tracker and a weather station.  I am using I2C to link them all together.  One of the LCDs has been modified to have a different address (0x3b) so as to not conflict with the first one (0x3f).  So far, so good.   The sun tracker shows its display on the yellow one and the weather station shows its data on the blue one.

In order to connect this together I am using the Mayhew I2C&Power devices, so one power source energizes the entire system.  I send 12 Volts on the wire, then at each node I use a 12v to 5v converter to provide power for the I2C&Power board and the Nanos.  (The anemometer on the WX needs 12V to operate so that's a plus)

Each Arduino has a unique I2C address - there is no master in the system.

I have learned to set the screen updates to be quick (take readings and do any calculations before writing to the LCD in one swell foop), and to stagger the display update timings (the WX info updates every 65050 ms (full display update) and the PV info updates every 67050 ms (4 characters) and 605550 ms (full display refresh).  I chose these (arbitrarily random) values to make it less likely that they would try to update at the same time, because when both systems try to update their respective displays at the same time it causes some very interesting results - basically wiping out one or both displays.  It works most of the time but eventually one or the other screen will get wiped out.

Question:  Is there any way to implement collision detection on the I2C bus to prevent transmitting while other devices are communicating?  Something like CSMA/CD (Carrier Sense Multiple Access with Collision Detection) on Ethernet..

body:
Collision detection on I2C is fully supported (See [I2C Multi-Master](http://www.i2c-bus.org/multimaster/)). It works basically by attempting to transmit something and reading what is being transmitted at the same time. If what is read matches what is transmitted then the transmission worked. If it didn't match then there was a collision.

It is usually performed on a per-bit basis:

1. If a 0 then pull the data line LOW. If a 1 then let the resistor pull the data line HIGH.
2. Read the data line. If you want a 1 and get a 0 then some other device is pulling the data line low for a 0.
3. If the value was wrong then stop your transmission and back off by a random amount. Retry again. (note: both ends may retry, so you need good random numbers).

There is no support in the Wire library for collision detection, though, so you will have to implement it yourself. Section 22.4 of [the datasheet](http://www.atmel.com/Images/Atmel-8271-8-bit-AVR-Microcontroller-ATmega48A-48PA-88A-88PA-168A-168PA-328-328P_datasheet_Complete.pdf) gives you more information about how to implement it.


message:
Arduino Leonardo - Using ICSP pins for serial

I'd like to know if it's possible to use the ICSP header pins on the Leonardo as GPIO pins, for example for software serial, and how to address them. I've a project which needs all available I/O pins, and I could use having serial comms on those "extra" pins.

body:
From `packages/arduino/hardware/avr/1.6.*/variants/leonardo/pins_arduino.h`:

>     // Map SPI port to 'new' pins D14..D17
    #define PIN_SPI_SS    (17)
    #define PIN_SPI_MOSI  (16)
    #define PIN_SPI_MISO  (14)
    #define PIN_SPI_SCK   (15)

>     static const uint8_t SS   = PIN_SPI_SS;
    static const uint8_t MOSI = PIN_SPI_MOSI;
    static const uint8_t MISO = PIN_SPI_MISO;
    static const uint8_t SCK  = PIN_SPI_SCK;

Those are the pin names and numbers you can use. Note that `SS`/17 is connected to the RX LED.


message:
Arduino Nano periodic reset under program control?

Is there a way to cause a periodic reset of an Arduino Nano under program control, short of some kind of external relay that signals the RST pin?

I'd like to do a full reset triggered by a digital write.

When the power is applied to the Nano it automatically pulls all the digital output pins to LOW so it appears that simply connecting a wire from a digital output to the RST pin would cause the system to continually reset and never run the program.  This would apply equally to using the DS3231 RTC chip's alarm function.  It would require the program to run in order to use it.

I suppose a relay would do the trick.  Or maybe even just an inverter chip like the 7404 between a digital output and the RST pin.  I am trying to fit this all in a small box so more hardware gets to be a problem.

So the question:  Is there any way to do this without external hardware?

body:
Why do you want to reset you board?  The reason affects the answer.

Do you want to reset the board because your program crashes after n hours?  If so its probably better to fix the memory leak that you have in the code.

Is it because some global variables need to resetting every now and again?  If so could you place them in a class and store a pointer to them as your only global.  When you want to 'reset' the board delete the instance of the class and recreate it.

What happens if the software crashes?  Have you got it configured to restart on a crash?  If so could you just crash the code deliberately?

Because you have size constraints then it may be worth a bit of lateral thinking to see what the code can do for you.


message:
Making two Arduinos/MKR1000s communicate

I am trying to create a project in my free time just for a bit of fun. It consists of two MKR1000s (one acting as a web server connected to one laptop, and the other acting as a web client connected to a different laptop - so I can view the Serial Monitor).

One MKR1000 has a potentiometer attached to it (therefore I can change the value of it), and sends the potentiometer value to the serial monitor every 4 seconds.

**THE AIM:** Once the web server sets up the w
WifFi network, and the web client connects to that WiFi network, I want to send the potentiometer value across to the web client every time it gets updated. However, I am clueless on how to achieve this.

**This is my web server void loop code** (the rest is similar to the https://www.arduino.cc/en/Tutorial/Wifi101WiFiWebServer):

    void loop() {
      WiFiClient client = server.available();
      // listen for incoming clients
      if (client) {
        // if you get a client,
        Serial.println("new client");
        // print a message out the serial port
        String currentLine = "";
        // make a String to hold incoming data from the client
        while (client.connected()) {
          // loop while the client's connected
          if (client.available()) {
            // if there's bytes to read from the client,
            char c = client.read();
            // read a byte, then
            Serial.write(c);
            // print it out the serial monitor
            if (c == '\n') {
              if (currentLine.length() == 0) {
                client.println("HTTP/1.1 200 OK");
                client.println("Content-type:text/html");
                client.println();
                // the content of the HTTP response follows the header:
                client.print("Click here showValue of the potentiometer
");
                // The HTTP response ends with another blank line:
                client.println();
                // break out of the while loop:
                break;
              } else {
                // if you got a newline, then clear currentLine:
                currentLine = "";
              }
            } else if (c != '\r') {
              currentLine += c;
              // add it to the end of the currentLine
            }
            if (currentLine.endsWith("GET /showValue")) {
              Serial.println(sensorValue);
              delay(2000);
            }
          }
        }
        client.stop();
      }
    }

**And this is my web client code I use this** https://www.arduino.cc/en/Tutorial/Wifi101WiFiWebClient  - I am not sure how I should modify this in order to receive the potentiometer value across from the web server MKR1000. Any tips or hints would be hugely appreciated!

I am sorry if this is a simple question, however I am just starting with the Arduino idea, and I'm new to coding!

body:
At the bottom of the page for the client code link you provided, there's a link to a Chat Server example. If you study the code I think you'll see how to send and receive the potentiometer reading. Hint: Look in the code where it echoes what it receives.

[mkr1000 WiFi Chat Server][1]

  [1]: https://www.arduino.cc/en/Tutorial/Wifi101WiFiChatServer


body:
You don't have to use a webserver/webclient for this; a raw socket would also work. If you do want to use "web technology":

You can either have the webclient poll the webserver periodically for a new value (ask for a new value every few seconds, and interpret the response), or have the webserver initiate the communication every time a new value is available.

For the latter, you could use Server-Sent Events (SSE) or a Websocket, both of which are very google-able.

I have made examples for both, but these examples are fairly large and have extra functionality. Still, they may give you some pointers and/or code to reuse.

These examples are here:

https://github.com/ocrdu/arduino-webinterface-sse

and here:

https://github.com/ocrdu/arduino-webinterface-websocket-ap

Note that the client side in the examples is a webpage in a webbrowser, but the principle is the same.


message:
Record Ping time using ultrasonic sensors and calculate speed

I'm trying to find the speed of remote control toy car passing by two ultrasonic sensors. I need help on my code and suggestion on max speed car should go to record time. Opposite direction not accounted for and ideally the car would pass by both sensors without stopping. I know laser reading is better for this simulation but I need it for a presentation in two weeks.

Here are the steps I was recommended to use:

1. Get the duration of pulse for sensor 1 and convert to distance
2. if the distance the object is within the desired threshold (you detected something)
 2a. record the system time at which object was detected
 2b. start a loop to for sensor 2
3. Within the sensor 2 loop keep getting the duration/distance until an object is detected or too much time has passed
4. If an object is detected record the system time
5. Subtract the two system times (from sensor 1 and 2) and use that to determine object speed

        #define sensor_distance .111 //distance between two sensors in meters
        const int trigPin1 = 3;
        const int echoPin1 = 4;
        const int trigPin2 = 5;
        const int echoPin2 = 6;

        double first_time = 0;
        double second_time = 0;
        double final_time = 0;

        double vehicle_speed = 0;

        void setup() {

          pinMode(trigPin1, OUTPUT);
          pinMode(echoPin1, INPUT);
          pinMode(trigPin2, OUTPUT);
          pinMode(echoPin2, INPUT);

          Serial.begin(9600);
        }

        void loop() {

        double ping_time(int trig1, int echo1, double first_time);
        double ping_time(int trig2, int echo2, double second_time);

        final_time = second_time - first_time;
        vehicle_speed = sensor_distance/final_time;
        }

        double ping_time(int trig, int echo, double record_time) //function used to record time.
        {
          long duration, distance;

           digitalWrite(trig, LOW);
          delayMicroseconds(2);
          digitalWrite(trig, HIGH);
          delayMicroseconds(10);
          digitalWrite(trig, LOW);

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

          if (distance < 35) {
            Serial.print(distance);
            Serial.println("  cm");
            record_time = millis();
            record_time = record_time/100; //Divided by 100 to get time in seconds

            return record_time;

          }
          if (distance > 35) {
            Serial.println("OUT OF RANGE");
          }
          delay(20);
        }

body:
In **THEORY**, this code should work. If there are any mistakes, please notify me and not hate on me. I did not have the equipment at hands to test the code in real life.

Chears!

    const int trigPins[2] = {3, 5}; //trig1 and trig2
    const int echoPins[2] = {4, 6}; //echo1 and echo2

    const int sensorDistance = 7;   //7 is the cm distance at which the sensors distant from eachother in CM

    void setup() {
      pinMode(trigPins[0], OUTPUT); //set trig pin 1 as output
      pinMode(echoPins[0], INPUT);  //set echo pin 1 as input
      pinMode(trigPins[1], OUTPUT); //set trig pin 2 as output
      pinMode(echoPins[1], INPUT);  //set echo pin 2 as input

      Serial.begin(9600);
    }

    void loop() {

      if (getDistance(0) == true)                   //if the car passed the first sensor
      {
        unsigned long currentMillis = millis();               //time when the passed the first sensor

        while (getDistance(1) == false);            //wating car to pass the second sensor

        unsigned long endMillis = millis();                   //time at which the car passed the second sensor

        unsigned long timeMillis = endMillis - currentMillis; //get duration in ms
        float timeSeconds = timeMillis / 1000.0;        //because 1000ms = 1s

        float s = sensorDistance / timeSeconds;       //speed = distance / time

        Serial.print(s);
        Serial.print(" cm/s");
        Serial.println();
      }
    }

    bool getDistance(int sensor)
    {
      //max range is 200cm, if further, it will go a little wild

      digitalWrite(trigPins[sensor], LOW); //set the trigger pin to low
      delayMicroseconds(2); //wait for 2 microseconds
      digitalWrite(trigPins[sensor], HIGH); //set the trigger pin to high
      delayMicroseconds(10); //wait for 10 microseconds
      digitalWrite(trigPins[sensor], LOW); //set the trigger pin to low

      long duration = pulseIn(echoPins[sensor], HIGH); //read the echo pin and calculate the duration in microseconds

      long distance = duration * 0.034 / 2;

      if (distance < 50) //50 is a reasonable distance other wise it might be innacurate
      {
        return true;
      }

      else
      {
        return false;
      }

    }


body:
You can try this, but I don't know if this gonna works or not since it is "imaginary-based"

    const int trigPin1 = 3;
    const int echoPin1 = 4;
    const int trigPin2 = 5;
    const int echoPin2 = 6;

    void setup() {

      pinMode(trigPin1, OUTPUT);
      pinMode(echoPin1, INPUT);
      pinMode(trigPin2, OUTPUT);
      pinMode(echoPin2, INPUT);

      Serial.begin(9600);
    }

    void loop()
    {
     if (ultraSonicdetect())
     {
      while (ultraSonicdetect(trigPin1,echoPin1)); // wait the car pass ultrasonic 1
      first_time = millis();
      while (!ultraSonicdetect(trigPin2,echoPin2)); //wait the car approach ultrasonic 2
      second_time = millis();

      //here you can calculate the speed, time needed to travel from ultrasonic 1 to ultrasonic 2
      //can be calculated from
      //(speed = second_time - first_time) / sensor range
     }
    }

    bool ultraSonicdetect(int trig, int echo) {
       long duration;
       float distance;
       digitalWrite(trigPin, LOW);
       delayMicroseconds(60);
       digitalWrite(trigPin, HIGH);
       delayMicroseconds(60);
       digitalWrite(trigPin, LOW);
       duration = pulseIn(echoPin, HIGH);
       distance = (duration * 0.034) / 2;
       if (distance<35) return true; else return false;
    }


message:
DHT11 sensor works on Arduino Uno, not on LoLin NodeMcu

When run [this code][1] on an Arduino Uno (clone), everything works.
When I run it on my LoLin NodeMcu, I get the following verbose upload output:

    esptool v0.4.9 - (c) 2014 Ch. Klippel <ck@atelier-klippel.de>
     setting board to nodemcu
     setting baudrate from 115200 to 115200
     setting port from COM1 to COM4
     setting address from 0x00000000 to 0x00000000
     espcomm_upload_file
     espcomm_upload_mem
     setting serial port timeouts to 1000 ms
    opening bootloader
    resetting board
    trying to connect
     flush start
     setting serial port timeouts to 1 ms
     setting serial port timeouts to 1000 ms
     flush complete
     espcomm_send_command: sending command header
     espcomm_send_command: sending command payload
     read 0, requested 1
    trying to connect
     flush start
     setting serial port timeouts to 1 ms
     setting serial port timeouts to 1000 ms
     flush complete
     espcomm_send_command: sending command header
     espcomm_send_command: sending command payload
     read 0, requested 1
    trying to connect
     flush start
     setting serial port timeouts to 1 ms
     setting serial port timeouts to 1000 ms
     flush complete
     espcomm_send_command: sending command header
     espcomm_send_command: sending command payload
     read 0, requested 1
    resetting board
    trying to connect
     flush start
     setting serial port timeouts to 1 ms
     setting serial port timeouts to 1000 ms
     flush complete
     espcomm_send_command: sending command header
     espcomm_send_command: sending command payload
     read 0, requested 1
    trying to connect
     flush start
     setting serial port timeouts to 1 ms
     setting serial port timeouts to 1000 ms
     flush complete
     espcomm_send_command: sending command header
     espcomm_send_command: sending command payload
     read 0, requested 1
    trying to connect
     flush start
     setting serial port timeouts to 1 ms
     setting serial port timeouts to 1000 ms
     flush complete
     espcomm_send_command: sending command header
     espcomm_send_command: sending command payload
     read 0, requested 1
    resetting board
    trying to connect
     flush start
     setting serial port timeouts to 1 ms
     setting serial port timeouts to 1000 ms
     flush complete
     espcomm_send_command: sending command header
     espcomm_send_command: sending command payload
     read 0, requested 1
    trying to connect
     flush start
     setting serial port timeouts to 1 ms
     setting serial port timeouts to 1000 ms
     flush complete
     espcomm_send_command: sending command header
     espcomm_send_command: sending command payload
     read 0, requested 1
    trying to connect
     flush start
     setting serial port timeouts to 1 ms
     setting serial port timeouts to 1000 ms
     flush complete
     espcomm_send_command: sending command header
     espcomm_send_command: sending command payload
     read 0, requested 1
    warning: espcomm_sync failed
    error: espcomm_open failed
    error: espcomm_upload_mem failed
    error: espcomm_upload_mem failed

The only difference I really see is that on the Arduino Uno, the voltage pin is connected to 5V, while on the LoLin, it's connected to one of the 3V pins. Does the DHT11 require 5V?

**Edit**

So I stumbled upon [this list of port mappings][2]. When I change my pin number to 5 (meaning D1), it actually works. Kinda. The numbers outputted are strange. Even when I put the board outside, in about -6 Celcius, it still displays

    Temp 247.208 °C
    RH 216.208 %

Well, I guess this oddity should be posted as another question. I'll answer my own question here with reference to the weird pin-to-number mapping on the LoLin board.

  [1]: https://tkkrlab.nl/wiki/Arduino_KY-015_Temperature_and_humidity_sensor_module#Schematic
  [2]: https://github.com/esp8266/Arduino/issues/584#issuecomment-123715951

body:
The datasheet says 3V-5V. 3V is the minimum so I **DOUBT** that isn't the problem, **BUT** try to pump more juice into it to see what happens. Never believe the datasheet if these cheap components at 100%.

It does say this though:

>VDD=5V, T = 25℃ (unless otherwise stated)

So maybe....

[Link to datasheet.][1]

  [1]: http://www.micropik.com/PDF/dht11.pdf


body:
The problem was that the port mappings on the LoLin board didn't make much sense.

Port D0 is for instance mapped to number 16, not 0.

Go [to this Github comment][1] to get a complete list:

    /*
     * Weird pin mappings on LoLin:
     *
     * static const uint8_t D0   = 16;
     * static const uint8_t D1   = 5;
     * static const uint8_t D2   = 4;
     * static const uint8_t D3   = 0;
     * static const uint8_t D4   = 2;
     * static const uint8_t D5   = 14;
     * static const uint8_t D6   = 12;
     * static const uint8_t D7   = 13;
     * static const uint8_t D8   = 15;
     * static const uint8_t D9   = 3;
     * static const uint8_t D10  = 1;
    */

**Missing decimal digits and not able to measure sub zero values**

If [this comment on github][2] is correct, the DHT11 sensor *does not offer decimals* and *does not measure values below zero*.

  [1]: https://github.com/esp8266/Arduino/issues/584#issuecomment-123715951
  [2]: https://github.com/RobTillaart/Arduino/issues/5#issuecomment-34655292


body:
I was scratching my head since last two days over similar issue. I am using ESP8266 NodeMCU which is V2 of LoLin NodeMCU and wanted to read DHT11 sensor data over WiFi into blynk app. However my serial output was 'Failed to read from DHT sensor!'. The program and interfacing was working perfectly with Arduin Uno and Raspberry Pi but not with NodeMCU.

Being a hardware guy, I tried all sorts of hardware modification possible. I had [DHT11 sensor module][1] which is already having 5k pull up resistors on board. Since NodeMCU board doesn't have 5V supply, I desoldered the sensor and did direct interfacing with 10k resistor as recommended by [adafruit DHTxx guide][2]. Doing internet search , someone recommended IDE version issue, tried that too. Nothing worked.

Finally referring per @nitech answer, I checked the pin details of NodeMCU board and got the idea of D2 pin actual mapped on GPIO4. Just changed the pin 2 with 4 in example code and it worked. Voila! I think recent race in achieving most of the boards as Arduino shield and IDE standard compatible, we need to be used for such issues for any deviation.

  [1]: https://www.amazon.com/Temperature-Relative-Humidity-Compatible-Arduino/dp/B00TM87YRS
  [2]: https://cdn-learn.adafruit.com/downloads/pdf/dht.pdf


message:
WaveHC Library Trouble

I posted this on the main Arduino forum, but no one has responded in 24 hours.

I'm trying to use the `WaveHC` library from Adafruit with a custom PCB. I am having trouble getting the `SPI` com to work for some reason, I modified the `ArduinoPins.h`, `SS_PIN`, from pin 10 to 8.

Using the Arduino SD library, I can see all the files no problem.

In the `WaveHC` library, all of the examples freeze after `card.init()`, I traced it to the `spiSend(uint8_t b)` in `SdReader.cpp`. It seems to get stuck in `while(!(SPSR & (1 << SPIF))`. This looks like the `SPDR` register (the `SPI` data register) is never loaded properly.

Does anyone know what is going on?

Adafruit library : https://github.com/adafruit/WaveHC

Edit :
This is the output from the SDReadTest example (Arduino SD Library)

 Initializing SD card...Wiring is correct and a card is present.

 Card type: SD2

 Volume type is FAT32

 Volume size (bytes): 1973350400
 Volume size (Kbytes): 1927100
 Volume size (Mbytes): 1881

 Files found on the card (name, date and size in bytes):
 SYSTEM~1/     2016-11-07 14:11:06
   INDEXE~1      2016-11-07 14:11:06 76
 0.WAV         2016-11-07 11:44:14 22124
 1.WAV         2016-11-07 11:44:14 18604
 2.WAV         2016-11-07 11:44:14 19244
 3.WAV         2016-11-07 11:44:14 19884
 4.WAV         2016-11-07 11:44:14 21164
 5.WAV         2016-11-07 11:44:14 23084
 6.WAV         2016-11-07 11:44:14 21484
 7.WAV         2016-11-07 11:44:14 29484
 8.WAV         2016-11-07 11:44:14 20844
 9.WAV         2016-11-07 11:44:14 25004
 P.WAV         2016-11-07 11:44:14 21804

Notes :

 - I am using an Atmega328P @ 8MHz with the pro mini bootloader (this may be the issue)
 - `SPI_DEFAULT_HALF_SPEED` is set to true
 - `SPI_INIT_SLOW` is set to 1

body:
So the problem was that I did not read this comment carefully

 /** SPI slave select pin. Warning: SS may be redefined as another pin
 but the hardware SS_PIN must be set to output mode before any calls to
 WaveHC functions. The SS_PIN can then be used as a general output pin */

"SS_PIN must be set to output mode before any calls to
WaveHC functions"

I read this and thought that meant whatever pin was being used as the SS pin needed to be an output, but it meant literally that pin 10 (the hardware SS pin) had to be set as an output regardless of whether it was being used or not.

So the solution is to add

 pinMode(10, OUTPUT);
to anywhere in the code

Edit : also thanks @per1234 for pointing out the correct answer, I just didn't read your comment properly.


message:
Sim900 error on AT command AT+HTTPINIT

I want to send data to my php server using sim900 module but I am unable to initialize http service on sim900.

code:

    #include <SoftwareSerial.h>
    SoftwareSerial gprsSerial(8, 9);

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

      Serial.println("Con");
      delay(2000);
      Serial.println("Done!...");
      gprsSerial.flush();
      Serial.flush();

      // See if the SIM900 is ready
      gprsSerial.println("AT");
      delay(1000);
      toSerial();

      // SIM card inserted and unlocked?
      gprsSerial.println("AT+CPIN?");
      delay(1000);
      toSerial();

      // Is the SIM card registered?
      gprsSerial.println("AT+CREG?");
      delay(1000);
      toSerial();

      // Is GPRS attached?
      gprsSerial.println("AT+CGATT?");
      delay(1000);
      toSerial();

      // Check signal strength
      gprsSerial.println("AT+CSQ ");
      delay(1000);
      toSerial();

      // Set connection type to GPRS
      gprsSerial.println("AT+SAPBR=3,1,\"Contype\",\"GPRS\"");
      delay(2000);
      toSerial();

      // Set the APN
      gprsSerial.println("AT+SAPBR=3,1,\"APN\",\"web\"");
      delay(2000);
      toSerial();

      // Enable GPRS
      gprsSerial.println("AT+SAPBR=1,1");
      delay(10000);
      toSerial();

      // Check to see if connection is correct and get your IP address
      gprsSerial.println("AT+SAPBR=2,1");
      delay(2000);
      toSerial();

    }

    void loop()
    {
       // initialize http service
       gprsSerial.println("AT+HTTPINIT");
       delay(2000);
       toSerial();

       // set http param value
       // ToDO : send dynamic value
       gprsSerial.println("AT+HTTPPARA=\"URL\",\"http://www.fohoraayo.000webhostapp.com/?lat=1111&lon=1111\"");
       delay(4000);
       toSerial();

       // set http action type 0 = GET, 1 = POST, 2 = HEAD
       gprsSerial.println("AT+HTTPACTION=0");
       delay(6000);
       toSerial();

       // read server response
       gprsSerial.println("AT+HTTPREAD");
       delay(1000);
       toSerial();

       //gprsSerial.println("");
       gprsSerial.println("AT+HTTPTERM");
       toSerial();
       delay(300);

       gprsSerial.println("");
       delay(10000);
    }

    void toSerial()
    {
      while(gprsSerial.available()!=0)
      {
        Serial.write(gprsSerial.read());
      }
    }

output:

    Config SIM900...
    Done!...
    AT

    OK
    AT+CPIN?

    +CPIN: READY

    OK
    AT+CREG?

    +CREG: 0,1

    OK
    AT+CGATT?

    +CGATT: 1

    OK
    AT+CSQ

    +CSQ: 31,0

    OK
    AT+SAPBR=3,1,"Contype","GPRS"

    OK
    AT+SAPBR=3,1,"APN","web"

    OK
    AT+SAPBR=1,1

    ERROR
    AT+SAPBR=2,1

    +SAPBR: 1,1,"xx.xxx.x.x"

    OK
    AT+HTTPINIT

    ERROR
    AT+HTTPPARA="URL","http://www.fohoraayo.000webhostapp.com/?lat=AT+HTTPACTION=0

    ERROR
    AT+HTTPREAD

    ERROR
    AT+HTTPTERM

    ERROR

body:
For me, your code is working like charm. but change the

    gprsSerial.begin(9600)

to

    gprsSerial.begin(4800)