Saturday, March 28, 2015

Sparkfun Proto Screw Shield

Today I got a package from Sparkfun that included a Raspberry Pi 2, a couple of MOSFETS, some right angled breakaway headers, and a Proto Screw Shield kit. This shield makes it very easy to connect sensors to the Arduino, and still be able to stack additional shields on top of this one. There is quite a bit of room to put additional components on this board as well. The kit has to be assembled, which takes about 15 minutes, and is easy to do. There is a good tutorial for this at https://www.sparkfun.com/tutorials/266

Wifi with the WizFi210 module

I'm playing with a new wifi module today from WizNet, the WizFi210. I have mine mounted on a test board that has 9 pin rs-232, usb, and TTL Serial interfaces. There is an Arduino shield available as well. This is a inexpensive wifi board that can be used for many applications, from smart appliances to wireless sensor monitoring. For ease of testing and prototyping, the test board or the shield are a necessity.

The wifi module itself is the square board on the right end of the test board, covered in metal, with the antenna attached. There is a version with on board chip antenna as well. I'll be documenting the setup and Arduino sketches necessary for communicating with this device, as well as it's applicability to working with a Raspberry Pi. Stay tuned!

Arduino Library

  • Single band 2.4GHz IEEE802.11b Wi-Fi module
  • Host Interface : UART & SPI
  • Quick booting time : under 20msec
  • Ultra low power through dynamic power management (34μA at the standby mode)
  • Security protocols : WEP, WPA/WPA2-PSK, Enterprise (EAP-FAST, EAP-TLS, EAP-TTLS, PEAP)
  • Operation temperature : -40 ~ 85
  • CE, FCC, KCC, TELEC certified
  • Dimension : 32 x 23.5 x 2.9(mm)
  • Provides chip antenna mounted version

Wednesday, March 25, 2015

The Arduino APRS Journey

We are investigating adding APRS abilities to our DIY Weather Stations. Automatic Packet Reporting System (APRS) is an amateur radio-based system for real time tactical digital communications of information of immediate value in the local area. In addition, all such data are ingested into the APRS Internet System (APRS-IS) and distributed globally for ubiquitous and immediate access. Along with messages, alerts, announcements, and bulletins, the most visible aspect of APRS is its map display. Anyone may place any object or information on his or her map, and it is distributed to all maps of all users in the local RF network or monitoring the area via the Internet. Any station, radio, or object that has an attached GPS is automatically tracked. Other prominent map features are weather stations, alerts and objects and other map-related amateur radio volunteer activities including Search and Rescue and signal direction finding.

Our friend Stanley has already been down this path, and reported on the various available options already out there, and why he went with his own open source solution. Good work Stanley! - http://9w2svt.blogspot.com/2014/07/building-open-source-arduino-aprs.html

We will be building upon his excellent foundation for our work. Thank you to Bob Bruninga (WB4APR) for developing this technology.

The new Lightning Sensor project has been finished. We now report Temperature, Humidity, calculate Heat Index and Dew Point, UV Index, Distance to Lightning strikes, and very soon radiation levels. Wind Speed / Direction (with wind chill) and rainfall amounts are coming online soon. Everything you need for your off grid weather station. Contact us if you are interested in building your own weather station, or want an assembled unit.

Monday, March 16, 2015

SD Card Datalogging with the DHT22 Temp Humidity Sensor

We were asked to do a tutorial explaining how to do logging with the DHT22 Temperature Humidity Sensor. This is a little tricky, as the sensor outputs floats, and we send strings to the SD card, I've put together a float to string feature to help with this. Please see our previous tutorials on how to connect the DHT22, and how to connect a SD card module. If you are able to get that to run, then you are ready for this tutorial.

Use checkout code "steveics", and get a 15% discount on the sensors!

Code: steveics Discount Amount: 15% Max Use: 1 No Min Order Started Date: 16th Mar, 2015 Ended Date: 16th May, 2015

Here is the sketch for the logging feature. It reads the DHT22, converts the floats to strings, and writes the comma delimited data to the SD card. Video is below!


#include<stdlib.h>

#include "DHT.h"

