loading
Build a nice looking LCD display with buttons for mounting on the wall.


Key Features:
2 line by 24 character LCD display controlled with 4 I/O’s (74HC164).
Back light control of LCD.
6 Buttons connected to 1 analog pin.
LM335 and LM334Z temp sensors.
Adjustable temperature offset.
Simple software clock.
Wall mounted in a picture frame.

Step 1:

Many times I have gone to a lot of trouble to build a project and when it comes time to have a display somewhere the stuff I put on the wall is less than appreciated by those around me.
Sometimes even becoming such a point of curiosity for my youngest that it ends badly.

One day while looking at a shadow box picture frame I thought… I bet I could stuff some electronics in that. This is what I came up with. Its not in a shadow box frame but for what I have planned this works a little better.


I started by taking a look at the size of the general purpose proto board and the LCD. I knew the frame would have to be at least large enough for them. I also did not want to have any screws sticking out ( or even screw heads ) when this was finished.


Parts Lists.

Picture Frame:
1- 5X7 picture frame (dollar store).
4- Screws for the LCD
6- Buttons ( Normally open)
2- General purpose proto boards.
8- #6-32 Brass Machine Nuts.
4- #6-32 x 3 / 4 Brass Machine Screws.
1- 3 / 8 x 12 inch Smoked Acrylic sheet.
1- 8 x 10 x .093 Lexan sheet.
8- Sheet rock screws and anchors ( Mounting display ).
3- Packages Micro rare earth magnets.
4- #6 x 3 / 4 Phillips Pan Head Screws.

Electronics parts:
1- Arduino Uno
1- 24 character 2 line LCD.
1- 7805 voltage regulator.
1- LM317 adjustable voltage regulator.
1- 74HC164 serial in parallel out shift register.
1- 4N26 optical isolator.
1- 2N2222
2- 100uf capacitors
1- 10uf capacitor
3- .1uf capacitors (noise reduction)
2- infrared leds
6- Normally open buttons
14- 10K resistors.
4- 1K resistors
1- 220 Ohm resistor
2- 10K potentiometes
1- 25 Ohm resistor (2 Watt plus).

Temp sensors:
LM335 - each
2- 1K resistors

LM334Z - each
1- 220 Ohm resistor
1- 10K resistor

Jumper wires.

Tools:
Hand held drill.
Hand held cutting tool ( Dremel ).
Pack Number 409 Cutting Wheels ( Dremel ).
Acrylic Cutting Knife.
Screw Driver.
Dust Mask.
C Clamps.
Scrap Piece of wood.
Paper towels.
Solder Iron.
Solder.
Glue.
Round File.
Flat File.
Assorted Drill Bits.
150 Grit Sand Paper.
Square.
Metal straight edge.

Step 2:

I laid out how I wanted the LCD and buttons on the proto board, marked them up with a pencil and cut the hole for the LCD.

I wanted a pretty snug fit for the LCD but kept a little wiggle room too.

Step 3:

I removed the small metal tabs that hold the glass in place.
I used the removed piece of glass to mark up the piece of 1 / 4 smoked acrylic for cutting.

The acrylic cutting knife is extremely sharp. Be very careful. Gloves and a well lit work space are important. Place a piece of scrap wood under the acrylic while you are cutting. Use a metal straight edge to make your cuts and drag the knife clear off the sheet. It takes quite a few passed before the acrylic is ready to be snapped off. The 1 / 4 sheet took about 60 passes.

Step 4:

Once the 1 / 4 Acrylic is cut out test fit it into the frame.

I left a little wiggle room here so the frame could be adjusted for level once it was on the wall.


Step 5:

Check your buttons to see what size drill bit you will need to make a hole.

I have square buttons so I had to file out square holes.

I place my proto board on the piece of acrylic to figure out where I want to have it.
Square it up and mark it.

I first thought I would drill holes behind where the buttons would be mounted and use the proto board as a template for them too.
It turns out I had drilled the holes too big for the legs of the buttons to work so I moved them down.
The good thing about that is it makes the buttons more centered in the frame and it gave me some holes to practice filing squares.

Take your pencil and stick it through the holes in the proto board where you want the buttons to make some little dots. These will be the markings you will use to line up for drilling the initial holes for the buttons.

Check to see how it all looks in the frame before you drill anything.

If you want to make some changes this is the time to do it.

Step 6:

I used a small drill bit ( 1 / 16 ) to make a pilot hole all the way through the Smoked Acrylic sheet for each button.

Follow the pilot hole with a 3 / 16 to make sure you are still in good shape.

Finish up the hole with a 1 / 4 drill bit.

Step 7:

I used two different files to finish the holes for my buttons.
One was round the other shaped like a triangle with edges roughly 1/ 4 inch wide.

Place the buttons on the proto board and test fit it to the Smoked Acrylic sheet.

Step 8:

Drill holes for the corners of the proto board and the one in the center of the button row only half way through.

Remove the paper covering and marvel at how awesome this is starting to look in the picture frame.

Step 9:

The buttons will be pressed now and then so I decided there would need to be some screws close by to keep the board from flexing. I drilled three 3 / 32 holes to accept some screws. Drill the holes about half way through. I didn’t watch as closely as I should have on one of the outside holes and went through. I drilled the other outside one through to match.

Gotta have symmetry.

If you notice the pads on the proto board are facing the wrong direction for soldering parts to it. Not only that but how would they fit? I will be adding another proto board for my electronics. First I needed a place to mount screws so this will be mountable to the wall.

I needed something sturdy I could run screws through to mount this securely to the wall. I had a sheet of Lexan hanging around so I decided to use that.
I took the .093 sheet and placed it on the back of the frame to mark where I wanted to cut. Get the Acrylic knife and cut it out.
Place the proto board minus the LCD in the picture frame. Place the cut sheet on the back of the picture frame again to be sure your cutting was good. Mark around the outside of the proto board and leave space for the screws in the corners of the proto board.

