Author Topic: Improve My Deerfeeder?  (Read 2960 times)

0 Members and 1 Guest are viewing this topic.

Offline squirrellluck

  • Trade Count: (0)
  • A Real Regular
  • ****
  • Posts: 642
Improve My Deerfeeder?
« on: September 14, 2009, 01:17:07 PM »
I built a feeder timer several years ago and now I'm thinking of revisiting this project. I took a small computer project board, micro switch,12 hr clock, capacitors and a vcr motor and built a timer. 6 volt battery sent power to the cap. until the switch closed sending power to the motor from the cap. Would a reastat work to adjust the lengh of the feed time.

Offline Matt

  • .:{º.º}:.
  • Administrator
  • Trade Count: (1)
  • Senior Member
  • *****
  • Posts: 2118
  • Gender: Male
    • Inkredible Image
Re: Improve My Deerfeeder?
« Reply #1 on: September 15, 2009, 04:29:33 PM »
I would say use a 555 timer IC then use a potentiometer to adjust your timing. It could then trigger a relay or a transistor and force the motor on to do its thing then after the cycle is over it resets. You could also use an AVR such as the ATMega8 which you could program for everyday of the year to go off at your own preset time or multiple times. All and all the circuit would be fairly simple to build and only need a few parts none of which would cost more than a few bucks. I can post some schematics if you like that will show both the 555 timer IC and the AVR methods. I also have a few feeder timers that I can pull apart and draw the schematic for them as well if it will help.

Matt
Any fool can know. The point is to understand.”
― Albert Einstein

Offline squirrellluck

  • Trade Count: (0)
  • A Real Regular
  • ****
  • Posts: 642
Re: Improve My Deerfeeder?
« Reply #2 on: September 16, 2009, 04:12:15 PM »
Matt, you are talking way over my head but I'll give it go. If you post schematics I would be interested. But be warned I will have lots of questions. Lets start with, what is a 555?

Offline Matt

  • .:{º.º}:.
  • Administrator
  • Trade Count: (1)
  • Senior Member
  • *****
  • Posts: 2118
  • Gender: Male
    • Inkredible Image
Re: Improve My Deerfeeder?
« Reply #3 on: September 16, 2009, 04:27:36 PM »
I like questions...lol

A 555 is a 8 pin IC in DIP configuration meaning it has 2 rows of 4 pins. It is a simple timer IC that can be used for most any time critical project.

I thought about this a little more and the more I think about it I am leaning toward a 4060 cmos IC based timer becuase then you can not only set when it triggers but also for how long in each cycle the relay stays engergized. This could be set with a variable resistor or "pot" so that you can adjust the timer to your needs and change it as your needs change without any reworking of the timer.

I will post you a schematic I found on the net last night after I have dinner...

Matt
Any fool can know. The point is to understand.”
― Albert Einstein

Offline Matt

  • .:{º.º}:.
  • Administrator
  • Trade Count: (1)
  • Senior Member
  • *****
  • Posts: 2118
  • Gender: Male
    • Inkredible Image
Re: Improve My Deerfeeder?
« Reply #4 on: September 17, 2009, 06:47:15 AM »
Any fool can know. The point is to understand.”
― Albert Einstein

Offline squirrellluck

  • Trade Count: (0)
  • A Real Regular
  • ****
  • Posts: 642
Re: Improve My Deerfeeder?
« Reply #5 on: September 20, 2009, 06:31:11 AM »
Matt these schematics look great... if I were a electronics tech :o I work on ac and refrig and heating. I've worked on a lot of mechanical equipt, I mean a lot! But I'm gonna have to do a lot of study before I can decipher those schematics.

Offline Matt

  • .:{º.º}:.
  • Administrator
  • Trade Count: (1)
  • Senior Member
  • *****
  • Posts: 2118
  • Gender: Male
    • Inkredible Image
Re: Improve My Deerfeeder?
« Reply #6 on: September 20, 2009, 06:53:35 AM »
Here is what it will look like when you are done with the repeat timer

Matt
Any fool can know. The point is to understand.”
― Albert Einstein

Offline squirrellluck

  • Trade Count: (0)
  • A Real Regular
  • ****
  • Posts: 642
Re: Improve My Deerfeeder?
« Reply #7 on: September 20, 2009, 07:44:28 AM »
How would you set the time on it as you do a feed timer?

Offline Matt

  • .:{º.º}:.
  • Administrator
  • Trade Count: (1)
  • Senior Member
  • *****
  • Posts: 2118
  • Gender: Male
    • Inkredible Image
Re: Improve My Deerfeeder?
« Reply #8 on: September 20, 2009, 07:49:01 AM »
Good question...

are you tring to be exact on the time it triggers every day?

Matt
Any fool can know. The point is to understand.”
― Albert Einstein

Offline squirrellluck

  • Trade Count: (0)
  • A Real Regular
  • ****
  • Posts: 642
Re: Improve My Deerfeeder?
« Reply #9 on: September 20, 2009, 07:58:02 AM »
Well, with the primitive setup I built I had removed the second and minute hands. I cut down the hour hand so that I could set the feed time at roughly the time I wanted it to feed. It would contact the micro switch twice in a 24 hr period. I would like to be able to set feed times more accurately. I could get a 24 hr clock and use pins I guess but the idea of using electronics is interesting

Offline Matt

  • .:{º.º}:.
  • Administrator
  • Trade Count: (1)
  • Senior Member
  • *****
  • Posts: 2118
  • Gender: Male
    • Inkredible Image
Re: Improve My Deerfeeder?
« Reply #10 on: September 20, 2009, 08:12:34 AM »
Well we could use a "PIC16F628 Digital Clock Timer" to build in a clock with an alarm and have that be the trigger for the timer.

set the alarm to the times you want the feeder to activate and then using the "pots" on the timer set the duration of activation.

Alarm triggers at set time which would engerize a transistor to start the timer. Seeing as it is a repeating timer you could have it repeat every 12 hours so that you could get say 6am then 6pm. After the 6pm event the system goes back to sleep until the alarm triggers the next day and starts the cycle over.

This would add about $12 bucks to the project for the PIC16F628 side of it.

Matt
Any fool can know. The point is to understand.”
― Albert Einstein

Offline Matt

  • .:{º.º}:.
  • Administrator
  • Trade Count: (1)
  • Senior Member
  • *****
  • Posts: 2118
  • Gender: Male
    • Inkredible Image
Re: Improve My Deerfeeder?
« Reply #11 on: September 20, 2009, 08:21:31 AM »
Well there is another way I just thought about as well, take a cheap alarm clock remove the A/C side of it and power it with a lantern battery then tie to the alarm buzzer with a "FET" to act as a relay using a flash capacitor ( 370v 97ųf )to drive the motor. This would give you a steady output to the motor while the alarm was going off. It might take a little work but it may be the less techy way to do it.

Matt
Any fool can know. The point is to understand.”
― Albert Einstein

Offline Matt

  • .:{º.º}:.
  • Administrator
  • Trade Count: (1)
  • Senior Member
  • *****
  • Posts: 2118
  • Gender: Male
    • Inkredible Image
Re: Improve My Deerfeeder?
« Reply #12 on: October 07, 2009, 10:36:51 PM »
Ok here is a little timer I put together:

Uses a ATmega8 AVR
2 10nf caps
1  1k resistor
1 10k pot
3 push button momentary switches
1  16x2 LCD module
--------------------------------------
Total Cost: $9.00

I wrote the software for the AVR in C but it is still a bit buggy and needs another function added to set the duration of activation.

Here are a few pics of it in action:

Boot Up:


Time Set:


The Count down:


The circuit on my small breadboard:



I will be working on the code and will publish the schematic for it just as soon as I can get a chance to draw it out.

Comments Welcome....

Matt

Any fool can know. The point is to understand.”
― Albert Einstein

Offline elmer

  • GBO Supporter
  • Trade Count: (0)
  • Contributor
  • *****
  • Posts: 388
Re: Improve My Deerfeeder?
« Reply #13 on: November 08, 2009, 02:42:32 PM »
This is a very interesting thread.

Matt, we use an ATMega32 in one of products at work. I setup timer0 as a 1ms timer. Then I set up variables for each thing I want to time and set each to a value equal to the number of milliseconds that I want to delay. Each time the timer0 interrupts trigger I decrement each variable that is greater than zero. When I loop through the main function if the duration has timed down to zero then do something else skip and to on to the next thing. This is a serious oversimplification, but I think you get the idea.
NRA life member
TSRA life member
Dallas Safari Club member
JPFO life member
GOA life member

