Definition

pid·dle [pid-l] verb, pid·dled, pid·dling.

To spend time in a wasteful, trifling, or ineffective way; dawdle (often followed by around ): He wasted the day piddling around.

Sunday, December 2, 2012

Arduino Based Temperature Sensor

Overview

I mentioned quite some time ago that I had ordered an Arduino UNO to play around with.  From looking at the left over parts I had laying around I got the idea to throw together a quick and dirty temperature monitor using a couple seven segment displays and a thermistor.  After many months I finally got around to actually completing this and documenting it.  One of the things I wanted to do, even thought I didn't really have to, was document the project using Fritzing.  In an earlier post I showed how to make a custom seven segment display so I continued using Fritzing to complete the breadboard layout and schematic.  

After reading through this project, my hope is that you will get a better understanding of how to:
  • Control multiple LEDs with a minimum number of micro-controller pins
  • Take a multiple digit number and split it into individual digits for display
  • Display two different numbers using the same control lines

Reference Material

Before reading the rest of this post, I would recommend that you jump over to the following links to gather some background information.  My program uses ideas and methods that are found in the following tutorials.

Hardware

This temperature sensor is made with some fairly simple components but provides a nice example of monitoring a simple input and displaying the appropriate output on a simple LED display.  With the exception of the thermistor, most of these parts are readily available at your local Radio Shack.

  • 2 Common Cathode 7 Segment Displays
  • 2 NPN Transistors
  • 7 Resistors (I used 220 Ohm - doesn't have to be exact)
  • 1 Resistor (10 K Ohm for thermistor voltage divider circuit)
  • 1 NTC Thermistor
This project was built up and prototyped on a breadboard.  Just for documentation purposes I built up a model of it in Fritzing.  A screenshot of the board is shown below.  I tried to use different color wires to denote the different functions of the signals.  The yellow wires are the digit select lines, the green wires are to drive the segments of the display, and the gray wire is the thermistor input.


A schematic of the design is shown below for reference as well.

Software

Most of the software is heavily re-used from the tutorials I linked to at the beginning of the posting.  However, the main loop is a little bit unique.  The idea behind this program is that it will read the thermistor, determine the temperature, and then display it on the two 7 segment displays.  One thing you may notice from the hardware section is the each display shares the same anode connections at the Arduino.  The benefit in this type of arrangement is that you only need one incremental pin to drive a new 7 segment display.  The downside is that only one display can be active at a time since the individual LED activated will be present on all displays.  So if you want to show a number, such as 19 on the two displays the ideas is that you set the LEDs to show a 1, then activate the first display for a few milliseconds.  Next you turn off the first display, set the LEDs to display a 9 and then activate the second display for a few milliseconds.  As long as you repeat this procedure quickly enough the human eye will not perceive a blink and it will look like a smooth, consistent digit display.

The full listing is shown below for reference.


#include <math.h>

void setup() 
{
  pinMode(10, OUTPUT);  // Segment C, Pin 7
  pinMode(9, OUTPUT);  // Segment G, Pin 1
  pinMode(8, OUTPUT);  // Segment B, Pin 9
  pinMode(7, OUTPUT);  // Segment D, Pin 5
  pinMode(6, OUTPUT);  // Segment F, Pin 2
  pinMode(5, OUTPUT);  // Segment A, Pin 10
  pinMode(4, OUTPUT);  // Segment E, Pin 4
  pinMode(3, OUTPUT);  // Display 2 
  pinMode(2, OUTPUT);  // Display 1

}

void Zero() // A, B, C, D, E, F
{
  digitalWrite(5, HIGH);  // Segment A
  digitalWrite(8, HIGH);  // Segment B
  digitalWrite(10, HIGH);  // Segment C
  digitalWrite(7, HIGH);  // Segment D
  digitalWrite(4, HIGH);  // Segment E
  digitalWrite(6, HIGH);  // Segment F
  digitalWrite(9, LOW);  // Segment G
}

void One()  // B, C
{
  digitalWrite(8, HIGH);  // Segment B
  digitalWrite(10, HIGH);  // Segment C
  digitalWrite(5, LOW);  // Segment A
  digitalWrite(7, LOW);  // Segment D
  digitalWrite(4, LOW);  // Segment E
  digitalWrite(6, LOW);  // Segment F
  digitalWrite(9, LOW);  // Segment G
}

void Two() // A, B, D, E, G
{
  digitalWrite(5, HIGH);  // Segment A
  digitalWrite(8, HIGH);  // Segment B
  digitalWrite(7, HIGH);  // Segment D
  digitalWrite(4, HIGH);  // Segment E
  digitalWrite(9, HIGH);  // Segment G
  digitalWrite(10, LOW);  // Segment C
  digitalWrite(6, LOW);  // Segment F
}

void Three() // A, B, C, D, G
{
  digitalWrite(5, HIGH);  // Segment A
  digitalWrite(8, HIGH);  // Segment B
  digitalWrite(10, HIGH);  // Segment C
  digitalWrite(7, HIGH);  // Segment D
  digitalWrite(9, HIGH);  // Segment G  
  digitalWrite(4, LOW);  // Segment E
  digitalWrite(6, LOW);  // Segment F
}

void Four() // B, C, F, G
{
  digitalWrite(8, HIGH);  // Segment B
  digitalWrite(10, HIGH);  // Segment C
  digitalWrite(6, HIGH);  // Segment F
  digitalWrite(9, HIGH);  // Segment G
  digitalWrite(5, LOW);  // Segment A
  digitalWrite(7, LOW);  // Segment D
  digitalWrite(4, LOW);  // Segment E
}

void Five() // A, C, D, F, G
{
  digitalWrite(5, HIGH);  // Segment A
  digitalWrite(10, HIGH);  // Segment C
  digitalWrite(7, HIGH);  // Segment D
  digitalWrite(6, HIGH);  // Segment F
  digitalWrite(9, HIGH);  // Segment G
  digitalWrite(8, LOW);  // Segment B
  digitalWrite(4, LOW);  // Segment E
}

void Six() // A, C, D, E, F, G
{
  digitalWrite(5, HIGH);  // Segment A
  digitalWrite(10, HIGH);  // Segment C
  digitalWrite(7, HIGH);  // Segment D
  digitalWrite(4, HIGH);  // Segment E
  digitalWrite(6, HIGH);  // Segment F
  digitalWrite(9, HIGH);  // Segment G
  digitalWrite(8, LOW);  // Segment B
}

void Seven() // A, B, C
{
  digitalWrite(5, HIGH);  // Segment A
  digitalWrite(8, HIGH);  // Segment B
  digitalWrite(10, HIGH);  // Segment C
  digitalWrite(7, LOW);  // Segment D
  digitalWrite(4, LOW);  // Segment E
  digitalWrite(6, LOW);  // Segment F
  digitalWrite(9, LOW);  // Segment G
}

void Eight() // A, B, C, D, E, F, G
{
  digitalWrite(5, HIGH);  // Segment A
  digitalWrite(8, HIGH);  // Segment B
  digitalWrite(10, HIGH);  // Segment C
  digitalWrite(7, HIGH);  // Segment D
  digitalWrite(4, HIGH);  // Segment E
  digitalWrite(6, HIGH);  // Segment F
  digitalWrite(9, HIGH);  // Segment G
}

void Nine() // A, B, C, F, G
{
  digitalWrite(5, HIGH);  // Segment A
  digitalWrite(8, HIGH);  // Segment B
  digitalWrite(10, HIGH);  // Segment C
  digitalWrite(6, HIGH);  // Segment F
  digitalWrite(9, HIGH);  // Segment G
  digitalWrite(7, LOW);  // Segment D
  digitalWrite(4, LOW);  // Segment E
}

void Blank()
{
  digitalWrite(10, LOW);  // Segment C
  digitalWrite(9, LOW);  // Segment G
  digitalWrite(8, LOW);  // Segment B
  digitalWrite(7, LOW);  // Segment D
  digitalWrite(6, LOW);  // Segment F
  digitalWrite(5, LOW);  // Segment A
  digitalWrite(4, LOW);  // Segment E
}

void displayDigit(int digit)
{
  if (digit == 0){
    Zero();
  }
  else if (digit == 1){
    One();
  }
  else if (digit == 2){
    Two();
  }
  else if (digit == 3){
    Three();
  }
  else if (digit == 4){
    Four();
  }
  else if (digit == 5){
    Five();
  }
  else if (digit == 6){
    Six();
  }
  else if (digit == 7){
    Seven();
  }
  else if (digit == 8){
    Eight();
  }
  else if (digit == 9){
    Nine();
  }
  else{
    Blank();
  }
}

double Thermistor(int RawADC){
  double Temp;
  // See http://en.wikipedia.org/wiki/Thermistor for explanation of formula
  Temp = log(((10240000/RawADC) - 10000));
  Temp = 1 / (0.001129148 + (0.000234125 * Temp) + (0.0000000876741 * Temp * Temp * Temp));
  Temp = Temp - 273.15; // Convert Kelvin to Celcius
  return Temp;
}

void loop()
{
  int count = 0;
  int displayLoop = 25;
  int digOne;
  int digTwo;
  int ThermistorInput = A0;
  int ThermistorValue = 0;
  double fTemp; // Temp in degrees Fahrenheit
  double temp;

  while(count < 10){
    // Read thermistor and determine temperature in degrees F
    temp = Thermistor(analogRead(ThermistorInput)); // Read thermistor value
    fTemp = (temp * 1.8) + 32 - 7; // Convert degrees C to F
    
    // Split two digit fTemp variable into individual digits to display
    digOne = fTemp / 10;  // Determine what to display for digit # 1
    digTwo = fTemp - digOne*10;  // Determine what to display for digit # 2

    // Alternate between displaying each digit for 10 mS 
    while (displayLoop > 0){
      digitalWrite(3, LOW);
      digitalWrite(2, HIGH);
      displayDigit(digOne);
      delay(10);

      digitalWrite(3, HIGH);
      digitalWrite(2, LOW);
      displayDigit(digTwo);

      delay(10);
      displayLoop --;
    }
    displayLoop = 250;
  }
  count = 0;  // Reset counter */
}

Sunday, March 18, 2012

Fritzing Part Creation

Creating a custom part in Fritzing requires a little bit of work but it isn't too bad if you can start with a part that is already in the library.  I can't speak to any problems that may be found if you try to create one from scratch but I would guess that the most difficult part would be creating the breadboard image.



The seven segment display that I have is a different footprint and pinout than any of the other common cathode displays that come in the standard library.  I used these basic steps:

  • Select the part that is closest to yours
  • Select the Part >  Edit menu item
  • Load the newly created images for the schematic and PCB views
  • Update connector settings
  • Save as a new part
Really the only one of these items that was tricky is creating the image for the PCB view.  This is because the layers of the SVG file are what denotes the layers that get associated with the PCB layers.  Each pin in the SVG image has to be named ConnectorX, where the X is the number of the pin.  Then all of those are grouped together and the group named Copper1, then another group is created which includes the same items and named as Copper0.  Also a silkscreen shape can be added as the final layer as well.  I'm sure this sounds quite confusing but if you open the SVG file of an existing part, ungroup each layer, and view the object properties you can see how the existing library parts are labeled.  A little tip for arranging your pins and getting the spacing right  when using Inkscape - I used the "straight line" tool to draw little guide bars to check spacing.  Also, Inkscape has the ability to align shapes so you can select a row of pins and align them to each other's middle to assure your pins are in a straight row.



One hiccup I had was that for some reason when the part was created an I.D. for the silkscreen layer was not created in the Fritzing part file.  The .fzp files can be edited with a text editor and per the advice of a developer on the Fritzing forums I manually added a line to the file which defined the silkscreen layer.

Throughout this process I asked a few questions on the Inkscape forums and the developers there always respond very quickly.  They did mention that the part creator will be re-vamped in future versions so perhaps it will be possible to do all of this from within Fritzing in the future. 

Friday, March 2, 2012

Fritzing

So I looked around my random parts box trying to decide what to make with the Arduino board.  I had a couple segmented LED displays so I thought I would try to make up a little temperature gauge using a thermistor to read the temp and display.

I figured this would be a good time to play around with Fritzing and plan the breadboard and make up a little schematic for reference.  Things were going pretty well and the tool works quite nicely - I started out just grabbing a few parts and placing them to see how things snap into the breadboard sockets and how the wires connect up.  From my experience it seemed easier to me to make connections on the breadboard view.  When trying to make connections on the schematic view, the "wire" mode was kind of finicky and it took several attempts to get the cursor in just the right position.

Once I was familiar with the basics of the program I went to actually create a decent representation of my design and hit a roadblock - the old displays I have from Radio Shack are not in their parts library.  That sent me off on a quest to figure out how to add parts to Fritzing.  It doesn't seem too difficult but I need to grab an SVG editor - I plan on using Inkscape since it is open source.

Looks like the build is on delay for now.  I could just skip the whole drawing and documentation aspect but there really isn't any urgency to building the project.  It would be better if I take the time and properly document things so if I want to re-build it later I'll have the information handy.

Wednesday, February 15, 2012

It's Here

So my Uno board came in the other day and I got a chance to play around with it for a few minutes and take a look at the schematic today.  At first I did not think that you could do anything with the board without wiring up some circuitry on a breadboard but there is actually one LED that is available and the blink sketch which comes as an example makes use of it.

If you go to Open > Basics > Blink it will open a sketch that turns the LED on for 1 second and then turns the LED off for one second.

Everything works very smoothly for me.  Simply plug it in and hit the "play" button to compile and download the sketch.  I did have to select the USB port that was being used but once that was done it downloaded without any issues.

It looks like really all you can do is "burn and learn" with this system - there is no debugging available to allow the setting of breakpoints, stepping, etc. so it looks like it may be difficult to figure out what is happening in more complicated systems.  However, I seem to recall that I read somewhere a debugging feature is in the works so we may get one in the near future.

Friday, February 10, 2012

Quick First Impression - Arduino IDE

So while I wait for my board to come in I am starting to get up to speed on the environment and the Arduino syntax.  This is going to sound really weird but for the life of me I could not find a screenshot of the IDE.  Of course if you really want a screenshot you can always do a google image search and find one but what I am saying is that on the general Arduiono website I don't recall seeing one so the first time I got a glimpse of the software was after I had installed it.  It looks much more like a text editor than what was expected based upon my experience with IDEs for other micro-controller platforms.  Seems to have very few panes with essentially a code editing area and then a status output below.  I'm not saying that is a bad thing, just different.  It makes me wonder how you manage multiple files in a project in order to bring in the libraries you create, etc.

Below is an obligatory screenshot of an example opened in the editor window.


Tuesday, February 7, 2012

Decisions, Decisions

So I sit down to order an Arduino board and there are a lot of different options.  Not only in the various types of boards but also there are a lot of different places to order them from.  Let's take a look at what I have found.

The hardware section of the official Arduino website shows many board assemblies.  Uno, LilyPad, Mega, Fio, Nano, and that isn't event getting into the shields.  So what are the differences and where should a beginner start?  One basic thing to remember is:

  • Arduino boards are sort of "mother" boards which hold the micro-controller and the support circuitry needed to program and run your application.
  • Arduino shields are a sort of "daughter" card which add functionality and interface to the connectors on the Arduino board.
I decided that starting with the Uno seemed to be the best choice.  From what I can tell it seems to be the best entry level board.  However, there now comes a second dilemma - which version of the Uno should I get?  It is now up to rev 3 and it seems that you pay a premium in order to get the latest hardware.  From what I found at various online retailers the Rev 3 boards about $3 more than the prior Uno generation.  While you do get some hardware improvements they did not seem to justify the few extra dollars cost to me.  On a somewhat related not, you could also purchase the Duemilanove version, which is nearly identical to the Uno for about $0.65 less.  But to me it was worth the extra few cents to get the Uno.

So now my hardware is in the mail and I guess the next step is to get the development environment installed while I wait.  If you have made it this far, thanks for reading!