#define DHTPIN 7     // what pin we're connected to
#define DHTTYPE DHT22   // DHT 22  (AM2302)
DHT dht(DHTPIN, DHTTYPE);


#include <SPI.h>
#include <SD.h>

const int chipSelect = 10;

void setup()
{
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }


  Serial.print("Initializing SD card...");
  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
  pinMode(10, OUTPUT);

  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    return;
  }
  Serial.println("card initialized.");
  
  Serial.println("DHTxx test!");
 
  dht.begin();
}

void loop()
{
  
    // Wait a few seconds between measurements.
  delay(2000);

  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht.readHumidity();
  // Read temperature as Celsius
  float t = dht.readTemperature();
  // Read temperature as Fahrenheit
  float f = dht.readTemperature(true);
  
  // Check if any reads failed and exit early (to try again).
  if (isnan(h) || isnan(t) || isnan(f)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }

  // Compute heat index
  // Must send in temp in Fahrenheit!
  float hi = dht.computeHeatIndex(f, h);

  Serial.print("Humidity: "); 
  Serial.print(h);
  Serial.print(" %\t");
  Serial.print("Temperature: "); 
  Serial.print(f);
  Serial.println(" *F\t");

  
  
  
  // make a string for assembling the data to log:
  String dataString = "";



char buffer[10];  
String stringH = dtostrf(h,6,2,buffer);  
dataString = stringH;
dataString += ",";
String stringF = dtostrf(f,6,2,buffer); 
dataString += stringF;

  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  File dataFile = SD.open("datalog.txt", FILE_WRITE);

  // if the file is available, write to it:
  if (dataFile) {
    dataFile.println(dataString);
    dataFile.close();
    // print to the serial port too:
    Serial.println(dataString);
  }
  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening datalog.txt");
  }
}






Saturday, March 14, 2015

IC Station MicroSD Card Module

This tutorial will help you get the IC Station Micro SD Card Module up and running. This is ideal for recording data from sensors for future analysis. This is a 5v piece, where commonly sd card modules are 3.3v.

The right angle header that comes pre soldered isn't long enough to sit in our standard breadboard, so we used a mini breadboard where the card can hang off the side. You can also use male to female jumpers.


Use checkout code "steveics", and get a 15% discount on the sensors!

Code: steveics Discount Amount: 15% Max Use: 1 No Min Order Started Date: 16th Mar, 2015 Ended Date: 16th May, 2015

The connections are as follows:


 ** MOSI - pin 11 on Arduino Uno/Duemilanove/Diecimila
 ** MISO - pin 12 on Arduino Uno/Duemilanove/Diecimila
 ** CLK - pin 13 on Arduino Uno/Duemilanove/Diecimila
 ** CS - pin 10 on Arduino Uno/Duemilanove/Diecimila. You can change this one.

Connect GND to Arduino GND and VCC to Arduino +5v.

Insert a fat32 formatted micro sd card.

No libraries have to be downloaded or installed, as the Arduino IDE comes pre configured with the SD Card libraries.

Just load the example from File, Examples, SD, Card Info.

This example already comes with the Leonardo / Micro serial delay.

After uploading you should see something similar to the following:



The Arduino only reports volumes less than 2GB, even if using a larger sd card. Stay tuned for a data logging project using this and the 3 previous modules we have blogged about.

IC Station DS1307 Real Time Clock

In this tutorial, we will be using the IC Station DS1307 Real Time Clock Module. This will allow you to not only build a clock display, but add date and time stamping functions to your projects, so you know when a particular value was recorded by a sensor.


Use checkout code "steveics", and get a 15% discount on the sensors!

Code: steveics Discount Amount: 15% Max Use: 1 No Min Order Started Date: 16th Mar, 2015 Ended Date: 16th May, 2015

This module does not include a battery, or the pin headers. You will need to order those:

LI2032 (rechargeable, non-rechargeable CR2032 will also work)
Right Angle Breakaway Headers (you can never have too many)

Solder the header to the module. I used the 5 hole side of the module. Only 4 pins are used. VCC to Arduino +5, GND to Arduino GND, SCL to Arduino SCL (A5), and SDA to Arduino SDA (A4).

You will need to download a library to use this module. I prefer the Adafruit library:

RTClib

Download and install into your IDE using the Sketch, Import Library, Add Library function.

Now load the File, Examples, RTClib-master, DS1307 example sketch.

Because we are using the Arduino Micro, we need to add the Serial delay in setup:

Serial.begin(9600);
   while (!Serial) ; //needed for Leonardo and Micro

Now you can upload to the Arduino. The time and date will be set from your computer during the compile and upload process.

When you run the Serial Monitor, you should see something similar to this:



We will show you how to use this for data logging and LCD display in a upcoming blog post.

IC Station DHT22 Temperature Humidity

This tutorial will teach you how to read temperature and humidity readings using the IC Station DHT22 Temperature & Humidity Module. Once you have those readings, you can calculate neat things like Heat Index and Dew Point, and by adding a wind speed sensor, Wind Chill.


Use checkout code "steveics", and get a 15% discount on the sensors!

Code: steveics Discount Amount: 15% Max Use: 1 No Min Order Started Date: 16th Mar, 2015 Ended Date: 16th May, 2015

Unlike the bare sensors, this one is assembled with the appropriate resistor, so there's only 3 connections. + connects to Arduino 5v or 3.3v, - to Ground, and out connects to the digital pin of your choice. We are using pin 2 per the included example.

Once again we are using an awesome library written by Adafruit:

DHT Sensor Library

Download and import into your Arduino sketchbook libraries folder using the import library feature in the IDE per our previous tutorial.

Load the example sketch DHTtester found under File, Examples, DHT Sensor Library.

Since we are using the Arduino Micro, we added the following line just after Serial.begin(9600);

  while (!Serial) ; //needed for leonardo and micro

Now upload to your Arduino and run the Serial Monitor. You should see something similar to the following:


This example already includes Metric and Standard unit display. We will be adding Dew Point calculations at a later date.






IC Station BMP180 Barometric Pressure

A while back we did a tutorial using the IC Station BMP085 Barometric Pressure Sensor. We wanted to do another tutorial using the newer BMP180, and the latest Unified Sensor Drivers from Adafruit. Another twist? We are using the Arduino Micro, which uses the Atmel ATmega32u4 like the Leonardo, instead of the ATmega328p like the UNO.

First, let's talk about the BMP180 from ICStation. You will need to solder the included header to the board. There are 5 pins, of which only 4 are needed. there is a VCC pin for 5v operation, or a 3.3 pin for 3.3v operation. GND connects to Arduino GND, SCL connects to Arduino SCL (A5), and SDA which connects to Arduino SDA (A4).


Use checkout code "steveics", and get a 15% discount on the sensors!

Code: steveics Discount Amount: 15% Max Use: 1 No Min Order Started Date: 16th Mar, 2015 Ended Date: 16th May, 2015

You will need to download and import two libraries (using the Arduino Sketch, Import Library, Add Library menu sequence). Those libraries are:

Adafruit Sensor
Adafruit BMP085 Unified

The code for a BMP085 and a BMP180 is identical. The BMP180 is a smaller, cheaper version of the older BMP085.

There is a example sketch on the File, Examples, Adafruit BMP085 menu called sensorapi. Load that into your IDE.

Because we are using the Arduino Micro, there is a small change that we have to make. This concerns the Leonardo as well. These units use the ATmega32u4 which not only is the processor, but is also the USB interface. As such, a reset not only resets the processor, but also resets the USB connection. We have to add a small delay after Serial.begin, or nothing in the Setup() will get printed to the serial monitor.

  Serial.begin(9600);

   while (!Serial) ; //needed for leonardo and micro

So, now that we have connected, and opened the example sketch, make sure you have chosen the correct board and port on the tools menu, go ahead and upload the sketch. When it says done uploading, open your Serial Monitor, and you should see something like the following:


Notice all the values are in metric (SI). I prefer US Customary (Standard) units myself, so I will probably add some conversion code to the units.

Monday, March 9, 2015

Arduino Map: Floats or Ints?

The Arduino Map function is a very useful function. It allows you to map a input range from a analog sensor to another set of values. For instance, lets say we have a fuel gauge, with a varying resistance. We do a analogRead on the variable resistor, but then we want to map that to inches of fuel (we will convert inches to volume, and volume to gallons). The problem with the map command is it only works for integers, so:

h = map(sensorValue, 0, 1023, 0, 12);

results in a number like 5 inches, which would throw off our calculations. We need to be able to handle float values, and get a fractional result. If we had a function called mapfloat, we could do the following:

h = mapfloat(sensorValue, 0, 1023, 0, 12);

and get a result of 5.87 inches, which will make our fuel gauge more accurate. But the Arduino doesn't do floats with the map command, does it? No, it does not, so we will make our own function by adding the following chunk of code after the last } in your sketch:

float mapfloat(float x, float in_min, float in_max, float out_min, float out_max)
{
 return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

now our mapfloat call will return a float that more accurately describes the amount of fuel in our tank. Remember to specify the number of decimal places in your Serial.print command:

Serial.print(h, 2);

so now the complete sketch would look something like this:

int sensorPin = 0; // select the analog input pin for the potentiometer
int sensorValue = 0; // variable to store the value coming from the sensor

float h; // variable for height of liquid
float v; // variable for volume in cu. in.
float g; // variable for gallons
float r = 3; //radius

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

}

void loop() {

sensorValue = analogRead(sensorPin);
Serial.print(sensorValue); //actual adc value
Serial.println(" ADC");
h = mapfloat(sensorValue, 171, 512, 12, 0);
Serial.print(h, 2); // fluid height (inches)
Serial.println(" inches");
v = h*PI*sq(r); // volume (cu. in.)
g= v * 0.004329; // gallons conversion
Serial.print(g, 2); // gallons
Serial.println(" gallons");
delay(5000);
}

float mapfloat(float x, float in_min, float in_max, float out_min, float out_max)
{
 return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

Sunday, March 1, 2015

Debouncing Switches

Very often we need to connect some type of mechanical switch to an Arduino as an input device. Also very often, there is mechanical slop in a switch, so the arduino sees one activation of the switch as multiple activations. This is called switch bounce. You can write code that looks at the state of the switch, saves it to a variable and waits for a short period of time and looks again to see if the button is still pressed, or you can debounce in hardware and save code space and complexity.

A digital input cannot be left floating (not connected to anything). If you are not activating the switch, it must be pulled down to LOW, or up to HIGH through a resistor. There are pullup resistors in the CPU that can be activated through the pinMode(pin, INPUT_PULLUP) command, or you can add a external resistor to the circuit.

By adding a small capacitor across the resistor, we eliminate switch bounce, as the capacitor charges during the press of the button, then slowly (from the microcontroller's point of view) discharges, enabling the microcontroller to see a single activation of the switch.

In the diagram above, if +5v is connected to the right pin, Gnd to the center, and the Signal is connected to a digital input, you have built a debounced switch in pulldown configuration, meaning the arduino will see a LOW unless the switch is pushed. If Gnd is connected to the right pin, +5v connected to the center, and the signal pin is connected to a digital input, the Arduino will read a HIGH unless the switch is pushed. The capacitor ensures only one activation is read per push.

Collaborate, and Simulate!

As part of our new technical support service, we have been using a new tool called 123circuits. It's an online circuit and arduino sketch simulator that allowed us to have multiple users online and sharing the same virtual breadboard and arduino. We were able to explain the operation and configuration of a transistor vs. a MOSFET with a working sketch so the customer could see a working motor speed up and slow down according to the sketch being written. It's a very useful tool for one person, or several.


Tuesday, February 10, 2015

What's new in Arduino 1.6.0?

Ok, so there's a new IDE, big deal, right? YES!

Finally there's one build for all the different Arduino platforms, but more than that:


  • Auto sensing board type
  • Auto sensing com port
  • Auto save after compiling or uploading


and a host of minor / major bug fixes! Check it out at http://arduino.cc/en/Main/Software


Monday, February 2, 2015

WIZnet 550 IO Ethernet Module

Today we are working with the WIZnet 550 IO Module. It's a very small and inexpensive ethernet module based on the WIZnet 5500 chip, similar to the 5100 on the official Arduino Shield. It's completely compatible with the code written for the Arduino Ethernet Shield as well. This is a nice addition to a Arduino Nano or Home built Arduino compatible board that does not require the size and expense of a full shield, plus the 550 has some additional features like increased number of connections, faster performance, and a bigger buffer.

Let's get the module connected, download the drivers, and get a sketch running!

First, the connections:



J1.1 - GND (only one needed, all GND connected on module)
J1.2 - GND
J1.3 - MOSI - 11
J1.4 - MISO - 12
J1.5 - SCK - 13
J1.6 - SS - 10
J1.7 - 3.3v
J1.8 - 3.3v

J2.1 - 3.3v - Arduino 3.3v (only one needed, all 3.3v are connected)
J2.2 - RDY - 7
J2.3 - RST - Arduino Reset
J2.4 - N/C
J2.5 - INT - 2
J2.6 - GND - Arduino Gnd

This module is 5V logic friendly, but requires 3.3v input.





Now download zip from https://github.com/Wiznet/WIZ_Ethernet_Library, extract, and copy the Ethernet folder to your Sketchbook libraries folder. Make sure you get the folder for the right version of your IDE. There are instructions for uncommenting the controller you are using. It defaults to the 5500, but if you go back to your 5100 based shield, you will have to edit the 5100.h file as described at GIThub.

Load the example Ethernet WebServer sketch, enter your IP address you want to assign and MAC address as shown on the module (you can use the default IP/MAC as listed in the directions at GIT Hub if appropriate), and you are off and running. Works just like the original Arduino Shield, but better, smaller, and cheaper.
/*
  Web Server
 
 A simple web server that shows the value of the analog input pins.
 using an Arduino Wiznet Ethernet shield. 
 
 Circuit:
 * Ethernet shield attached to pins 10, 11, 12, 13
 * Analog inputs attached to pins A0 through A5 (optional)
 
 created 18 Dec 2009
 by David A. Mellis
 modified 9 Apr 2012
 by Tom Igoe
 
 */

#include <SPI.h>
#include <Ethernet.h>

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = { 
  0x00, 0x08, 0xDC, 0x1D, 0x29, 0x0B };
IPAddress ip(192,168,254,177);

// Initialize the Ethernet server library
// with the IP address and port you want to use 
// (port 80 is default for HTTP):
EthernetServer server(80);

void setup() {
 // Open serial communications and wait for port to open:
  Serial.begin(9600);
   while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }


  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip);
  server.begin();
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());
}


void loop() {
  // listen for incoming clients
  EthernetClient client = server.available();
  if (client) {
    Serial.println("new client");
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        Serial.write(c);
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connection: close");  // the connection will be closed after completion of the response
   client.println("Refresh: 5");  // refresh the page automatically every 5 sec
          client.println();
          client.println("<!DOCTYPE HTML>");
          client.println("<html>");
          // output the value of each analog input pin
          for (int analogChannel = 0; analogChannel < 6; analogChannel++) {
            int sensorReading = analogRead(analogChannel);
            client.print("analog input ");
            client.print(analogChannel);
            client.print(" is ");
            client.print(sensorReading);
            client.println("<br />");       
          }
          client.println("</html>");
          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        } 
        else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
    Serial.println("client disonnected");
  }
}

Here is the output in the browser:


Resources:
http://wizwiki.net/wiki/doku.php?id=products:wiz550io:start


Monday, January 26, 2015

SainSmart L298N Motor Controller

I got a SainSmart 4WD Robot Kit, which contains the L298N Motor Controller. There's not a lot of documentation of how to use this, and much of what exists by users of the board is just plain wrong. I put together a short tutorial (as part of a much more comprehensive robot kit manual I'm writing), on how to use this controller, and make a simple robot that goes forwards, backwards, and turns left or right.

Schematic:



Code:

//declaring the pins for the IN pins on the L298N
const int rightForwardPin = 3;
const int rightBackwardPin = 5;
const int leftBackwardPin = 6;
const int leftForwardPin = 9;

int runTime = 5000;

void setup() {
  //Stating that the pins are OUTPUT
  pinMode(rightForwardPin, OUTPUT);
  pinMode(rightBackwardPin, OUTPUT);
  pinMode(leftForwardPin, OUTPUT);
  pinMode(leftBackwardPin, OUTPUT);
  Serial.begin(9600);
}

//Looping to test the wheels of the car
void loop() {

  forward();
 
  stopCar();
 
  backward();
 
  stopCar();
 
  left();
 
  stopCar();
 
  right();
 
  stopCar();
}

//Setting the wheels to go forward by setting the forward pins to HIGH
void forward(){
  Serial.println("Forward");
  digitalWrite(rightForwardPin, HIGH);
  digitalWrite(rightBackwardPin, LOW);
  digitalWrite(leftForwardPin, HIGH);
  digitalWrite(leftBackwardPin, LOW);
  delay(runTime);
}

//Setting the wheels to go backward by setting the backward pins to HIGH
void backward(){
  Serial.println("Backward");
  digitalWrite(rightForwardPin, LOW);
  digitalWrite(rightBackwardPin, HIGH);
  digitalWrite(leftForwardPin, LOW);
  digitalWrite(leftBackwardPin, HIGH);
  delay(runTime);
}

//Setting the wheels to go right by setting the rightBackwardPin and leftForwardPin to HIGH
void right(){
  Serial.println("Right");
  digitalWrite(rightForwardPin, LOW);
  digitalWrite(rightBackwardPin, HIGH);
  digitalWrite(leftForwardPin, HIGH);
  digitalWrite(leftBackwardPin, LOW);
  delay(runTime);
}

//Setting the wheels to go left by setting the rightForwardPin and leftBackwardPin to HIGH
void left(){
  Serial.println("Left");
  digitalWrite(rightForwardPin, HIGH);
  digitalWrite(rightBackwardPin, LOW);
  digitalWrite(leftForwardPin, LOW);
  digitalWrite(leftBackwardPin, HIGH);
  delay(runTime);
}

//Setting the wheels to go stop by setting all the pins to LOW
void stopCar(){
  Serial.println("Stop");
  digitalWrite(rightForwardPin, LOW);
  digitalWrite(rightBackwardPin, LOW);
  digitalWrite(leftForwardPin, LOW);
  digitalWrite(leftBackwardPin, LOW);
  delay(1000);
}



Video:

Saturday, January 17, 2015

Optical Tachometer

A while back I discussed a IR emitter / detector pair, and talked about building a optical tachometer for determining the RPM of a fan or motor. So now I'm making good on that promise. Connect the emitter / detector as shown in the previous post, using pin 2 on the Arduino (interrupt 0). Put something reflective on one blade of the fan, or cover one half of the motor shaft with black tape, to get one trigger per revolution. We based this project on the work found at http://elimelecsarduinoprojects.blogspot.com/2013/06/measure-rpms-arduino.html.



// based on http://elimelecsarduinoprojects.blogspot.com/2013/06/measure-rpms-arduino.html
// read RPM and calculate average every then readings.
const int numreadings = 10;
int readings[numreadings];
unsigned long average = 0;
int index = 0;
unsigned long total;

volatile int rpmcount = 0;
unsigned long rpm = 0;
unsigned long lastmillis = 0;

void setup(){
 Serial.begin(9600);
 attachInterrupt(0, rpm_fan, FALLING);
}

void loop(){


 if (millis() - lastmillis >= 1000){  //Update every one second, this will be equal to reading frequency (Hz).

 detachInterrupt(0);    //Disable interrupt when calculating
 total = 0;
 readings[index] = rpmcount * 60;  // Convert frequency to RPM, note: this works for one interruption per full rotation. For two interrupts per full rotation use rpmcount * 30.

 for (int x=0; x<=9; x++){
   total = total + readings[x];
 }

 average = total / numreadings;
 rpm = average;

 rpmcount = 0; // Restart the RPM counter
 index++;
 if(index >= numreadings){
  index=0;
 }


if (millis() > 11000){  // wait for RPMs average to get stable

 Serial.print(" RPM = ");
 Serial.println(rpm);
}

 lastmillis = millis(); // Update lastmillis
  attachInterrupt(0, rpm_fan, FALLING); //enable interrupt
  }
}


void rpm_fan(){ // this code will be executed every time the interrupt 0 (pin2) gets low.
  rpmcount++;
}