http://public.fotki.com/ElmerF/
http://s215.photobucket.com/profile/CharlesL_album

Offline Matt

  • .:{º.º}:.
  • Administrator
  • Trade Count: (1)
  • Senior Member
  • *****
  • Posts: 2118
  • Gender: Male
    • Inkredible Image
Re: Improve My Deerfeeder?
« Reply #14 on: November 09, 2009, 09:23:20 PM »
This is a very interesting thread.

Matt, we use an ATMega32 in one of products at work. I setup timer0 as a 1ms timer. Then I set up variables for each thing I want to time and set each to a value equal to the number of milliseconds that I want to delay. Each time the timer0 interrupts trigger I decrement each variable that is greater than zero. When I loop through the main function if the duration has timed down to zero then do something else skip and to on to the next thing. This is a serious oversimplification, but I think you get the idea.

I use this to setup my delays:

delay.h

Code: [Select]
#ifndef _UTIL_DELAY_H_
#define _UTIL_DELAY_H_ 1

#include <inttypes.h>
#include <util/delay_basic.h>

/** \file */
/** \defgroup util_delay <util/delay.h>: Convenience functions for busy-wait delay loops
    \code
    //#define F_CPU 1000000UL  // 1 MHz
    #define F_CPU 14.7456E6
    #include <util/delay.h>
    \endcode

    \note As an alternative method, it is possible to pass the
    F_CPU macro down to the compiler from the Makefile.
    Obviously, in that case, no \c \#define statement should be
    used.

    The functions in this header file are wrappers around the basic
    busy-wait functions from <util/delay_basic.h>.  They are meant as
    convenience functions where actual time values can be specified
    rather than a number of cycles to wait for.  The idea behind is
    that compile-time constant expressions will be eliminated by
    compiler optimization so floating-point expressions can be used
    to calculate the number of delay cycles needed based on the CPU
    frequency passed by the macro F_CPU.

    \note In order for these functions to work as intended, compiler
    optimizations <em>must</em> be enabled, and the delay time
    <em>must</em> be an expression that is a known constant at
    compile-time.  If these requirements are not met, the resulting
    delay will be much longer (and basically unpredictable), and
    applications that otherwise do not use floating-point calculations
    will experience severe code bloat by the floating-point library
    routines linked into the application.

    The functions available allow the specification of microsecond, and
    millisecond delays directly, using the application-supplied macro
    F_CPU as the CPU clock frequency (in Hertz).

*/

#if !defined(__DOXYGEN__)
static inline void _delay_us(double __us) __attribute__((always_inline));
static inline void _delay_ms(double __ms) __attribute__((always_inline));
#endif

#ifndef F_CPU
/* prevent compiler error by supplying a default */
# warning "F_CPU not defined for <util/delay.h>"
//# define F_CPU 1000000UL
#define F_CPU 14.7456E6
#endif

#ifndef __OPTIMIZE__
# warning "Compiler optimizations disabled; functions from <util/delay.h> won't work as designed"
#endif

/**
   \ingroup util_delay

   Perform a delay of \c __ms milliseconds, using _delay_loop_2().

   The macro F_CPU is supposed to be defined to a
   constant defining the CPU clock frequency (in Hertz).

   The maximal possible delay is 262.14 ms / F_CPU in MHz.

   When the user request delay which exceed the maximum possible one,
   _delay_ms() provides a decreased resolution functionality. In this
   mode _delay_ms() will work with a resolution of 1/10 ms, providing
   delays up to 6.5535 seconds (independent from CPU frequency).  The
   user will not be informed about decreased resolution.
 */
void
_delay_ms(double __ms)
{
uint16_t __ticks;
double __tmp = ((F_CPU) / 4e3) * __ms;
if (__tmp < 1.0)
__ticks = 1;
else if (__tmp > 65535)
{
// __ticks = requested delay in 1/10 ms
__ticks = (uint16_t) (__ms * 10.0);
while(__ticks)
{
// wait 1/10 ms
_delay_loop_2(((F_CPU) / 4e3) / 10);
__ticks --;
}
return;
}
else
__ticks = (uint16_t)__tmp;
_delay_loop_2(__ticks);
}

/**
   \ingroup util_delay

   Perform a delay of \c __us microseconds, using _delay_loop_1().

   The macro F_CPU is supposed to be defined to a
   constant defining the CPU clock frequency (in Hertz).

   The maximal possible delay is 768 us / F_CPU in MHz.

   If the user requests a delay greater than the maximal possible one,
   _delay_us() will automatically call _delay_ms() instead.  The user
   will not be informed about this case.
 */
