9 Jan 2011

Arduino Lightmeter - the code

As you can see, the program is very short. an explanation follows the code:


#include LiquidCrystal lcd(13, 12, 5, 4, 3, 0);


void setup() {
  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
  pinMode(0,INPUT);
  pinMode(1,INPUT);
  // Print a message to the LCD.
}


int sensor1Value, sensor2Value;
void loop() {
  if(digitalRead(1)){sensor1Value = analogRead(A0);} // read the switch, overwrite stored LDR value
  if(digitalRead(2)){sensor2Value = analogRead(A0);} // read the switch, overwrite stored LDR value
  lcd.setCursor(0, 0); // set the cursor to first line
  lcd.print("s1: ");
  lcd.print((int) (sensor1Value*(10000.00/1023.00)), DEC);
  lcd.setCursor(0, 1); // set the cursor to next line
  lcd.print("s2: ");
  lcd.print((int) (sensor2Value*(10000.00/1023.00)), DEC);
  delay(100); // the delay slows down the refresh of the display (lcd.clear in the loop) to improve readability.
 } 


First of all, we need to include the LiquidCrystal library to give us access to the functions some other altruistic geek has written for us. Immediately following that - and outside of main() and loop(), so that it is in the global scope (it can be accessed from anywhere) - the instance of lcd is initialised with the output pins used on the Arduino, so we don't need to set them later. If you look at the numbers here, you'll see they correspond to the digital pins connected to on the Arduino board. There's no magic in which numbers to use - they're just like that to show that you can use whichever pins you want and that control lies within the sketch. 


In setup we call begin on lcd which defines the number of columns and rows in the display. Next we tell the Arduino that we'll be using pins 1 & 2 for input - these are the push-switches. Remember that the lcd library set the outputs for the display so we don't need to.


Again in the global scope, so that they don't get redefined by every iteration of loop(), we declare the variables sensor1Value and sensor2Value.

Now onto loop() - the centre of operations:

if(digitalRead(1)){sensor1Value = analogRead(A0);}
this instruction says, "If the switch on pin 1 is pressed, overwrite the value in sensor1Value with the new value read from analogue input 0 (A0) by function analogRead(). The following line does the same for the switch on pin 2.


The remainder of the sketch is concerned with writing the information to the display.
First we need to clear the display to avoid interference from previously written data. Then we construct the string to write for each line of the display. s1: and s2: correspond to the switches. The calculation converts the digital value into something vaguely meaningful. The Arduino can measure an analogue input in 1024 steps. I was playing with the pull-down value on the LDR, so I divided that by 1024 to give a value to each step. I don't remember what the meaning was, though.  Anyway, we multiply that by the measured input and print it to the display. Finally, I added a delay because I was getting some flicker.


Please try this out and let me know how you get on! If you're feeling nerdy you could even buy a shirt or hoody from RedBubble and make me a little money.

3 Jan 2011

Arduino Light Meter

Well, this is the layout for the lightmeter as it stands. I created the image using Fritzing which is a great application for virtual breadboarding. It'll also produce circuit diagrams and printed circuit boards (PCB) from your layout, although it's early days and the results can be a bit interesting.


If I've made any mistakes in the wiring, I'm sorry. Let me know and I'll correct it. And don't hold me responsible if you maim or kill yourself (or anything else) -  I'm not offering this as instructions or a tutorial.

That said, the voltages and currents here are pretty small (5volts or less) and even if you wire it wrong, you're unlikely to damage anything. Do be careful, though, of polarities i.e. positive (+ve / 3.3v / 5v ) and ground (GND or 0v).

The circuit has three main parts and they are grouped as such on the breadboard (the big white thing at the bottom).

  1. At the left are two switches that are tied to GND through the resistors and feed into digital 1 & 2. Press one of these switches and it will read the value of the LDR and store it in one of two variables. This will let me use the same LDR to measure dark areas and light areas.
  2. The central section is the LDR. Again it is tied to GND through a resistor and this time feeds into analogue 0.
  3. The right hand section includes the LCD (the green thing above the big white thing) appears to be the most complex, but it's just a lot of wiring. The little bit on the breadboard is a preset (or trimmer) variable resistor used to adjust the contrast of the display. There is also a resistor there which serves to drop the voltage to a safer 2v for the LED illumination that the LCD uses. More about that later.