I tried using the Acrylic Knife to cut out the inside at first. As you can see from the picture that was a little difficult. I then changed to the Dremel tool with No. 409 cutting wheel. That worked well.

Step 10:

Remove the plastic covering the Lexan.

Mark where you want to have the screws on the back of the picture frame and the corners of the proto board.

Place the Lexan back on the picture frame and mark the screw locations there too. I also placed an extra mark in the middle so I would remember which side was to be the top.

Step 11:

Drill 1 / 4 inch holes through the Lexan for mounting to the wall and for securing the display board.

The #6 phillips pan head screws I had were long enough to go clear through the 1 / 4 smoked acrylic so I used some heavy wire cutters to trim them to length. The Dremel works well for this too.

Place the clear Lexan on the back again and secure it to the 1 / 4 acrylic and proto board with one #6 screw. Mark the bottom angles on the proto board. Remove the screw and the clear Lexan so the brass nuts can be placed and soldered.

Step 12:

I took the four #6 brass nuts and placed them on the proto board so they can be soldered into place.

I found that if they were aligned so there was one proto board hole seen through the middle of the nut it was easy to align for drilling the board that will go on top.

Tack them into place and be sure they have not moved.

If they still look good finish by soldering each pad they touch to them.

Step 13:

I wanted to have an easy way to connect the picture frame to the LCD display and still have easy access to remove it if I ever needed to.

I decided on some small rare earth magnets. The ones I used are small and they will definitely hold on to the screw heads.

I drilled some shallow 3 / 16 holes in the frame to match where the screws are going to be located.
The holes are pretty tight.
I put a small amount of gorilla glue in each hole then pressed them in as far as I could by hand.
I then flipped over the picture frame and pressed down until each was seated nicely.

Step 14: Main Schematic

Now that the picture frame part of this is ready to go its time for the electronics part of this display.

Step 15: Buttons Schematic

For most of my projects I don’t really need a full blown button set up with rows and columns.

Usually I only need a few buttons but that costs me precious I/O lines. I have much better things I want to do with my I/O’s then to have them waiting around for me to press a button.

I decided to put my buttons on an analog line.
This is what I came up with after looking at some schematics for digital to analog converters. My buttons are connected in what is referred to as a resistor ladder. The cool thing about this arrangement is that you don’t need to worry about using resistors of a certain percentage or trying to balance the difference of resistance from resistor to resistor. All of my resistors are the same value (10K).

Simple. I like that.

Step 16: Temp Sensor Schematic

I used the LM335 and the LM334Z for my temp sensors for a few reasons.

1. I had them around

2. They output a reading higher then zero volts at zero degrees celcius (That makes it a lot easier to get readings that will be below zero).

3. I wanted to get some experience with a few different temp sensors.

I put 1 LM334Z on the main board next to the heat sinks so I have an idea of how hot they are.

Step 17:

The LCD I used is a 24 charcter by 2 line display.

The back light has to be pretty bright to be able to see what is being displayed.
I used a 25 ohm wire wound resistor because it can handle the heat. I also used an LM317 adjustable voltage regulator so I could turn up the voltage to the back light until I had it where I wanted it. Because of the differing voltages I optically isolated the back light circuit from the Arduino to keep it from getting destroyed.

I think that every voltage regulator should have some kind of led to let you know it is working. The problem with a regular led in this project is that it could light this up from behind and that wouldn’t look very good. I decided to use some infrared leds because they will be visable with a camera but not to my eye. That takes care of an indicator and keeps it from being back lit where I don’t want it.

Step 18: Mounting My Aduino

I bent some pins to 90 degree angles and then bent them a little to get to the solder pads on the proto board so I could mount the Arduino right onto the back.

I then removed the pads that would be directly below the pins so there would not be an issue with shorting things.

I found it was easiest to remove the pads by soldering a piece of wire into the pad then simply pulling the wire until the pad came free.

Once I had the pads out of the way I could solder the rest of the circuit together.

Keep your wires organized and neat. It makes things a lot easier to work on if you have some problems.

Step 19: Pictures of the Stuffed Electronics

Step 20: About My Program

I set up a button configuration that runs when the board is first powered.
During button configuration you will be asked to press the buttons one at a time so the program can get a reading and set a range for each button. Any button may be used for any button number. You can also set multiple buttons to be a button. Also the buttons may be used out of order.
Button 1 sets the day of the week. Button 2 sets the hour of the day. Button 3 sets the minutes of the day. Button 4 is used with temperature offset. Button 5 subtracts from temperature offset. Button 6 adds to temperature offset.

I decided to set up the adjustment to temperature offset because I was tired of trying to match resistors between sensors to always get the same reading.
That is a pain.
Because of the ability to adjust the offset I can now use any value resistor that is close and simply adjust the offset to get the temperature close enough for me.

I don’t want to have the back light on all the time because I would like to have this blend in with the other pictures a little better. I set things up so that when any button is pressed it activates the back light for 2 minutes then turns it off.

Once it is all loaded run a test to make sure everything is working properly.

Assemble the electronics to the picture frame.

Secure it to the wall and snap on the picture frame.

Make sure to keep it level.

Now the display blends in a bit.

Sweet.

Step 21: My Program