void
_delay_us(double __us)
{
uint8_t __ticks;
double __tmp = ((F_CPU) / 3e6) * __us;
if (__tmp < 1.0)
__ticks = 1;
else if (__tmp > 255)
{
_delay_ms(__us / 1000.0);
return;
}
else
__ticks = (uint8_t)__tmp;
_delay_loop_1(__ticks);
}


#endif /* _UTIL_DELAY_H_ */


and here is the delay_basic.h

Code: [Select]

#ifndef _UTIL_DELAY_BASIC_H_
#define _UTIL_DELAY_BASIC_H_ 1

#include <inttypes.h>

/** \file */
/** \defgroup util_delay_basic <util/delay_basic.h>: Basic busy-wait delay loops
    \code
    #include <util/delay_basic.h>
    \endcode

    The functions in this header file implement simple delay loops
    that perform a busy-waiting.  They are typically used to
    facilitate short delays in the program execution.  They are
    implemented as count-down loops with a well-known CPU cycle
    count per loop iteration.  As such, no other processing can
    occur simultaneously.  It should be kept in mind that the
    functions described here do not disable interrupts.

    In general, for long delays, the use of hardware timers is
    much preferrable, as they free the CPU, and allow for
    concurrent processing of other events while the timer is
    running.  However, in particular for very short delays, the
    overhead of setting up a hardware timer is too much compared
    to the overall delay time.

    Two inline functions are provided for the actual delay algorithms.

*/

#if !defined(__DOXYGEN__)
static inline void _delay_loop_1(uint8_t __count) __attribute__((always_inline));
static inline void _delay_loop_2(uint16_t __count) __attribute__((always_inline));
#endif

/** \ingroup util_delay_basic

    Delay loop using an 8-bit counter \c __count, so up to 256
    iterations are possible.  (The value 256 would have to be passed
    as 0.)  The loop executes three CPU cycles per iteration, not
    including the overhead the compiler needs to setup the counter
    register.

    Thus, at a CPU speed of 1 MHz, delays of up to 768 microseconds
    can be achieved.
*/
void
_delay_loop_1(uint8_t __count)
{
__asm__ volatile (
"1: dec %0" "\n\t"
"brne 1b"
: "=r" (__count)
: "0" (__count)
);
}

/** \ingroup util_delay_basic

    Delay loop using a 16-bit counter \c __count, so up to 65536
    iterations are possible.  (The value 65536 would have to be
    passed as 0.)  The loop executes four CPU cycles per iteration,
    not including the overhead the compiler requires to setup the
    counter register pair.

    Thus, at a CPU speed of 1 MHz, delays of up to about 262.1
    milliseconds can be achieved.
 */
void
_delay_loop_2(uint16_t __count)
{
__asm__ volatile (
"1: sbiw %0,1" "\n\t"
"brne 1b"
: "=w" (__count)
: "0" (__count)
);
}

#endif /* _UTIL_DELAY_BASIC_H_ */


It seems to work ok but was written to run on the internal clock so I have to play with it a little to get it timed right with the 14.7456mhz crystal I'm using. I am thinking about using my HVP to reset the FUSES to use the internal 1mhz clock as I think using an extrenal one is an overkill for this project.

I would love to play with some mega32's... I am watching some on ebay but they are going for almost $4 each and I just cant bring myself to pay that for them yet.

I have some mega8's 16's and 1 mega128 but it is a TQFP64 and I dont have a board to put it on. I have been thinking of playing with PICS and seeing how much difference there is. I have a few dozen 16f18xx's I pulled out of some Triplite UPS's that I was thinking about erasing and maybe doing some LED POV projects with them. But that can be another thread...  ;)

Matt
Any fool can know. The point is to understand.”
― Albert Einstein

Offline jiminpa

  • Trade Count: (0)
  • Avid Poster
  • **
  • Posts: 120
  • Gender: Male
Re: Improve My Deerfeeder?
« Reply #15 on: November 13, 2009, 06:29:02 AM »

mine works easier,just add corn!!!
life member pa trappers
life member v.f.w.

Offline squirrellluck

  • Trade Count: (0)
  • A Real Regular
  • ****
  • Posts: 642
Re: Improve My Deerfeeder?
« Reply #16 on: November 14, 2009, 03:54:26 PM »
Used pipe feeders for years. But I like to feed daily and around here the deer will empty that pipe feeder over night. At 50 lb a day I cant afford it. Timed feed and my corn last longer.

Offline elmer

  • GBO Supporter
  • Trade Count: (0)
  • Contributor
  • *****
  • Posts: 388
Re: Improve My Deerfeeder?
« Reply #17 on: November 16, 2009, 10:21:13 AM »
Matt,

Our mega32's are TQFP's. I really like in-circuit programming, but don't like loosing the ports.

For short delays where the timing is critical (such as communicating with one wire serial devices) I turn off all interrupts and then call one of the delay loops such as this one which gives a 12us delay with a 10M crystal.

void D_12U(void)
 {
   for (ds = 7; ds > 0; ds--)
    NOP();
   return;   
 }

For longer delays I use this and just send it a number. My timer0 increments Delay_Time (as well as other time variables) once each mS.

void Delay(unsigned int d)
 {
   Delay_Time = 0;
   while (Delay_Time < d)
    {
      NOP();
    }
   return;   
 }

For timings I don't use delays because the equipment has to multitask and I don't want to stay in a loop longer than a few milliseconds. By using the timer to increment or decrement a variable I can time a task and only branch when it needs tending to.



NRA life member
TSRA life member
Dallas Safari Club member
JPFO life member
GOA life member

http://public.fotki.com/ElmerF/
http://s215.photobucket.com/profile/CharlesL_album

Offline elmer

  • GBO Supporter
  • Trade Count: (0)
  • Contributor
  • *****
  • Posts: 388
Re: Improve My Deerfeeder?
« Reply #18 on: November 16, 2009, 10:27:34 AM »
Matt,

Have you played with PWM to control motor speed? If you are using a MOSFET or IGBT to drive the motor you could vary the duty cycle and customize the motor speed as well as duration.
NRA life member
TSRA life member
Dallas Safari Club member
JPFO life member
GOA life member

http://public.fotki.com/ElmerF/
http://s215.photobucket.com/profile/CharlesL_album

Offline Matt

  • .:{º.º}:.
  • Administrator
  • Trade Count: (1)
  • Senior Member
  • *****
  • Posts: 2118
  • Gender: Male
    • Inkredible Image
Re: Improve My Deerfeeder?
« Reply #19 on: November 17, 2009, 07:26:54 AM »
Matt,

Have you played with PWM to control motor speed? If you are using a MOSFET or IGBT to drive the motor you could vary the duty cycle and customize the motor speed as well as duration.

I have been playing with some LMD18245 that I got National to send me as samples. They are ok but I have to use 2 of them for the bipolar motors that I want to use in my CNC.

I also have some PWM though I can’t seem to find them at the moment but here is a look at some of my toys I have collected over the last month or two.


I also have thousands of parts I pulled from other devices and such not shown.

---------------------------------------------------------------------------

One of my current projects is a Video Overlay System for retail applications such as POS systems or cash registers. It takes the printer output and formats it to NTSC video and overlays that on CCTV so that the managers or owners can see what the clerks are charging for items... Keeps them from giving the buddy discount as much.

I have built the first prototype which was nothing more than a mega8 with RX only. It acts like a terminal and seems to work well with computer powered POS systems but not so well with cash registers. I have prototype 2 also which I added a MAX232 to handle both RX and TX and seems to work fine with all systems. I am working on prototype number 3 which I am adding a LM1881 to handle video sync for me because I am having a hell of a time getting my CCTV video and my generated NTSC video to sync. I have to change the value of a handful of resistors each time I change the model of CCTV camera... not good...

Have you played with video generation? any tips?

Matt




Any fool can know. The point is to understand.”
― Albert Einstein

Offline elmer

  • GBO Supporter
  • Trade Count: (0)
  • Contributor
  • *****
  • Posts: 388
Re: Improve My Deerfeeder?
« Reply #20 on: November 17, 2009, 03:28:17 PM »
Sorry I have zero experience with video. All of my experience is on motor speed control on 1/2 - 1 hp size motors, temperature sensing, safety interlock monitoring, and user interface (buttons pressed and led seven segment displays).

I need to get involved with the LCD alpha numeric displays like you have on your project.

The mega32 has the pwm controller built in and I think the mega8 does too.
NRA life member
TSRA life member
Dallas Safari Club member
JPFO life member
GOA life member

http://public.fotki.com/ElmerF/
http://s215.photobucket.com/profile/CharlesL_album

Offline Matt

  • .:{º.º}:.
  • Administrator
  • Trade Count: (1)
  • Senior Member
  • *****
  • Posts: 2118
  • Gender: Male
    • Inkredible Image
Re: Improve My Deerfeeder?
« Reply #21 on: November 24, 2009, 10:55:00 AM »
Here is the code I use for the LCD. IF you use AVR Studio then you have all the needed includes.

lcd.c

Code: [Select]
#include <avr/io.h>
#include <inttypes.h>

#ifndef F_CPU
#define F_CPU 1000000UL /* 1 MHz Internal Oscillator */
#endif

#include <util/delay.h>

#include "lcd.h"



#define LCD_DATA_PORT PORT(LCD_DATA)
#define LCD_E_PORT PORT(LCD_E)
#define LCD_RS_PORT PORT(LCD_RS)
#define LCD_RW_PORT PORT(LCD_RW)

#define LCD_DATA_DDR DDR(LCD_DATA)
#define LCD_E_DDR DDR(LCD_E)
#define LCD_RS_DDR DDR(LCD_RS)
#define LCD_RW_DDR DDR(LCD_RW)

#define LCD_DATA_PIN PIN(LCD_DATA)

#define SET_E() (LCD_E_PORT|=(1<<LCD_E_POS))
#define SET_RS() (LCD_RS_PORT|=(1<<LCD_RS_POS))
#define SET_RW() (LCD_RW_PORT|=(1<<LCD_RW_POS))

#define CLEAR_E() (LCD_E_PORT&=(~(1<<LCD_E_POS)))
#define CLEAR_RS() (LCD_RS_PORT&=(~(1<<LCD_RS_POS)))
#define CLEAR_RW() (LCD_RW_PORT&=(~(1<<LCD_RW_POS)))



void LCDByte(uint8_t c,uint8_t isdata)
{
//Sends a byte to the LCD in 4bit mode
//cmd=0 for data
//cmd=1 for command


//NOTE: THIS FUNCTION RETURS ONLY WHEN LCD HAS PROCESSED THE COMMAND

uint8_t hn,ln; //Nibbles
uint8_t temp;

hn=c>>4;
ln=(c & 0x0F);

if(isdata==0)
CLEAR_RS();
else
SET_RS();

_delay_us(0.500); //tAS

SET_E();

//Send high nibble

temp=(LCD_DATA_PORT & 0XF0)|(hn);
LCD_DATA_PORT=temp;

_delay_us(1); //tEH

//Now data lines are stable pull E low for transmission

CLEAR_E();

_delay_us(1);

//Send the lower nibble
SET_E();

temp=(LCD_DATA_PORT & 0XF0)|(ln);

LCD_DATA_PORT=temp;

_delay_us(1); //tEH

//SEND

CLEAR_E();

_delay_us(1); //tEL

LCDBusyLoop();
}

void LCDBusyLoop()
{
//This function waits till lcd is BUSY

uint8_t busy,status=0x00,temp;

//Change Port to input type because we are reading data
LCD_DATA_DDR&=0xF0;

//change LCD mode
SET_RW(); //Read mode
CLEAR_RS(); //Read status

//Let the RW/RS lines stabilize

_delay_us(0.5); //tAS


do
{

SET_E();

//Wait tDA for data to become available
_delay_us(0.5);

status=LCD_DATA_PIN;
status=status<<4;

_delay_us(0.5);

//Pull E low
CLEAR_E();
_delay_us(1); //tEL

SET_E();
_delay_us(0.5);

temp=LCD_DATA_PIN;
temp&=0x0F;

status=status|temp;

busy=status & 0b10000000;

_delay_us(0.5);
CLEAR_E();
_delay_us(1); //tEL
}while(busy);

CLEAR_RW(); //write mode
//Change Port to output
LCD_DATA_DDR|=0x0F;

}

void InitLCD(uint8_t style)
{
/*****************************************************************

This function Initializes the lcd module
must be called before calling lcd related functions

Arguments:
style = LS_BLINK,LS_ULINE(can be "OR"ed for combination)
LS_BLINK :The cursor is blinking type
LS_ULINE :Cursor is "underline" type else "block" type

*****************************************************************/

//After power on Wait for LCD to Initialize
_delay_ms(30);

//Set IO Ports
LCD_DATA_DDR|=(0x0F);
LCD_E_DDR|=(1<<LCD_E_POS);
LCD_RS_DDR|=(1<<LCD_RS_POS);
LCD_RW_DDR|=(1<<LCD_RW_POS);

LCD_DATA_PORT&=0XF0;
CLEAR_E();
CLEAR_RW();
CLEAR_RS();

//Set 4-bit mode
_delay_us(0.3); //tAS

SET_E();
LCD_DATA_PORT|=(0b00000010); //[B] To transfer 0b00100000 i was using LCD_DATA_PORT|=0b00100000
_delay_us(1);
CLEAR_E();
_delay_us(1);

//Wait for LCD to execute the Functionset Command
LCDBusyLoop();                                    //[B] Forgot this delay

//Now the LCD is in 4-bit mode

LCDCmd(0b00001100|style); //Display On
LCDCmd(0b00101000); //function set 4-bit,2 line 5x7 dot format
}
void LCDWriteString(const char *msg)
{
/*****************************************************************

This function Writes a given string to lcd at the current cursor
location.

Arguments:
msg: a null terminated string to print


*****************************************************************/
 while(*msg!='\0')
 {
LCDData(*msg);
msg++;
 }
}

void LCDWriteInt(int val,unsigned int field_length)
{
/***************************************************************
This function writes a integer type value to LCD module

Arguments:
1)int val : Value to print

2)unsigned int field_length :total length of field in which the value is printed
must be between 1-5 if it is -1 the field length is no of digits in the val

****************************************************************/

char str[5]={0,0,0,0,0};
int i=4,j=0;
while(val)
{
str[i]=val%10;
val=val/10;
i--;
}
if(field_length==-1)
while(str[j]==0) j++;
else
j=5-field_length;

if(val<0) LCDData('-');
for(i=j;i<5;i++)
{
LCDData(48+str[i]);
}
}
void LCDGotoXY(uint8_t x,uint8_t y)
{
 if(x<40)
 {
  if(y) x|=0b01000000;
  x|=0b10000000;
  LCDCmd(x);
  }
}


lcd.h

Code: [Select]
#include <avr/io.h>

#ifndef F_CPU
#define F_CPU 1000000UL /* 1 MHz Internal Oscillator */
#endif

#include <util/delay.h>

#include "myutils.h"

#ifndef _LCD_H
#define _LCD_H
/*_________________________________________________________________________________________*/

/************************************************
LCD CONNECTIONS
*************************************************/

#define LCD_DATA D //Port PD0-PD3 are connected to D4-D7

#define LCD_E D //Enable OR strobe signal
#define LCD_E_POS PD4 //Position of enable in above port

#define LCD_RS D
#define LCD_RS_POS PD6

#define LCD_RW D
#define LCD_RW_POS PD5


//************************************************

#define LS_BLINK 0B00000001
#define LS_ULINE 0B00000010



/***************************************************
F U N C T I O N S
****************************************************/



void InitLCD(uint8_t style);
void LCDWriteString(const char *msg);
void LCDWriteInt(int val,unsigned int field_length);
void LCDGotoXY(uint8_t x,uint8_t y);

//Low level
void LCDByte(uint8_t,uint8_t);
#define LCDCmd(c) (LCDByte(c,0))
#define LCDData(d) (LCDByte(d,1))

void LCDBusyLoop();





/***************************************************
F U N C T I O N S     E N D
****************************************************/


/***************************************************
M A C R O S
***************************************************/
#define LCDClear() LCDCmd(0b00000001)
#define LCDHome() LCDCmd(0b00000010);

#define LCDWriteStringXY(x,y,msg) {\
 LCDGotoXY(x,y);\
 LCDWriteString(msg);\
}

#define LCDWriteIntXY(x,y,val,fl) {\
 LCDGotoXY(x,y);\
 LCDWriteInt(val,fl);\
}
/***************************************************/




/*_________________________________________________________________________________________*/
#endif







This will work for most LCD modules and for sure the 2x8, 2x16 and 4x16 but I think as long as the module has a HD44xxx chip on it this will control it.

Matt
Any fool can know. The point is to understand.”
― Albert Einstein