If you're wondering what the blue thing is, that's the Arduino. It even says so. It's virtually identical in colour and layout to my real Uno.

Now, some explanation about a couple of things:

There is an explanation of breadboarding here, but basically, the two tracks at the top and bottom are linked horizontally and are normally used for power (and ground) rails. The central section has tracks that are linked vertically and this is where we build the circuits.

I've wired the LCD into a hotchpotch of inputs. It doesn't really matter which you use so long as they are reflected in the code, which we'll look at later.

Where I've tied something to GND through a resistor, that is because if there is no definite state on an input, the Arduino can't make up its mind how to read it and the result can be erratic. 'Pulling it down' to ground gives it a definite default off state. You can also 'Pull up' to a voltage, say the 5v rail, in which case it would have a definite default on state. Think of it like a door. With a closer spring, the door will be closed unless it is held open. Without the spring it will be however it was left: open, closed or part-open.

That's all for now. Next time I'll look at the code, explain how it works and think about improvements.

Getting to Grips with the Arduino

There are plenty of Arduino tutorials out there - try the Arduino website, LadyAda and, of course, Google. I don't plan to add to them.

The ubiquitous "Hello, World!" application is a blinking LED. Typically it blinks the onboard LED. If you're really daring you can plug in an external LED and make that blink. Right. As I said before, my kit (should have) shipped with 60 LEDs. I can't get excited about making LEDs flash whether it's one or sixty, yellow, red or blue. If I want a flashing LED, I'll buy one - it's way cheaper.

A lot of the tutorials build on the flashing/fading LED for several chapters. Unless you are obsessed with them or need simple concepts repeatedly driven home, I'd suggest you skip these chapters and start doing real stuff.

Fortunately for me, the LEDs and resistors had been omitted from my kit, so I was left with the handful of components I had kicking around - one LED, some switches, three resistors of mixed value, a servo, some variable resistors and a couple of LDRs (light dependent resistors).  Oh, and an LCD display I ordered with the kit (about £3.00). Time to get creative!

I said I wanted to make an enlarger timer and controller for photography. A really useful add-on to that would be an exposure meter that I could use to measure the darkness of the darks and the lightness of the lights to calculate the contrast as well as the exposure.

I've built the first bit and it only took about an hour! To achieve this I combined three tutorials from the Arduino website and hacked the sketch (the Arduino world's word for a program) a little. The tutorials are:
  • AnalogReadSerial - reads the value of an analog (non-digital) input, in my case the LDR.
  • Button - reads the state of a digital input. Possibilities are ON or OFF.
  • LiquidCrystal - uses library code to interface to an LCD display.
A light dependent resistor (LDR) normally has a high resistance. As light shines on them, the resistance drops by a known amount. Measuring the drop tells us the relative light intensity. There're some nice pictures here.

It's easier to understand the concept of analogue inputs if you first understand digital! As you probably know, computers work with ones and zeros. One equates to on or true, zero equates to off or false. That doesn't give us a lot to work with. It's okay for a switch, so we configure that as a digital input, but the LDR (which you can also think of, for these purposes, as a variable resistor or potentiomer) has a whole range of 'on' values. We need to take the value and convert it to a digital value. The Arduino cleverly does this for us using a built-in A/D (analogue-to-digital) converter. It represents the value as a number between 0 and 1023. If you have a 10k potentiometer, it'll measure in steps of about ten ohms.

Finally, liquid crystal displays (LCDs) are commonly used in calculators etc. They're more complex than switches and variable resitors so here we introduce the concept of libraries. A library is a bunch of code and functions that someone has written to deal with a specific situation - in this case LCDs. By including the library at the beginning of our sketch, we gain access to all those extra functions.

That's enough for now. Next time I'm going to include the circuit I came up with and the sketch.