Guys i am trying this project since now hobbyshops sell this. I bought the arduino uno and also the arduino lcd key shield 1602 itead . if i change the lcd id's i get display but having problems with the pressing key code. ANYONE PLEASE WILLING TO HELP OR LOOK AT IT. HERE is the link to the code below.
but having problems with the pressing key code.
Care to describe what the problems are? Care to share the code that is causing the problems?
What i can pick up is:
//*******************************************************************************************
// USER INTERFACE DEFINITIONS
//*******************************************************************************************
// initialise the liquidCrystal Library
// Initialise the LCD using 12,11,10,9,8,7
LiquidCrystal lcd(12,11,10,9,8,7);
i had to change that to
LiquidCrystal(8, 9, 4, 5, 6, 7)
after i did that i got a display instead of a row of blocks.
my other problem would no be
// PINs for user interface buttons - use any
#define KEY_OK_PIN 6
#define KEY_CANCEL_PIN 5
#define KEY_UP_PIN 4
#define KEY_DOWN_PIN 3
// bit flags used in key functions getKeys, waitForKeyPress, waitForKeyRelease
#define KEY_NONE 0
#define KEY_OK 1
#define KEY_CANCEL 2
#define KEY_UP 4
#define KEY_DOWN 8
#define KEYPRESS_ANY B11111111
the project only use up,down,ok,cancel,and none option.
and i dont know how to program the key info since i dont understand how key shield work. i was told plug it into the uno.
Anyone ??
I building this project RCArduino: Lap Timer Build Along Part One
I have following stuff for project the RC IR Lap Timer to build.
Arduino Uno - R3
Arduino LCD Keypad Shield - 1602 ITEAD Shield
IR Receiver 38Khz
IR LED 5mm
Arduino Pro Mini 328 - 3.3V/8MHz
Arduino ScrewShield v1.5
I looking for the changes i need to do for this hardware to work with the follow software.
LapTimerBuildAlongPart1.pde -
// RCArduinoPersonalLapTimer Part 1 by DuaneB is
// licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
// Based on a work at rcarduino.blogspot.com.
#include <avr/pgmspace.h>
#include <EEPROM.h>
#include <LiquidCrystal.h>
#include "laptimes.h"
//*******************************************************************************************
// USER INTERFACE DEFINITIONS
//*******************************************************************************************
// initialise the liquidCrystal Library
// Initialise the LCD using 12,11,10,9,8,7
LiquidCrystal lcd(12,11,10,9,8,7);
// PINs for user interface buttons - use any
#define KEY_OK_PIN 6
#define KEY_CANCEL_PIN 5
#define KEY_UP_PIN 4
#define KEY_DOWN_PIN 3
// bit flags used in key functions getKeys, waitForKeyPress, waitForKeyRelease
#define KEY_NONE 0
#define KEY_OK 1
#define KEY_CANCEL 2
#define KEY_UP 4
#define KEY_DOWN 8
#define KEYPRESS_ANY B11111111
// display width + 1, used by getRamString to copy a PROG_MEM string into ram
#define DISPLAY_ROW_BUFFER_LENGTH 17
//*******************************************************************************************
// Lap Capture definitions
//*******************************************************************************************
#define LAP_CAPTURE_LED 13
#define BUZZER_PIN A0
// minimum and maximum duration of qualifying IR Pulse
#define MIN_PULSE_DURATION 200
#define MAX_PULSE_DURATION 500
// start and end of pulse
uint32_t ulStartPulse;
uint32_t ulEndPulse;
volatile uint32_t ulPulseDuration;
// flags to manage access and pulse edges
volatile uint8_t bIRPulseFlags;
//
volatile uint32_t ulNewLapStartTime;
#define IR_PULSE_START_SET 1
#define IR_PULSE_END_SET 2
//*****************************************************************
// Global Instance of CLapTimes class
//*****************************************************************
CLapTimes gLapTimes(new CEEPROMLapStore());
//////////////////////////////////////////////////////////////////////////////////
//
// doShowSessionSummaries
//
// implements the show session summary menu
// allows the user to scroll up and down through summaries of the recorded sessions
//
//////////////////////////////////////////////////////////////////////////////////
void setup()
{
Serial.begin(9600);
Serial.println("In Setup");
lcd.begin(16, 2);
lcd.print("Lap Timer");
lcd.setCursor(0,1);
lcd.print("Version 0.9 Beta");
delay(3000);
pinMode(KEY_OK_PIN,INPUT);
pinMode(KEY_CANCEL_PIN,INPUT);
pinMode(KEY_UP_PIN,INPUT);
pinMode(KEY_DOWN_PIN,INPUT);
pinMode(LAP_CAPTURE_LED,OUTPUT);
pinMode(BUZZER_PIN,OUTPUT);
digitalWrite(LAP_CAPTURE_LED,LOW);
digitalWrite(BUZZER_PIN,LOW);
showTotals();
Serial.println("Out Setup");
}
//////////////////////////////////////////////////////////////////////////////////
//
// base loop, implements root of menu system
//
// allows the user to scroll up and down through summaries of the recorded sessions
//
//////////////////////////////////////////////////////////////////////////////////
void loop()
{
// lets keep control of the loop
while(true)
{
// wait for a key command to tell us what to do
Serial.println("Beginning Loop");
switch(waitForKeyPress(KEYPRESS_ANY))
{
// start recording
case KEY_OK:
doRecord();
break;
// delete all sessions
case KEY_CANCEL:
doConfirmDeleteSessions();
break;
// scroll through recorded session summaries
case KEY_UP:
case KEY_DOWN:
doShowSessionSummaries();
break;
}
showTotals();
waitForKeyRelease();
}
}
//////////////////////////////////////////////////////////////////////////////////
//
// doRecord
//
// start recording new sessions, update screen every second
// check for new laps
// record new laps
// show lap time for a few seconds at the end of a lap
// update and show new best lap if its a new session best
//
//////////////////////////////////////////////////////////////////////////////////
void doRecord()
{
lap_handle_t currentLapHandle = gLapTimes.createNewSession();
uint32_t ulOldLapStartTime = millis();
lap_time_t bestLapTime = 0XFFFF;
uint32_t ulLastTimeRefresh = millis();
char *pStringTimeBuffer = NULL;
lcd.clear();
lcd.setCursor(0,0);
lcd.print(getRamString(PSTR("Recording")));
attachInterrupt(0,captureLap,CHANGE);
while((getKeys() != KEY_CANCEL) && (currentLapHandle != INVALID_LAP_HANDLE))
{
Serial.println(ulPulseDuration);
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Check for new laps captured
//////////////////////////////////////////////////////////////////////////////////////////////////////
if((IR_PULSE_END_SET|IR_PULSE_START_SET) == bIRPulseFlags)
{
uint32_t ulLastLapDuration = ulNewLapStartTime - ulOldLapStartTime;
ulOldLapStartTime = ulNewLapStartTime;
lap_time_t lapTime = CLapTimes::convertMillisToLapTime(ulLastLapDuration);
gLapTimes.addLapTime(currentLapHandle,lapTime);
currentLapHandle = gLapTimes.moveNext(currentLapHandle);
// new best lap
if(lapTime < bestLapTime)
{
bestLapTime = lapTime;
}
lcd.clear();
lcd.print(getRamString(PSTR("Best Lap ")));
lcd.print(CLapTimes::formatTime(bestLapTime,true));
lcd.setCursor(0,1);
lcd.print(getRamString(PSTR("Last Lap")));
// use this to show lap time
lcd.print(CLapTimes::formatTime(lapTime,true));
// or this to show delta time
//lcd.print(CLapTimes::formatTime(lapTime-bestLapTime,true));
digitalWrite(LAP_CAPTURE_LED,HIGH);
digitalWrite(BUZZER_PIN,HIGH);
delay(400);
if(lapTime == bestLapTime)
{
digitalWrite(LAP_CAPTURE_LED,LOW);
digitalWrite(BUZZER_PIN,LOW);
delay(200);
digitalWrite(LAP_CAPTURE_LED,HIGH);
digitalWrite(BUZZER_PIN,HIGH);
delay(400);
}
digitalWrite(LAP_CAPTURE_LED,LOW);
digitalWrite(BUZZER_PIN,LOW);
// dont look for another lap for 2 seconds
delay(2000);
// give ownership of the shared variables back to the ISR
bIRPulseFlags = 0;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Update screen with current lap time
//////////////////////////////////////////////////////////////////////////////////////////////////////
uint32_t ulCurrentLapTime = millis();
if((ulCurrentLapTime - ulLastTimeRefresh) > 1000)
{
ulLastTimeRefresh = ulCurrentLapTime;
lcd.clear();
if(bestLapTime != 0XFFFF)
{
lcd.print(getRamString(PSTR("Best Lap ")));
lcd.print(CLapTimes::formatTime(bestLapTime,true));
}
else
{
lcd.print(getRamString(PSTR("Recording")));
}
pStringTimeBuffer = CLapTimes::formatTime(CLapTimes::convertMillisToLapTime(ulCurrentLapTime - ulOldLapStartTime),false);
if(pStringTimeBuffer != NULL)
{
lcd.setCursor(0,1);
lcd.print(pStringTimeBuffer);
}
else
{
// If we do not complete a lap for 9m59s display an idle message until a key is pressed
lcd.setCursor(0,1);
lcd.print(getRamString(PSTR("Idle")));
waitForKeyPress(KEYPRESS_ANY);
ulOldLapStartTime = millis();
}
}
}
if(currentLapHandle == INVALID_LAP_HANDLE)
{
lcd.setCursor(0,1);
lcd.print(getRamString(PSTR("Memory Full!")));
}
}
//////////////////////////////////////////////////////////////////////////////////
//
// doConfirmDeleteSessions
//
// Delete all sessions - if we are using storage for the first time we may need
// to call this function to initialise the storage to a known value. The user
// can access this function by pressing cancel on the root menu. This will bring
// up a confirmation message asking the user to press ok to delete all laps.
//
//////////////////////////////////////////////////////////////////////////////////
void doConfirmDeleteSessions()
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print(getRamString(PSTR("OK to Reset")));
lcd.setCursor(0,1);
lcd.print(getRamString(PSTR("Cancel to go Back")));
// we pressed cancel to get here - so lets wait for cancel to be released before we look for more input
waitForKeyRelease();
if(KEY_OK == waitForKeyPress(KEY_OK|KEY_CANCEL))
{
gLapTimes.clearAll();
}
}
//////////////////////////////////////////////////////////////////////////////////
//
// doShowSessionSummaries
//
// implements the show session summary menu
// allows the user to scroll up and down through summaries of the recorded sessions
// user can press ok to enter the session and scroll through the session laps
//
//////////////////////////////////////////////////////////////////////////////////
void doShowSessionSummaries()
{
boolean bFinished = false;
uint8_t nSession = 0;
do
{
lap_handle_t lapHandle = 0;
uint16_t nSessionAverage = 0;
uint16_t nSessionBest = 0;
uint16_t nSessionLapCount = 0;
Serial.println(nSession);
lapHandle = gLapTimes.getSessionHandle(nSession);
lcd.clear();
lcd.setCursor(0,0);
lcd.print(getRamString(PSTR("SNo:")));
lcd.print(nSession);
// if theres no laps for this session or its the first session but it doesnt contain any laps
if(lapHandle == INVALID_LAP_HANDLE || (lapHandle == 0 && gLapTimes.getLapTime(lapHandle)==0))
{
lcd.setCursor(0,1);
lcd.print(getRamString(PSTR("Empty Session")));
}
else
{
Serial.println(lapHandle);
gLapTimes.getSessionSummary(lapHandle,nSessionAverage,nSessionBest,nSessionLapCount);
lcd.print(getRamString(PSTR(" Laps:")));
lcd.print(nSessionLapCount);
lcd.setCursor(0,1);
// Best Lap Time
lcd.print(CLapTimes::formatTime(nSessionBest,true));
// Average Lap Time
lcd.print(" ");
lcd.print(CLapTimes::formatTime(nSessionAverage,true));
}
waitForKeyRelease();
switch(waitForKeyPress(KEYPRESS_ANY))
{
case KEY_UP:
nSession++;
break;
case KEY_DOWN:
nSession--;
break;
case KEY_CANCEL:
bFinished = true;
break;
case KEY_OK:
if(nSessionLapCount != 0)
{
doLapScroll(gLapTimes.getSessionHandle(nSession));
}
break;
}
}while(!bFinished);
}
//////////////////////////////////////////////////////////////////////////////////
//
// showTotals shows the number of sessions, laps and laps left
// as the root of the menu
//
//////////////////////////////////////////////////////////////////////////////////
void showTotals()
{
Serial.println(getRamString(PSTR("Entering showTotals")));
uint16_t nSessions = 0;
uint16_t nLapsRecorded = 0;
uint16_t nLapsRemaining = 0;
gLapTimes.getTotals(nSessions,nLapsRecorded,nLapsRemaining);
lcd.clear();
lcd.print(getRamString(PSTR("Sessions=")));lcd.print(nSessions);
lcd.setCursor(0, 1);
lcd.print(getRamString(PSTR("Laps=")));lcd.print(nLapsRecorded);
lcd.print(getRamString(PSTR("Left=")));lcd.print(nLapsRemaining);
Serial.println(getRamString(PSTR("Leaving showSummaryData")));
}
//////////////////////////////////////////////////////////////////////////////////
//
// doLapScroll
//
// scroll through the laps within a session, startLapHandle points to the start
//
//////////////////////////////////////////////////////////////////////////////////
void doLapScroll(lap_handle_t startLapHandle)
{
boolean bFinished = false;
lap_handle_t currentLapHandle = startLapHandle;
lap_handle_t tmpLap = currentLapHandle;
uint8_t nLapNumber = 0;
do
{
lcd.clear();
lcd.setCursor(0,0);
if(tmpLap == INVALID_LAP_HANDLE)
{
lcd.print(getRamString(PSTR("No More Laps")));
delay(2000);
lcd.clear();
}
lcd.print(getRamString(PSTR("Lap No.")));
lcd.print(nLapNumber);
lcd.setCursor(0,1);
if(currentLapHandle != INVALID_LAP_HANDLE)
{
char *pTime = CLapTimes::formatTime(gLapTimes.getLapTime(currentLapHandle),true);
lcd.setCursor(0,1);
lcd.print(pTime);
}
waitForKeyRelease();
uint8_t sKey = waitForKeyPress(KEYPRESS_ANY);
switch(sKey)
{
case KEY_DOWN:
case KEY_UP:
(sKey == KEY_UP) ? tmpLap = gLapTimes.moveNext(currentLapHandle) : tmpLap = gLapTimes.movePrevious(currentLapHandle);
if(tmpLap != INVALID_LAP_HANDLE)
{
if(gLapTimes.getLapTime(tmpLap) != EMPTY_LAP_TIME)
{
currentLapHandle = tmpLap;
(sKey == KEY_UP) ? nLapNumber++ : nLapNumber--;
}
else
{
tmpLap = INVALID_LAP_HANDLE;
}
}
break;
case KEY_OK:
tmpLap = currentLapHandle;
break;
case KEY_CANCEL:
bFinished = true;
break;
}
}
while(!bFinished);
}
//////////////////////////////////////////////////////////////////////////////////
//
// Key related helpers
//
// getKeys - pole keys
// waitForKeyPress - block waiting for keys based on a mask
// waitForKeyRelease - block waiting until no kets are pressed
//
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//
// getKeys
//
// read the inputs and create a bit mask based on the buttons pressed
// this does not block, need to review whether we should make this block, in most
// cases we loop waiting for a key, sometimes we also loop waiting for no key
// could put both options here with an input parameter.
//
//////////////////////////////////////////////////////////////////////////////////
short getKeys()
{
// Use bit flags for keys, we may have a future use for
// combined key presses
short sKeys = KEY_NONE;
if(digitalRead(KEY_UP_PIN) == LOW)
{
sKeys |= KEY_UP;
}
if(digitalRead(KEY_DOWN_PIN) == LOW)
{
sKeys |= KEY_DOWN;
}
if(digitalRead(KEY_OK_PIN) == LOW)
{
sKeys |= KEY_OK;
}
if(digitalRead(KEY_CANCEL_PIN) == LOW)
{
sKeys |= KEY_CANCEL;
}
return sKeys;
}
//////////////////////////////////////////////////////////////////////////////////
//
// waitForKeyRelease
//
// we can enter a function while the activating key is still pressed, in the new
// context the key can have a different purpose, so lets wait until it is released
// before reading it as pressed in the new context
//
//////////////////////////////////////////////////////////////////////////////////
void waitForKeyRelease()
{
do
{
// do nothing
}
while(getKeys() != KEY_NONE);
// debounce
delay(20);
}
//////////////////////////////////////////////////////////////////////////////////
//
// waitForKeyPress
//
// convenience function, loop doing nothing until one of the sKeyMask keys is
// pressed
//
//////////////////////////////////////////////////////////////////////////////////
uint8_t waitForKeyPress(uint8_t sKeyMask)
{
uint8_t sKey = KEY_NONE;
do
{
sKey = getKeys() & sKeyMask;
}
while(sKey == KEY_NONE);
digitalWrite(BUZZER_PIN,HIGH);
delay(20);
digitalWrite(BUZZER_PIN,LOW);
return sKey;
}
// A helper that copies a string from program memory into a buffer in sram
// we need this because our code can only use strings held in sram
// this fetches strings that are stored in program memory as and when
// we need them.
char * getRamString(PGM_P pString)
{
// NEED TO ADD A CHECK HERE TO ENSURE pString < DISPLAY_ROW_LENGTH
static char pBuffer[DISPLAY_ROW_BUFFER_LENGTH];
return strcpy_P(pBuffer,pString);
}
//////////////////////////////////////////////////////////////////////////////////
//
// captureLap
//
// In part 1 we will fake a lap if we detect INT0 being pulled low
// In part 2 we will add a simple IR Detector which you can test with
// a TV Remote
// In part three we will add a more complex IR Detector which will allow
// us to detect a transponder and ignore any other IR Signal
//////////////////////////////////////////////////////////////////////////////////
void captureLap()
{
uint8_t bLapCaptureState = digitalRead(2);
digitalWrite(LAP_CAPTURE_LED,bLapCaptureState);
if(bLapCaptureState == LOW)
{
bIRPulseFlags = (IR_PULSE_END_SET|IR_PULSE_START_SET);
ulNewLapStartTime = millis();
}
else
{
bIRPulseFlags = 0;
}
}
Hope this helps a abit. I copied the code from here
All other info can be found there.
Hi,
Can you please post a copy of your sketch, using code tags?
They are made with the </> icon in the reply Menu.
See section 7 http://forum.arduino.cc/index.php/topic,148850.0.html
If your sketch is too big, use REPLY rather than QUICK REPLY and it has an attachment facility, so you can post your sketch as an attachment, but try code tags first.
Tom..... ![]()
Hi i will try..I have non experience in software or applications. So will try..
I am gonna try attached the code it is to big. Hope this help. I am really stupid when it come to this things.
I had to change the LiquidCrystal to LiquidCrystal lcd(8, 9, 4, 5, 6, 7); to get a display.
The keys code is my problem.
LapTimerBuildAlongPart1.ino (16.7 KB)
LapTimes.cpp (9.52 KB)
LapTimes.h (3.39 KB)
Strings.h (93 Bytes)
why is no one placing there code inside the [ code ] tags ?
void setup()
{
Serial.begin(9600);
Serial.println("In Setup");
lcd.begin(16, 2);
lcd.print("Lap Timer");
lcd.setCursor(0,1);
lcd.print("Version 0.9 Beta");
delay(3000);
pinMode(KEY_OK_PIN,INPUT);
pinMode(KEY_CANCEL_PIN,INPUT);
pinMode(KEY_UP_PIN,INPUT);
pinMode(KEY_DOWN_PIN,INPUT);
pinMode(LAP_CAPTURE_LED,OUTPUT);
pinMode(BUZZER_PIN,OUTPUT);
digitalWrite(LAP_CAPTURE_LED,LOW);
digitalWrite(BUZZER_PIN,LOW);
showTotals();
digitalWrite(2,HIGH);
Serial.println("Out Setup");
}
//////////////////////////////////////////////////////////////////////////////////
//
// base loop, implements root of menu system
//
// allows the user to scroll up and down through summaries of the recorded sessions
//
//////////////////////////////////////////////////////////////////////////////////
void loop()
{
// lets keep control of the loop
while(true)
{
// wait for a key command to tell us what to do
Serial.println("Beginning Loop");
switch(waitForKeyPress(KEYPRESS_ANY))
{
// start recording
case KEY_OK:
doRecord();
break;
// delete all sessions
case KEY_CANCEL:
doConfirmDeleteSessions();
break;
// scroll through recorded session summaries
case KEY_UP:
case KEY_DOWN:
doShowSessionSummaries();
break;
}
showTotals();
waitForKeyRelease();
}
}
I need code for keys to use with Arduino Key Shield 1602 ITEAD
Is this better !!