/*

11-11-2012 Ray McQueen

LCD line 1 day and time
LCD line 2 temp readings

6 buttons on analog A0
Any button activation turns on back light for 2 minutes.
The cool part about the button config is that
  any button may be set to button 1, 2, 3, 4, 5 or 6.

LM335 and LM334Z temp sensors are used.
Temperature offset is adjustable.

*/
//
//
// Const int
//
const int lcd_datapin = 6; //  74HC164 pin 1
const int lcd_clk = 5; //  74HC164 pin 8
const int lcd_E = 4; // LCD E line
const int lcd_RS = 3; // LCD RS line
const int light = 2;// Back light output
//
// Analog stuff
//
// A0- Buttons
// A1- On board temp sensor.
// A2- Inside temp sensor.
// A3- Outside temp sensor.
//
//
//    CLOCK STUFF
//NO NEGATIVE NUMBERS
unsigned long time_begin;
unsigned long time_duration;
unsigned long time_remain;
unsigned long time_val;
unsigned int time_seconds = 0;// Stores the number of seconds
unsigned int time_minutes = 0;// Stores the number of minutes. The
// clock will start at the number of minutes stored here upon reset.
unsigned int time_hours = 12;// Stores the number of hours. The clock
// will start at the number of hours stored here upon rest.
unsigned int time_days = 0;// Stores the number of days
// Used for the counting up to a set event.
unsigned int event_seconds1 = 0;// Storage of seconds count
//
//
//LCD stuff
//
int lcd_C = 0; // Character to be shifted
int lcd_D = 0; // Character to be shifted
int lcd_N = 0; // Number of characters to send to lcd
int lcd_i = 0; // Used for looping
int lcd_set = 0;// Used to store which setup to get
int lcd_A = 0;// Used to choose the aray to use
int lcd_Z = 0; // Used in lcd char testing
//
//
//Used by cracker
//
int val1000s = 0;// Register to hold 1000 count
int val100s = 0;// Register to hold 100 count
int val10s = 0;// Register to hold 10 count
int val1s = 0;// Register for 1 count
int test_test = 0;// Register to store number for testing/time also
//
//Used for sensor readings
float sensor = 0;// Storage for sensor level
int copy = 0;// Copy of whatever I put in it/time also
//
int back_lit = 0;// Back light on/off
//
//
//
//BUTTON STUFF
int btn_read = 0;// Reading from the analog line
int btn_read2 = 0;// Copy of the reading
int btn_pressed = 0;// Button was pressed
int btn_number = 1;// Allways start with button #1
int btn_copy = 0;// Copy of button for con_fig.
int looping = 0;// For my loops
//*****************
// Store the high and low range of a buttons analog value
//
int btn_1hi;// Button #1 high range
int btn_1lo;// Button #1 low range
int btn_2hi;// Button #2 high range
int btn_2lo;// Button #2 low range
int btn_3hi;// Button #3 high range
int btn_3lo;// Button #3 low range
int btn_4hi;// Button #4 high range
int btn_4lo;// Button #4 low range
int btn_5hi;// Button #5 high range
int btn_5lo;// Button #5 low range
int btn_6hi;// Button #6 high range
int btn_6lo;// Button #6 low range
//
//
int offset_sensor_1 = 257;//  Start offset at 2.57 volts = LM334Z
int offset_sensor_2 = 273;//  Start offset at 2.73 volts
int offset_sensor_3 = 273;//  Start offset at 2.73 volts
int offset_A = 0;//  0 = No adjustments.
//                   1 = Sensor 1 adjust.
//                   2 = Sensor 2 adjust.
//                   3 = Sensor 3 adjust.
//    LM335 2.73 volts output at zero deg. C
//    LM334Z Roughly 2.57 volts output at zero deg. C
//
//
//***ARRAYS***
//  Arrays count starts at 0 not 1 and goes up
//
//  16-24 character 2 line lcd
int aray_set_up[] = {
  56, 12, 6, 1 }; // LCD setup characters
//
// Start locations for the LCD
int aray_lines[] = {
  //132 = 5th character from the left start position, line 1
  //196 = 5th character from the left start position, line 2
  //128 = line 1 
  //192 = line 2
  128, 192, 132, 196 };
//
// Uses a blank in the first location so as not to display
//  preceeding zeros.
int aray_hunds[] = {
  ' ', '1', '2', '3', '4', '5', '6', '7', '8', '9', };
//
// "0" in the first loaction so as to display
//  any precceding zero
int aray_tens[] = {
  '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', };
//
//The first array so I can put the name on the lcd at start up
// Array is only displayed at the start up.
// lcd_Z = which array to use
int aray0[] = {
  'F', 'u', 'n', ' ', 'S', 'h', 'w', 'a', 'y', ' ', 'D', 'i', 's', 'p', 'l', 'a', 'y', ' ', ' ', ' ', ' ', ' ', ' ', ' ' };
//
// Only 4 of these characters are sent but its left at 5 so no over run
int aray1[] = {
  ' ', 'I', 'n', ' ', ' ' };
// Only 4 of these characters are sent but its left at 5 so no over run
int aray2[] = {
  'O', 'u', 't', ' ', ' ' };
// Leave below for blanks
int aray3[] = {
  ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' };
// Not used yet
int aray4[] = {
  ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' };
// The word time
int aray5[] = {
  'T', 'i', 'm', 'e', ' ' };
// Not used yet
int aray6[] = {
  ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '    , ' ', ' ', ' ', ' ', ' ', ' ' };
//
// ARRAYS FOR THE DAYS OF THE WEEK
//
int aray7[] = {
  'M', 'o', 'n', ' ', ' ', ' ' };
//
int aray8[] = {
  'T', 'u', 'e', ' ', ' ', ' ' };
//
int aray9[] = {
  'W', 'e', 'd', ' ', ' ', ' ' };
//
int aray10[] = {
  'T', 'h', 'u', ' ', ' ', ' ' };
//
int aray11[] = {
  'F', 'r', 'i', ' ', ' ', ' ' };
//
int aray12[] = {
  'S', 'a', 't', ' ', ' ', ' ' };
//
int aray13[] = {
  'S', 'u', 'n', ' ', ' ', ' ' };
//
// ARRAYS FOR BUTTON CONFIG
//
int aray14[] = {
  'B', 'u', 't', 't', 'o', 'n', ' ', 'C', 'o', 'n', 'f', 'i', 'g', '.', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' };
//
int aray15[] = {
  'P', 'r', 'e', 's', 's', ' ', ' ', ' ', ' ', ' ' };
//
int aray16[] = {
  'R', 'e', 'l', 'e', 'a', 's', 'e', ' ', ' ', ' ' };
//
int aray17[] = {
  ' ', 'F', 'a', 'i', 'l', 'e', 'd', ' ', ' ', ' ' };
//
int aray18[] = {
  ' ', 'S', 'e', 't', ' ' };
//
//
//
void setup() {
  pinMode(lcd_datapin, OUTPUT); // Define as output
  pinMode(lcd_clk, OUTPUT); // Define as output
  pinMode(lcd_E, OUTPUT); // Define (the E line) as output
  pinMode(lcd_RS, OUTPUT); // Define (RS line) as output
  pinMode(light, OUTPUT); // Define (back light) as output
  //
  digitalWrite(lcd_E, HIGH);// Bring lcd control line high
  digitalWrite(lcd_RS, HIGH);// Bring lcd control line high
  //
  digitalWrite(light, LOW);// Turn on the back light for display
  //
  // LCD setup
  lcd_init();// Initialize the lcd for use
  //
  lcd_set = 0;// First line
  lcd_line();
  delay(5);
  //*** Added so line one displays start up screen ***
  //*** It only displays this once at the start up ***
  //
  lcd_Z = 0;// LCD line one character string
  lcd_N = 24;// Send all 24 characters
  lcd_char();
  //
  delay(10000);// Delay 10 seconds so I can see the program name.
  //
  // Clear the LCD line before writing to it so there is no left over
  lcd_set = 0;// LCD line one
  //
  lcd_line_clear();// Clears the lcd line to blanks
  //
  //
  // Configure the buttons on the analog line
  //  This gets done once before main loop
  //
  btn_config();// Button configuration routine.
  //
  digitalWrite(light, HIGH);// Turn off the back light for display
  event_seconds1 = 0;// Clear the seconds event register.
  back_lit = 0;// Clear the back light register.
  //
  /////////////////
  //END OF SET UP//
  /////////////////
  //
}
//
////////////////////////
//   BEGIN MAIN LOOP  //
////////////////////////
//
//
void loop() {
  //
  // Must be done at the beginning for the clock to work right.
  time_begin = millis();// Place at the very beginning
  //
  lcd_timeDisp();// Display the day and time on line 1
  //
  lcd_tempDisp();// Display the temp in/out on line 2
  //
  //**************************
  //DO TIME STUFF TO UPDATE REGISTERS
  //
  time_val = (time_remain + time_duration);
  // If the time through (interval) has been less than a second
  //  keep adding it up.
  if (time_val < 1000) {
    time_remain = time_val;
  }
  // If the time through (interval) has been more than a second
  //  count out how many seconds.
  if (time_val >= 1000) {
    while (time_val >= 1000) {
      time_val = time_val - 1000;
      time_seconds++;
      event_seconds1++;// Increase event_seconds1 by one
    }
    time_remain = time_val;
  }
  //
  if (time_seconds >= 60) {
    time_minutes++;// Increase minutes by one
    time_remain = (time_remain + 1);// Added for time tick loss over time.
    time_seconds = (time_seconds - 60);
  }
  if (time_minutes >= 60) {
    time_hours++;// Increase by 1
    time_minutes = (time_minutes - 60);
  }
  if (time_hours >= 24) {
    time_days++;// Increase by 1
    time_hours = (time_hours - 24);
  }
  if (time_days >= 7) {
    time_days = (time_days - 7);
  }
  //
  //
  // Check to see if a button is pressed.
  // No Debounce was harmed in the making of this program.
  //
  btn_read = analogRead(A0);
  if (btn_read > 50 && back_lit == 0) {
    digitalWrite(light, LOW);// Turn on the back light for any
    //button activation. Dont do any button actions yet.
    event_seconds1 = 0;// Clear the seconds event generator.
    back_lit = 1;// The next button press is valid to do something.
    delay(2000);// Before looking for another button pressed.
    //
  }
  //
  //
  btn_read = analogRead(A0);//
  if (btn_read > 50 && back_lit == 1) {
    //
    //Valid reading is anything great than 50.
    // A valid reading and back light=1 to do the button stuff.
    // 50 is my out of range (disable) setting for bad buttons.
    //                 A button is being pressed.
    button_pressed();//Figure out which one
  }
  // Check to see if a button is released.
  btn_read = analogRead(A0);//
  if (btn_read == 0 && back_lit == 1) {
    //                   Button was released.
    button_released();// Figure out which one
  }
  //
  // Timer for turning off the back light
  if (event_seconds1 >= 120) {
    digitalWrite(light, HIGH);//  Turn off the back light.
    back_lit = 0;//  Clear register for LCD back light.
    offset_A = 0;//  Clear register for offsetting temps.
  }
  //
  //
  delay(100);// For stability
  //
  //************************************
  // THIS GOES AT THE END OF MAIN LOOP
  //Error corrects when millis rolls
  //Simply sets both readings to 0 and starts over.
  if (millis() < time_begin) {
    time_duration = 0;// Place at the very end
    time_begin = 0;// Place at very end
  }
  //
  if (millis() > time_begin) {
    time_duration = (millis() - time_begin);// Place at the very end
  }
  //
  /////////////////////////
  //   END OF MAIN LOOP  //
  /////////////////////////
  //
}
//
//
//
//
//
//*********************
//   BEGIN ROUTINES  **
//*********************
//
//
/////////////////////
//   LCD ROUTINES  //
/////////////////////
//
//
//Routine to initialize the lcd.
//
void lcd_init() {
  digitalWrite(lcd_E, LOW);// Clear E line
  digitalWrite(lcd_RS, LOW);// Clear RS line
  delayMicroseconds(125);// Longer delay then needed but works
  for (int lcd_i = 0; lcd_i < 4; lcd_i++) {
    //
    lcd_C = (aray_set_up[lcd_set]);
    //
    shiftOut(lcd_datapin, lcd_clk, MSBFIRST, lcd_C);
    E_line();
    lcd_set = lcd_set + 1;
  }
  delay(5);
}
//
//**********
//Routine to choose which line info is to be displayed on.
// lcd_set = 0 for line one.
// lcd_set = 1 for line two.
// lcd_set must be set before getting here.
//
void lcd_line() {
  lcd_C = (aray_lines[lcd_set]); // aray_lines[lcd_set] if lcd_set = 0 = line one
  // aray_lines[lcd_set] if lcd_set = 1 = line two.
  digitalWrite(lcd_E, LOW); // Lower E line
  digitalWrite(lcd_RS, LOW); // Lower RS line
  delayMicroseconds(125); // Small delay
  //
  shiftOut(lcd_datapin, lcd_clk, MSBFIRST, lcd_C);
  E_line();
  digitalWrite(lcd_RS, HIGH);
  delayMicroseconds(125);
}
//
//**********
//Routine to send character strings to the display.
// lcd_N must be loaded with the number of characters to send
// before getting here.
//
void lcd_char() {
  lcd_D = 0;
  //
  //Adjust lcd_N for number of characters to send
  for (lcd_i = 0; lcd_i < lcd_N; lcd_i++) {
    //
    switch (lcd_Z) {
      case 0://1st char string Fun_Shway_Display
      lcd_A = (aray0[lcd_D]);
      break;
      case 1://2nd char string _In_
      lcd_A = (aray1[lcd_D]);
      break;
      case 2://3rd char string Out_
      lcd_A = (aray2[lcd_D]);
      break;
      case 3://4th char string used for blanks
      lcd_A = (aray3[lcd_D]);
      break;
      case 4://5th char string not used yet. blanks.
      lcd_A = (aray4[lcd_D]);
      break;
      case 5://6th char string Time_
      lcd_A = (aray5[lcd_D]);
      break;
      case 6://7th char string not used yet. Blanks.
      lcd_A = (aray6[lcd_D]);
      break;
      case 7://8th char string. Mon_
      lcd_A = (aray7[lcd_D]);
      break;
      case 8://9th char string. Tue_
      lcd_A = (aray8[lcd_D]);
      break;
      case 9://10th char string. Wed_
      lcd_A = (aray9[lcd_D]);
      break;
      case 10://11th char string. Thu_
      lcd_A = (aray10[lcd_D]);
      break;
      case 11://12th char string. Fri_
      lcd_A = (aray11[lcd_D]);
      break;
      case 12://13th char string. Sat_
      lcd_A = (aray12[lcd_D]);
      break;
      case 13://14th char string. Sun_
      lcd_A = (aray13[lcd_D]);
      break;
      case 14://15th char string. Button_Config._
      lcd_A = (aray14[lcd_D]);
      break;
      case 15://16th char string. Press_
      lcd_A = (aray15[lcd_D]);
      break;
      case 16://17th char string. Release_
      lcd_A = (aray16[lcd_D]);
      break;
      case 17://18th char string. _Failed_
      lcd_A = (aray17[lcd_D]);
      break;
      case 18://19th char string. _Set_
      lcd_A = (aray18[lcd_D]);
      break;
    }
    //
    shiftOut(lcd_datapin, lcd_clk, MSBFIRST, lcd_A);
    E_line();
    lcd_D = lcd_D + 1;
  }
}
//
//**********
//Routine is for the testing out of the register.
// lcd_A must be set to what to send before getting here
// lcd_A may = val1000s or val100s
// thous_out results in a blank if the first number = 0
//
void thous_out() {
  shiftOut(lcd_datapin, lcd_clk, MSBFIRST, aray_hunds[lcd_A]);
  E_line();
  //
}
//
//**********
//Routine is for the testing out of the register.
// lcd_A must be set before getting here.
// lcd_A may = val10s or val1s
// tens_out results in a zero if the first number = 0
//
void tens_out() {
  shiftOut(lcd_datapin, lcd_clk, MSBFIRST, aray_tens[lcd_A]);
  E_line();
  //
}
//
//**********
//Routine for sending individual characters to the lcd
// example ":" used in the seperation of hours from minutes
//
void car_out() {
  shiftOut(lcd_datapin, lcd_clk, MSBFIRST, lcd_A); // this is set to
  E_line();
  //
}
//
//**********
//Routine to do the E line of the lcd
//
void E_line() {
  digitalWrite(lcd_E, HIGH);
  delayMicroseconds(1);
  digitalWrite(lcd_E, LOW);
  delayMicroseconds(125);
}
//
//**********
//Routine to send blanks to the lcd.
// lcd_set must be set before getting here.
// lcd_set = 0;//lcd line one
// lcd_set = 1;//lcd line two
//
void lcd_line_clear() {
   // Clear the lcd line before writing to it
   lcd_line();
   delay(5);
   //
   lcd_Z = 3;// Spaces character string
   lcd_N = 24;// Send all 24 characters
   lcd_char();
   delay(5);
   //
}
//
//**********
//Routine to display the time on the LCD.
// Time is displayed on the first line.
//
void lcd_timeDisp() {
  //
  lcd_set = 0;// LCD line one
  lcd_line();
  delay(5);
  //
  lcd_Z = (time_days + 7);// String for day of the week
  //  Plus 7 is to jump over the non days character strings
  lcd_N = 4;// Send 4 characters = day plus space
  lcd_char();
  //
  test_test = time_hours;// Make a copy for testing
  cracker();// Break out hours
  //
  lcd_A = val10s;// Now holds the 10s in the hour
  thous_out();// Send a blank if no tens
  //
  lcd_A = val1s;// Now holds the 1s in the hour
  tens_out();// Send the number of 1s in hour
  //
  //
  lcd_A = ':';//
  car_out();// Send an individual character
  //
  //
  test_test = time_minutes;// Make a copy for testing
  cracker();// Break out minutes.
  //
  lcd_A = val10s;// Now holds the 10s in the minutes.
  tens_out();// Send the number of 10s in the minutes.
  //
  lcd_A = val1s;// Now holds the 1s in the minutes.
  tens_out();// Send the number of 1s in the minutes.
  //
  lcd_A = ' ';// Add a space
  car_out();// Send an individual character.
  //
  test_test = offset_A;// Make a copy for testing.
  cracker(); // Break out register.
  //
  lcd_A = val1s;// Now holds the sensor # being adjusted.
  thous_out();// Send a blank if no sensor is being adjusted.
  //
}
//
//**********
//Routine to display the temp on the LCD.
// Temp is displayed on the second line.
//
void lcd_tempDisp() {
  //
  //
  lcd_set = 1;//LCD line two
  lcd_line();
  delay(5);
  //
  lcd_Z = 1;// Inside character string
  lcd_N = 4;// Send only 4 characters
  lcd_char();
  delay(5);
  //
  // Get the value of inside temp sensor on analog line 2
  sensor = analogRead(A2);//
  // I am displaying in degrees F
  // Looks like this with no offset
  // sensor = (((((sensor * (5.0 / 1023.0)) * 100) - 273) * 1.8) + 32);
  sensor = (((((sensor * (5.0 / 1023.0)) * 100) - offset_sensor_2) * 1.8) + 32);
  //
  test_test = sensor;// Not interested in numbers after decimal.
  //
  // cracker is used after any reading on any analoge line
  //  to make the reading so it can be displayed on LCD
  cracker();// Convert the reading
  //
  lcd_A = val100s;
  thous_out();
  //
  lcd_A = val10s;
  tens_out();
  //
  lcd_A = val1s;
  tens_out();
  //
  lcd_A = ' ';// Gives a space
  car_out();// Sends individual character instead of a string
  //
  lcd_Z = 2;// Outside character string
  lcd_N = 4;// Send only 4 characters
  lcd_char();
  delay(5);
  //
  // Get the value of outside temp sensor on analog line 3
  sensor = analogRead(A3);
  sensor = (((((sensor * (5.0 / 1023.0)) * 100) - offset_sensor_3) * 1.8) + 32);
  //
  test_test = sensor;// Not interested in numbers after decimal.
  //
  //cracker is used after any reading on any analoge line
  // to make the reading so it can be displayed on LCD.
  cracker();// Convert the reading
  //
  lcd_A = val100s;
  thous_out();
  //
  lcd_A = val10s;
  tens_out();
  //
  lcd_A = val1s;
  tens_out();
  //
  lcd_A = ' ';
  car_out();
  //
  lcd_A = ' ';
  car_out();
  //
  lcd_A = ' ';
  car_out();
  //
  lcd_A = ' ';
  car_out();
  //
  lcd_A = ' ';
  car_out();
  //
  // Get the value of on board temp sensor on analog line 1
  sensor = analogRead(A1);// Get the value of analog line 1
  sensor = (((((sensor * (5.0 / 1023.0)) * 100) - offset_sensor_1) * 1.8) + 32);
  //
  test_test = sensor;// Not interested in numbers after decimal.
  //
  //cracker is used after any reading on any analog line
  // to make the reading so it can be displayed on LCD
  cracker();// Convert the reading.
  //
  lcd_A = val100s;
  thous_out();
  //
  lcd_A = val10s;
  tens_out();
  //
  lcd_A = val1s;
  tens_out();
  //
  //
}
//
////////////////
//   CRACKER  //
////////////////
//
//**********
//Routine breaks numbers into something that can be displayed
// on the lcd.
// test_test must have a copy of what to crack before getting here.
//
void cracker() {
  //
  // Test 1000s
  val1000s = 0;// Clear 1000 register
  while (test_test >= 1000) {
    test_test = test_test - 1000;
    val1000s++;
  }
  // Test 100s
  val100s = 0;// Clear 100 register
  while (test_test >= 100) {
    test_test = test_test - 100;
    val100s++;
  }
  // Test 10s
  val10s = 0;// Clear 10 register
  while (test_test >= 10) {
    test_test = test_test - 10;
    val10s++;
  }
  // Remainder is the 1's
  val1s = test_test;
  //
  // End testing
  // The number stored in test_test is now be broken
  //  out into four register
  // val1000s = the number of thousands in the test number
  // val100s = the number of hundreds in the test number
  // val10s = the number of tens in the test number
  // val1s = remainder, the number of ones in the number
  //
}
//
//
///////////////////////////////
//   BUTTONS ON ANALOG LINE  //
///////////////////////////////
//
//**********
//Routine to do button 1 stuff.
//
void btn_1() {
  time_days = (time_days +1);
  delay(100);
}
//
//**********
//Routine to do button 2 stuff.
//
void btn_2() {
  time_hours = (time_hours +1);
  delay(100);
}
//
//**********
//Routine to do button 3 stuff.
//
void btn_3() {
  time_minutes = (time_minutes +1);
  delay(100);
}
//
//**********
//Routine to do button 4 stuff.
//
void btn_4() {
  switch (offset_A) {
    case 0:// Offset was 0
    offset_A = 1;// Make it sensor 1
    break;
    case 1:// Offset was 1
    offset_A = 2;// Make it sensor 2
    break;
    case 2:// Offset was 2
    offset_A = 3;// Make it sensor 3
    break;
    case 3:// Offset was 3
    offset_A = 0;// Make it 0 = No sensor adjustment.
    break;
  }
}
//
//**********
//Routine to do button 5 stuff.
// Increase sensor offsets.
void btn_5() {
  //
  if (offset_A == 1) {
    offset_sensor_1++;// Increase the offset for sensor 1
  }
  //
  if (offset_A == 2) {
    offset_sensor_2++;// Increase the offset for sensor 2
  }
  //
  if (offset_A == 3) {
    offset_sensor_3++;// Increase the offset for sensor 3
  }
  //
}
//
//**********
//Routine to do button 6 stuff.
// Decrease sensor offsets.
void btn_6() {
  //
  if (offset_A == 1) {
    offset_sensor_1--;// Decrease the offset for sensor 1
  }
  //
  if (offset_A == 2) {
    offset_sensor_2--;// Decrease the offset for sensor 2
  }
  //
  if (offset_A == 3) {
    offset_sensor_3--;// Decrease the offset for sensor 3
  }
  //
}
//
//
////////////////////////
//   Button  Pressed  //
////////////////////////
//
//**********
//Routine for when a button is pressed.
// The button is not counted until released.
//
void button_pressed() {
  //
  btn_read2 = (btn_read);// Make a copy of the reading for testing
  //
  // If the button values are between certain levels that
  //  is equal to its button.
  // Button values aquired from btn_config
  //
  if (btn_read >= btn_1lo && btn_read2 <= btn_1hi) {
    btn_pressed = 1;// 1 in register = button 1 was pressed
  }
  //
  if (btn_read >= btn_2lo && btn_read2 <= btn_2hi) {
    btn_pressed = 2;// 2 in register = button 2 was pressed
  }
  //
  if (btn_read >= btn_3lo && btn_read2 <= btn_3hi) {
    btn_pressed = 3;// 3 in register = button 3 was pressed
  }
  //
  if (btn_read >= btn_4lo && btn_read2 <= btn_4hi) {
    btn_pressed = 4;// 4 in register = button 4 was pressed.
  }
  //
  if (btn_read >= btn_5lo && btn_read2 <= btn_5hi) {
    btn_pressed = 5;// 5 in register = button 5 was pressed.
  }
  //
  if (btn_read >= btn_6lo && btn_read2 <= btn_6hi) {
    btn_pressed = 6;// 6 in register = button 6 was pressed.
  }
  //
}
//
//
/////////////////////////
//   Button  Released  //
/////////////////////////
//
//**********
//Routine for when a button is released.
// This is when the button event is performed
//
void button_released() {
  // Count this as a button press once cleared.
  if (btn_read == 0 && btn_pressed == 1) {
    btn_pressed = 0;// Clear the register
    btn_1();// Do the button 1 stuff.
  }
  //
  // Count this as a button press once cleared.
  if (btn_read == 0 && btn_pressed == 2) {
    btn_pressed = 0;// Clear the register
    btn_2();// Do the button 2 stuff.
  }
  //
  // Count this as a button press once cleared.
  if (btn_read == 0 && btn_pressed == 3) {
    btn_pressed = 0;// Clear the register
    btn_3();// Do the button 3 stuff.
  }
  //
  // Count this as a button press once cleared.
  if (btn_read == 0 && btn_pressed == 4) {
    btn_pressed = 0;// Clear the register
    btn_4();// Do the button 4 stuff.
  }
  //
  // Count this as a button press once cleared.
  if (btn_read == 0 && btn_pressed == 5) {
    btn_pressed = 0;// Clear the register
    btn_5();// Do the button 5 stuff.
  }
  //
  // Count this as a button press once cleared.
  if (btn_read == 0 && btn_pressed == 6) {
    btn_pressed = 0;// Clear the register
    btn_6();// Do the button 6 stuff.
  }
  //
}
//
//
/////////////////////////////////
//   BUTTON CONFIGURE ROUTINE  //
/////////////////////////////////
//
//**********
//Routine to get the values and make a range for the buttons.
// Routine is run one time before the main loop.
// Buttons on analog line 0
// Buttons may be used in any order.
//
void btn_config() {
  // Configure the buttons on the analog line A0
  //
  lcd_set = 1;// LCD line two
  lcd_line_clear;// Clear line of the lcd
  //
  lcd_set = 0;// LCD line one
  lcd_line_clear();// Clear line of the lcd
  //lcd_set = 0;// Already done no need to repeat
  lcd_line();// Write to lcd line
  delay(5);
  // Display button Config on line one
  lcd_Z = 14;// Button config
  lcd_N = 24;// Send all 24 characters
  lcd_char();
  delay(10000);// Give time to read
  //
  //
  //6 buttons = 6 loops around.
  //
  for (looping = 0; looping < 6; looping++) {
    btn_btn();// Test out buttons
    btn_number++;// Increase the button to test by 1.
  }
  //
  btn_number == 1;// Set back to 1 when finished.
  //
}
//
////////////////
//   btn_btn  //
////////////////
//
//**********
//Routine to tell you what button to press
//
void btn_btn() {
  // Test out buttons
  lcd_set = 0;// LCD line one
  lcd_line();
  delay(5);
  //
  lcd_Z = 15;//
  lcd_N = 6;// Send 6 characters = Press_
  lcd_char();
  lcd_Z = 14;//
  lcd_N = 7;// Send 7 characters = Button_
  lcd_char();
  //
  lcd_A = btn_number;// Starts at button 1
  tens_out();// Send the digit
  //
  delay(5000);// Give time to read
  //
  btn_read = analogRead(A0);// Buttons are on analog 0
  //
  lcd_set = 0;// LCD line one
  lcd_line();
  delay(5);
  //
  lcd_Z = 16;// Button config
  lcd_N = 8;// Send 8 characters = Release_
  lcd_char();
  lcd_Z = 14;// Button config
  lcd_N = 7;// Send 7 characters = Button_
  lcd_char();
  lcd_A = btn_number;// Starts at button 1
  tens_out();// Send the digit
  //
  delay(5000);// Give time to read.
  //
  lcd_set = 0;// Line one
  lcd_line_clear();// Clear the lcd line
  //
  // Test out results
  // Button was good go here
  if (btn_read > 0) {
    btn_copy = btn_number;// Make a copy. It was good
    btn_con_fig();
    // Do the stuff if it was a good reading
    //
    lcd_line();// Already set for line 1
    delay(5);
    //
    lcd_Z = 14;// Button config
    lcd_N = 7;// Send 7 characters = Button_
    lcd_char();
    lcd_A = btn_number;// Starts at button 1
    tens_out();// Send the digit
    lcd_Z = 18;// String for " Set"
    lcd_N = 4;// Send 4 characters = _Set
    lcd_char();// Send it
    //
    //
  }
  //
  //
  // Test out results
  // Button failed go here
  if (btn_read <= 50) {
    btn_copy = (btn_number + 6);// The button working on +6
    // to skip over the good readings and do the bad ones
    btn_con_fig();
    // Do the stuff if it was a bad reading
    //
    lcd_line();// Already set for line 1
    delay(5);
    //
    lcd_Z = 14;// String for Button_
    lcd_N = 7;// Send 7 characters = Button_
    lcd_char();
    lcd_A = btn_number;// Starts at button 1
    tens_out();// Send the digit   
    lcd_Z = 17;//
    lcd_N = 7;// Send 7 characters = _Failed
    lcd_char();
    //
  }
  btn_read = 0;// Clear the last analog reading
  delay(5000);//
  //
  lcd_set = 0;// Line one
  lcd_line_clear();// Clear the lcd line
  //
}
//
////////////////////
//   btn_con_fig  //
////////////////////
//
//**********
//Routine that sets the button ranges to watch for.
//
void btn_con_fig() {
  //
  // Number 1-6 are for good read
  // Numbers 7-12 are for bad read
  //
  switch (btn_copy) {
    case 0:// No numbers should be zero. error
    break;// Kick out of here
    //
    case 1:// Button number 1 was good
    btn_1hi = (btn_read + 2);// Make the proper adjustments
    btn_1lo = (btn_read - 2);// Make the proper adjustments
    break;
    //
    case 2:// Button number 2 was good
    btn_2hi = (btn_read + 2);// Make the proper adjustments
    btn_2lo = (btn_read - 2);// Make the proper adjustments
    break;
    //
    case 3:// Button number 3 was good
    btn_3hi = (btn_read + 2);// Make the proper adjustments
    btn_3lo = (btn_read - 2);// Make the proper adjustments
    break;
    //
    case 4:// Button number 4 was good
    btn_4hi = (btn_read + 2);// Make the proper adjustments
    btn_4lo = (btn_read - 2);// Make the proper adjustments
    break;
    //
    case 5:// Button number 5 was good
    btn_5hi = (btn_read + 2);// Make the proper adjustments
    btn_5lo = (btn_read - 2);// Make the proper adjustments
    break;
    //
    case 6:// Button number 6 was good
    btn_6hi = (btn_read + 2);// Make the proper adjustments
    btn_6lo = (btn_read - 2);// Make the proper adjustments
    break;
    //
    ////////////////////
    //   Bad buttons  //
    ////////////////////
    //
    case 7:// Button number 1 was bad
    btn_1hi = 100;// Load false numbers so buttons do not
    btn_1lo = 100;//  act erroneously
    break;
    //
    case 8:// Button number 2 was bad
    btn_2hi = 100;// Load false numbers so buttons do not
    btn_2lo = 100;//  act erroneously
    break;
    //
    case 9:// Button number 3 was bad
    btn_3hi = 100;// Load false numbers so buttons do not
    btn_3lo = 100;//  act erroneously
    break;
    //
    case 10:// Button number 4 was bad
    btn_4hi = 100;// Load false numbers so buttons do not
    btn_4lo = 100;//  act erroneously
    break;
    //
    case 11:// Button number 5 was bad
    btn_5hi = 100;// Load false numbers so buttons do not
    btn_5lo = 100;//  act erroneously
    break;
    //
    case 12:// Button number 6 was bad
    btn_6hi = 100;// Load false numbers so buttons do not
    btn_6lo = 100;//  act erroneously
    break;
    //
  }
}
//
//
//
//
Feng shui. ;)
how much did this cost to make <br>
I had most of the parts for this around. I did some quick searching at Sparkfun and Jameco. Between the two of them you can get all of the electronics parts for around $67.00 including the Arduino. The LCD is the second most expensive electronic part. The non-electronic materials ran about $25.00. Total cost, around $92ish. Having an electronic device on the wall that no one is scared of . . . Priceless ;)
gooood!
Thank you linkedin :)

About This Instructable

13,268views

33favorites

License:

More by ray74:Clay Crucible Recipes Make a clay crucible mold Color changing display 
Add instructable to: