NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Microcontroller Programming » Total noob in need of LCD help Atmega328p

April 10, 2012
by ram_engineerin_2012
ram_engineerin_2012's Avatar

I am trying to do a simple up/down counter with LCD output on my atmega328p for my senior project and have no idea how to really initialize and use it, nor connect it. I've gone over sample programs and looked at the code that was given to me when I purchased our MC kit from Nerdkits.com. If someone could tell me what I'm doing wrong and how to fix it, I would be greatly appreciative. Please, be brutally honest with me if you need to. This is my first attempt at doing any AVR work and the only other microcontrollers/microprocessors I've had experience with are Motorla and Intel-based while strictly using assembly, not C. If it helps, this program was done in the newest version of AVRstudio and I will also include a semi-current image of my schematic, which was done in Proteus. Thanks for any and all help you can give me.

Sorry about my formatting. I just C&P my code here

include <avr/io.h> include "C:Usersghost_117DesktopClass notesEE4220ResearchCode sampleslibnerdkitslcd.c" include "C:Usersghost_117DesktopClass notesEE4220ResearchCode sampleslibnerdkitslcd.h" include "C:Usersghost_117DesktopClass notesEE4220ResearchCode sampleslibnerdkitsdelay.c" include "C:Usersghost_117DesktopClass notesEE4220ResearchCode sampleslibnerdkitsdelay.h" include "C:Usersghost_117DesktopClass notesEE4220ResearchCode sampleslibnerdkitsuart.c" include "C:Usersghost_117DesktopClass notesEE4220ResearchCode sampleslibnerdkitsuart.h"

int main(void) { lcd_init(); FILE lcd_stream = FDEV_SETUP_STREAM(lcd_putchar, 0, _FDEV_SETUP_WRITE);

unsigned char i;
int x;
DDRD = 0x00;
DDRC = 0xFF;

PORTC = 0x00;

while(1)
{
  x = 0;

  i = PIND;

  PORTC = i;

  if (PIND0){
            ++x;
            fprintf_P(&lcd_stream, PSTR("Amount in lot: %d"), x);
            }

  if (PIND1){
            --x;
            fprintf_P(&lcd_stream, PSTR("Amount in lot: %d"), x);
            }

}
return 1;

}

here is the schematic:

Alt Text

April 10, 2012
by pcbolt
pcbolt's Avatar

Let me post your code first...

#include <avr/io.h>
#include "C:\Users\ghost_117\Desktop\Class\notes\EE4220\Research\Code\samples\libnerdkits\lcd.c"
#include "C:\Users\ghost_117\Desktop\Class\notes\EE4220\Research\Code\samples\libnerdkits\lcd.h"
#include "C:\Users\ghost_117\Desktop\Class\notes\EE4220\Research\Code\samples\libnerdkits\delay.c"
#include "C:\Users\ghost_117\Desktop\Class\notes\EE4220\Research\Code\samples\libnerdkits\delay.h"
#include "C:\Users\ghost_117\Desktop\Class\notes\EE4220\Research\Code\samples\libnerdkits\uart.c"
#include "C:\Users\ghost_117\Desktop\Class\notes\EE4220\Research\Code\samples\libnerdkits\uart.h"

int main(void) {
  lcd_init();
  FILE lcd_stream = FDEV_SETUP_STREAM(lcd_putchar, 0, _FDEV_SETUP_WRITE);

  unsigned char i;
  int x;
  DDRD = 0x00;
  DDRC = 0xFF;

  PORTC = 0x00;

  while(1) {
    x = 0;
    i = PIND;
    PORTC = i;
    if (PIND0){
      ++x;
      fprintf_P(&lcd_stream, PSTR("Amount in lot: %d"), x);
    }
    if (PIND1){
      --x;
      fprintf_P(&lcd_stream, PSTR("Amount in lot: %d"), x);
    }
  }
  return 1;
}

On lines 24 and 28, you can't access individual pins using that code. Since you're dealing with 8-bit values you need to mask the register value to test the pins. Use this code instead...

if (PIND & (1<<PD0)) {

And

if (PIND & (1<<PD1)) {

I don't know if you want to re-assign x to 0 each time through the while loop (maybe just before? ). You most likely will need one or more of the following "includes"...

#include <avr/pgmspace.h>
#include <inttypes.h>

I can't see the left side of your schematic...is the UART/USB cable hooked up to PD0 and PD1 as well as your input buttons? I'm assuming you did not show the LCD data connections on your diagram and it's been tested.

April 11, 2012
by Ralphxyz
Ralphxyz's Avatar

Nice schematic, you are not showing a 1k resistor or pot on VEE.

Ralph

April 11, 2012
by ram_engineerin_2012
ram_engineerin_2012's Avatar

@pcbolt I'm not going to need to set x to 0 at any time, unless the system turns off. The project we're developing is a constant on parking lot attendant that counts the number of vehicles going in and out of a lot and will show the current amount and if the lot is full on LCD. Eventually we will be using Xbees to connect to a computer and have the values available in a database that can be accessed via Android app. As for the UART/USB cable, I don't fully understand what you mean. I'm very new to all of this and this is my first real experience with self programming a MC.

@Ralphxyz Thanks. I use Proteus for all PCB design on this project, as it is one of our guidelines. As for the 1k resistor on VEE, where do I connect to? Does this also go to my main power source or does it connect to another part of my MC?

April 11, 2012
by pcbolt
pcbolt's Avatar

The UART/USB cable is how the Nerdkits gets programmed directly from a PC. I guess you use another method. Many of your questions can be answered in the Nerdkit guide found Here. It will tell you how to hook up the LCD resistor Ralph mentioned.

April 11, 2012
by ram_engineerin_2012
ram_engineerin_2012's Avatar

@pcbolt oh ok I get you now. Yeah, people recommended we use the usb version of the STK500 to program the MC through AVRstudio. The one we have is the avrisp mkii if I remember correctly. However, all the testing I'm doing right now is strictly through simulation, so I load the .hex file directly into the MC in Proteus. I guess I really need to pour over the connections so the program works properly. I'll let y'all know if I get things right, as I'm in the middle of class right now.

April 11, 2012
by ram_engineerin_2012
ram_engineerin_2012's Avatar

So I tried adding the code that pcbolt recommended and added a few extra lines for uart and a couple of include lines. I also connected the pins on the LCD in my schematic but I still can't seem to get it to work. What could I be missing?

#include <stdio.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <inttypes.h>
#include "C:\Users\ghost_117\Desktop\Class notes\EE4220\Research\Code samples\libnerdkits\lcd.c"
#include "C:\Users\ghost_117\Desktop\Class notes\EE4220\Research\Code samples\libnerdkits\lcd.h"
#include "C:\Users\ghost_117\Desktop\Class notes\EE4220\Research\Code samples\libnerdkits\delay.c"
#include "C:\Users\ghost_117\Desktop\Class notes\EE4220\Research\Code samples\libnerdkits\delay.h"
#include "C:\Users\ghost_117\Desktop\Class notes\EE4220\Research\Code samples\libnerdkits\uart.c"
#include "C:\Users\ghost_117\Desktop\Class notes\EE4220\Research\Code samples\libnerdkits\uart.h"

int main(void){

lcd_init();
FILE lcd_stream = FDEV_SETUP_STREAM(lcd_putchar, 0, _FDEV_SETUP_WRITE);
lcd_home();

uart_init();
FILE uart_stream = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);
stdin = stdout = &uart_stream;

unsigned char i;
int x;
DDRD = 0x00;
DDRC = 0xFF;

PORTC = 0x00;

while(1)
{
  x = 0;

  i = PIND;

  PORTC = i;

  if (PIND & (1<<PIND0)){
                         ++x;
                         fprintf_P(&lcd_stream, PSTR("Amount in lot: %d"), x);
                        }

  if (PIND & (1<<PIND1)){
                         --x;
                         fprintf_P(&lcd_stream, PSTR("Amount in lot: %d"), x);
                        }

}
return 1;

}

Alt Text

April 11, 2012
by pcbolt
pcbolt's Avatar

I can't be certain, but when you execute "uart_init()", you are setting up pins PD0 and PD1 as Tx and Rx serial ports. You could try using PB0 and PB1 as your input pins. Then change all occurrences of DDRD, PIND, PD0, PD1 to DDRB, PINB, PB0, PB1 respectively. Also, you are still assigning x to 0 each time you loop through the code. The code in the "if" tests should be PD1/PD0 not PIND1/PIND0...(or PB1/PB0 if you make the pin change).

April 11, 2012
by ram_engineerin_2012
ram_engineerin_2012's Avatar

Holy crap, I got it working!! I need to work out some bugs (i.e. debouncing circuits and LCD formatting) but it's working!! Thank you all for your help!!

April 11, 2012
by pcbolt
pcbolt's Avatar

LOL

What did you do?!?

April 12, 2012
by ram_engineerin_2012
ram_engineerin_2012's Avatar

@pcbolt It was exactly as you said! Using port B rather than D solved a whole mess of problems and using your version of masking helped with the enabling of each pin. The output is still a little messy, but I feel that is more the circuitry than the program. I also initialized X=0 OUTSIDE of the main while(1) loop, so that the system begins at 0 and will count from there. You have no idea how much all this help has mean to me. I've been struggling to see if I could learn all of this by myself for the past month but I had just given up hope. I'm so glad these forums are here for when a total newbie has problems and great forum members are there to help out!

April 18, 2012
by ram_engineerin_2012
ram_engineerin_2012's Avatar

Ok, I take what I said back. Even with trying debouncing and even rewriting code, I cannot get the system to not count by 5. Every button press adds by 5 and I have tried messing with voltage using resistors and even lowering the system voltage. What could I be doing wrong?

/*
 * Senior_Redux.c
 *
 * Created: 3/30/2012 12:23:08 PM
 *  Author: ghost_117
 *
 */

#include <stdio.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <inttypes.h>
#include "C:\Users\ghost_117\Desktop\Class notes\EE4220\Research\Code samples\libnerdkits\lcd.c"
#include "C:\Users\ghost_117\Desktop\Class notes\EE4220\Research\Code samples\libnerdkits\lcd.h"
#include "C:\Users\ghost_117\Desktop\Class notes\EE4220\Research\Code samples\libnerdkits\delay.c"
#include "C:\Users\ghost_117\Desktop\Class notes\EE4220\Research\Code samples\libnerdkits\delay.h"
#include "C:\Users\ghost_117\Desktop\Class notes\EE4220\Research\Code samples\libnerdkits\uart.c"
#include "C:\Users\ghost_117\Desktop\Class notes\EE4220\Research\Code samples\libnerdkits\uart.h"

int main(void)
{
    lcd_init();
    FILE lcd_stream = FDEV_SETUP_STREAM(lcd_putchar, 0, _FDEV_SETUP_WRITE);
    lcd_home();

    uart_init();
    FILE uart_stream = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);
    stdin = stdout = &uart_stream;

    unsigned char i;
    int x = 0;
    DDRB = 0x00;
    DDRC = 0xFF;

    PORTC = 0x00;

    while(1)
    {

      i = PINB;

      PORTC = i;

      if (PINB & (1<<PB0)){
                             ++x;
                             fprintf_P(&lcd_stream, PSTR("Amt in lot:%d\n"), x);
                            }

      if (PINB & (1<<PB1)){
                             --x;
                             fprintf_P(&lcd_stream, PSTR("Amt in lot:%d\n"), x);
                            }

    }
    return 1;
}
April 18, 2012
by ram_engineerin_2012
ram_engineerin_2012's Avatar

Sorry, I forgot to include the schematic:

alt image text

April 18, 2012
by pcbolt
pcbolt's Avatar

ram -

I think the first thing I would try is to add a couple of variables to keep track of the button states (up = 0 and down = 1). Then you could execute the increment code only when the button has gone through a complete up/down/up cycle. For instance, after line 32 ("int x = 0;") declare two new variables;

uint8_t pb0_state = 0, pb1_state = 0;

Then change your "if" block to;

if (PINB & (1<<PB0)){       // is button down
  if (pb0_state == 0){      // was button up before - if not do nothing
    ++x;
    fprintf_P(&lcd_stream, PSTR("Amt in lot:%d\n"), x);
    pb0_state = 1;          // set button state to down
  }
}
else {                      // button is up
  pb0_state = 0;            // reset button state to up
}

Do the same with the other "if" block (just use "pb1_state" instead). If you still have problems, you may have to include some kind of count variable to cut down on any remaining debouncing.

April 18, 2012
by ram_engineerin_2012
ram_engineerin_2012's Avatar

@pcbolt, you are a coding god! That is exactly what was needed to fix the program. Now the system counts up and down properly without any bouncing of the switch or extra addition being done. I am forever in your debt!!!

April 18, 2012
by pcbolt
pcbolt's Avatar

@ram -

No problem, bud. I'm a puzzle freak (electronics, coding, crosswords, sudoku, etc.) so it's rewarding in a selfish way. I just hope I don't cross the Nerdkits line of "learn by doing". I don't want to deprive someone of learning by "giving" them them the answers but sometimes all it takes is a little push in the right direction and off you go.

April 19, 2012
by ram_engineerin_2012
ram_engineerin_2012's Avatar

@pcbolt No, believe me, I'm actually figuring out what I'm doing as you show me what is wrong. So don't worry about the "learning by doing" thing. This is my first time really working with AVR controllers, or microcontrollers in general, so I've been asking friends and colleagues for all the help I need. I do have another question though. Is it absolutely necessary to define the CPU clock frequency in the #include section or will it default to full speed? Also, now that I flashed my microcontroller, it doesn't do anything at all like it does in my simulation and me and my teammate have triple checked the wiring to make sure it is right and we are stumped. Could it be that simple as setting the clock and it will run, because we tried using

#include F_CPU 8000000UL

as the way to define the clock but I get an error in AVRStudio that says

#include expects "FILENAME" or <FILENAME>

What could be wrong?

April 19, 2012
by pcbolt
pcbolt's Avatar

Hi ram -

You don't "include" the clock frequency, you just "define" it, and it should be set to whatever crystal or oscillator you are using. The one provided in the Nerdkit is 14745600. You define it using this directive (place it just above or below the includes):

#define F_CPU 14745600
April 20, 2012
by ram_engineerin_2012
ram_engineerin_2012's Avatar

Hey bolt,

I actually used the internal clock and defined it when flashing the chip using the STK500. I set it to the standard 8Mhz and scaled it by 1024 by messing with register TCCR1B. Now that I did that, everything runs swimmingly. Bolt, you have been a good friend and I'm glad to have met you on here to help me out. Couldn't have done this without you!

Post a Reply

Please log in to post a reply.

Did you know that the Timer/Counter modules on the microcontroller can be configured to output a PWM (Pulse Width Modulation) signal? Learn more...