Tag Archives: arduino

Arduino Gas Sensor – Part 2

Previously

So I left the last article with the following:

Well apart from the hardware I need, so issues need to be addressed which may or may not require extra hardware – as I’ve just thought of them.

  • DateTime equivalent object for when I register a pulse
  • Work out how long these will last on battery
  • Can I set an interrupt to go off when a digital value hits a threshold? Or does this require analogue input? If I can it would massively save on battery as no polling! But, it may require fiddly per-house calibration, which the brute force method ignores
  • Laser/3d Printed box and some form of mounting which will let me attach to anything. Probably going to be velcro

So I’ll go through what has been done since then via this criterea.

Hardware Changes

The DateTime object style thing was achieved through an RTC module (http://www.sparkfun.com/products/99) which communicated to the ‘duino using the I2C bus and takes 5V. A microSD card shield was also added to the hardware for saving events into a simple text file (http://www.sparkfun.com/products/9802).

Rather than use my hastily build photosensor, I used a load of RFXcom sensors as they are well built and have a housing designed for sticking to the meter (Which is by far the biggest engineering challenge of this project). A board layout for interfacing with the sensor units was created and the gEDA/gSchem schematic file can be found on the git hub project page.

Software Changes

Well, apart from the stuff which interfaces with the RTC module and the microSD card, not much has changed code wise. The way the RFXcom modules work was backwards to my prototype, so I measured the time it takes to discharge a capacitor rather than charge. An LED on a meter normally flashes for .1s, so the timout is set to 0.05s.

Battery Life

Using a multimeter showed the whole sensor drew 92mA. It isn’t ideal, but with a 6 AA battery pack which packs ~3000mAH which lasts a bout a day ( :-( ) However,  that was with a ridiculously high powered infrared LED on the RFXcom board. Using just the photosensor (rather than the reflective) the power output was 42mA and that was with the SD card always powered. There is a lot of scope for battery life improvement on this project.

Source

The source can be found on my github page at https://github.com/carl-ellis/Arduino-Gas-Sensor .

Arduino Gas Meter Sensor – Part 1

Motivation

My newly ordered Arduino Uno came in the post today so I got to start building with it!

An upcoming sensing deployment needs a way of sensing gas usage, so I’m building a basic sensor to measure it. Luckily, most gas meters have an LED pulse which goes off every so often and we can measure that. The one in my house informs me the light will pulse every 10 dm^3 of gas, so every time the second number from the right on the meter ticks the light will pulse. Failing this, the 0 on the right most dial is very reflective, and an LED can be used to reflect light from it.

As the extra bits I need to finish the sensor hasn’t come yet, namely the SD card shield and a battery pack, I can’t lock the sensor in my gas cupboard and give it a test, so for the time being I’m turning off my computer screens and lights, then flashing a red head torch at it to simulate a pulse.

Code

After a bit of internet trawling, I found an ace site laying down how to do the wiring for a digital light sensor (http://www.ladyada.net/learn/sensors/cds.html#bonus_reading_photocells_without_analog_pins). From that, I added in a method which took a rolling average of the last 5 measurements and outputted if the measured light was brighter than 110% of the average (not exactly statistical, but I intend for these to be locked in a dark box…).

Here’s what I have so far:

<span style="color: #7e7e7e;">/* Based on: Photocell simple testing sketch. </span>
<span style="color: #7e7e7e;">Connect one end of photocell to power, the other end to pin 2.</span>
<span style="color: #7e7e7e;">Then connect one end of a 0.1uF capacitor from pin 2 to ground </span>
<span style="color: #7e7e7e;">For more information see www.ladyada.net/learn/sensors/cds.html */</span>

<span style="color: #7e7e7e;">// Number of measurements for averaging</span>
const <span style="color: #cc6600;">int</span> AVERAGE_LENGTH = 5;

<span style="color: #cc6600;">int</span> photocellPin = 2;     <span style="color: #7e7e7e;">// the LDR and cap are connected to pin2</span>
<span style="color: #cc6600;">int</span> photocellReading;     <span style="color: #7e7e7e;">// the digital reading</span>
<span style="color: #cc6600;">int</span> ledPin = 13;    <span style="color: #7e7e7e;">// you can just use the 'built in' LED</span>

<span style="color: #7e7e7e;">// for the circular buffer</span>
<span style="color: #cc6600;">int</span> lastReadings[AVERAGE_LENGTH];
<span style="color: #cc6600;">int</span> average = 0;
<span style="color: #cc6600;">int</span> counter = 0;

<span style="color: #cc6600;">void</span> <span style="color: #cc6600;"><strong>setup</strong></span>(<span style="color: #cc6600;">void</span>) {
  <span style="color: #7e7e7e;">// We'll send debugging information via the Serial monitor</span>
  <span style="color: #cc6600;"><strong>Serial</strong></span>.<span style="color: #cc6600;">begin</span>(9600);

  <span style="color: #7e7e7e;">// Initialise the array </span>
  <span style="color: #cc6600;">for</span>(<span style="color: #cc6600;">int</span> i=0;i&lt;AVERAGE_LENGTH;i++) {
    lastReadings[i] = 0;
  }   
}

<span style="color: #cc6600;">void</span> <span style="color: #cc6600;"><strong>loop</strong></span>(<span style="color: #cc6600;">void</span>) {
  <span style="color: #7e7e7e;">// read the resistor using the RCtime technique</span>
  photocellReading = RCtime(photocellPin);

  <span style="color: #7e7e7e;">// Calculate rolling average</span>
  ++counter %= AVERAGE_LENGTH;
  lastReadings[counter] = photocellReading;
  calcStats();
  <span style="color: #cc6600;">int</span> bound = average - (average/10);

  <span style="color: #7e7e7e;">// Glorious debug</span>
  <span style="color: #cc6600;"><strong>Serial</strong></span>.<span style="color: #cc6600;">print</span>(<span style="color: #006699;">"Av = "</span>);
  <span style="color: #cc6600;"><strong>Serial</strong></span>.<span style="color: #cc6600;">print</span>(average);
  <span style="color: #cc6600;"><strong>Serial</strong></span>.<span style="color: #cc6600;">print</span>(<span style="color: #006699;">" = ["</span>);
  <span style="color: #cc6600;">for</span>(<span style="color: #cc6600;">int</span> i=0; i&lt;AVERAGE_LENGTH;i++) {
    <span style="color: #cc6600;"><strong>Serial</strong></span>.<span style="color: #cc6600;">print</span>(lastReadings[i]);
    <span style="color: #cc6600;"><strong>Serial</strong></span>.<span style="color: #cc6600;">print</span>(<span style="color: #006699;">","</span>);
  }
  <span style="color: #cc6600;"><strong>Serial</strong></span>.<span style="color: #cc6600;">print</span>(<span style="color: #006699;">"] "</span>);
  <span style="color: #cc6600;">if</span> (photocellReading &lt; bound) {
    <span style="color: #cc6600;"><strong>Serial</strong></span>.<span style="color: #cc6600;">print</span>(<span style="color: #006699;">" . RCtime reading = "</span>);
    <span style="color: #cc6600;"><strong>Serial</strong></span>.<span style="color: #cc6600;">println</span>(photocellReading);     <span style="color: #7e7e7e;">// the raw analog reading</span>
  } <span style="color: #cc6600;">else</span> {
    <span style="color: #cc6600;"><strong>Serial</strong></span>.<span style="color: #cc6600;">println</span>();
  }

  <span style="color: #cc6600;">delay</span>(100);
}

<span style="color: #7e7e7e;">// Calculates the new mean based on the last 20 measurements </span>
<span style="color: #cc6600;">int</span> calcStats() {

  <span style="color: #7e7e7e;">// average</span>
  average = 0;
  <span style="color: #cc6600;">for</span>(<span style="color: #cc6600;">int</span> i=0;i&lt;AVERAGE_LENGTH;i++) {
    average += lastReadings[i];
  }
  average /= AVERAGE_LENGTH;
}

<span style="color: #7e7e7e;">// Uses a digital pin to measure a resistor (like an FSR or photocell!)</span>
<span style="color: #7e7e7e;">// We do this by having the resistor feed current into a capacitor and</span>
<span style="color: #7e7e7e;">// counting how long it takes to get to Vcc/2 (for most arduinos, thats 2.5V)</span>
<span style="color: #cc6600;">int</span> RCtime(<span style="color: #cc6600;">int</span> RCpin) {
  <span style="color: #cc6600;">int</span> reading = 0;  <span style="color: #7e7e7e;">// start with 0</span>

  <span style="color: #7e7e7e;">// set the pin to an output and pull to LOW (ground)</span>
  <span style="color: #cc6600;">pinMode</span>(RCpin, <span style="color: #006699;">OUTPUT</span>);
  <span style="color: #cc6600;">digitalWrite</span>(RCpin, <span style="color: #006699;">LOW</span>);

  <span style="color: #7e7e7e;">// Now set the pin to an input and...</span>
  <span style="color: #cc6600;">pinMode</span>(RCpin, <span style="color: #006699;">INPUT</span>);
  <span style="color: #cc6600;">while</span> (<span style="color: #cc6600;">digitalRead</span>(RCpin) == <span style="color: #006699;">LOW</span>) { <span style="color: #7e7e7e;">// count how long it takes to rise up to HIGH</span>
    reading++;      <span style="color: #7e7e7e;">// increment to keep track of time </span>

    <span style="color: #cc6600;">if</span> (reading == 30000) {
      <span style="color: #7e7e7e;">// if we got this far, the resistance is so high</span>
      <span style="color: #7e7e7e;">// its likely that nothing is connected! </span>
      <span style="color: #cc6600;">break</span>;           <span style="color: #7e7e7e;">// leave the loop</span>
    }
  }
  <span style="color: #7e7e7e;">// OK either we maxed out at 30000 or hopefully got a reading, return the count</span>

  <span style="color: #cc6600;">return</span> reading;
}

Next Steps

Well apart from the hardware I need, so issues need to be addressed which may or may not require extra hardware – as I’ve just thought of them.

  • DateTime equivalent object for when I register a pulse
  • Work out how long these will last on battery
  • Can I set an interrupt to go off when a digital value hits a threshold? Or does this require analogue input? If I can it would massively save on battery as no polling! But, it may require fiddly per-house calibration, which the brute force method ignores
  • Laser/3d Printed box and some form of mounting which will let me attach to anything. Probably going to be velcro.

Here’s a video of it working: