Arduino Projects for Dummies by Brock Craft

I'm working my way thru Arduino Projects for Dummies and ran into an error message doing Chapter 7, Building an Arduino Clock.
I'm at the section labelled "Adding and testing your LCD Display".
The error message follows :
/tmp/.arduinoIDE-unsaved20231126-1782-1azlg6s.l780f/sketch_dec26a/sketch_dec26a.ino: In function 'void setup()':
/tmp/.arduinoIDE-unsaved20231126-1782-1azlg6s.l780f/sketch_dec26a/sketch_dec26a.ino:15:1: error: 'rtc' was not declared in this scope
rtc.begin();
^~~
/tmp/.arduinoIDE-unsaved20231126-1782-1azlg6s.l780f/sketch_dec26a/sketch_dec26a.ino:15:1: note: suggested alternative: 'getc'
rtc.begin();
^~~
getc

exit status 1

Compilation error: 'rtc' was not declared in this scope

Thanks for any help with this.

Please post the exact sketch that gives this error. Are you copy/pasting or retyping as some instructors make ppl do so they see every character go in?

Please say you followed instructions and have also installed any library your learning materials told you would be necessary.

a7

Not many people are going to have that book handy. Post the code you are using. Not the code you copied from, but the actual code in your program. Just in case you made a mistake entering it.

Looks like you didn't include some rtc library.

Seems like you didn't include rtc library. Have you inserted the library to your project?

So you say you're in the section labelled "Adding and testing your LCD display". I'm going to assume that you're trying the first LCD test sketch, shown below:

/* Arduino Projects for Dummies
 * by Brock Craft 
 *
 * Chapter 7: Building an Arduino Clock
 * An alarm clock that uses the Adafruit Industries DS1307 RTC Breakout board
 * and a 16x2 Parallel LCD Display
 *
 * This code just tests the LCD display
 *
 * Uses the default Wire and LiquitCrystal libraries
 * and the Adafruit RTC library
 *
 * v0.1 30.04.2013
 * Adapted from http://www.adafruit.com/products/746
*/

#include <Wire.h>          // I2C Wire Library for communicating with the DS1307 RTC
#include "RTClib.h"        // Date and time functions for the DS1307 RTC connected
#include <LiquidCrystal.h> // Display functions for the LCD Display 

RTC_DS1307 rtc;                         // Create a realtime clock called rtc
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);  // Create an LCD called lcd 

void setup () {
  Wire.begin();      // Enables the communication for the LCD
  rtc.begin();       // Enables the RTC
  lcd.begin(16, 2);  // Enables the LCD
  lcd.print("  It's Alive!");    // Print a message, centered, to the LCD to confirm is working
  delay(1000);                   // Wait a moment so we can read it
  lcd.clear();       // Clear the LCD
}

void loop(){
}

With both these libraries installed:

the example sketch compiles pretty much cleanly, with only a warning about comparing signed and unsigned values in the DateTime constructor in RTClib (which you likely won't even see unless you've got the warning level cranked up like I do).

Since you didn't include your sketch in your message, I suppose it's possible that you're further on and have something closer to the final sketch in Chapter 7, shown below:

/* Arduino Projects for Dummies
 * by Brock Craft 
 *
 * Chapter 7: Building an Arduino Clock
 * An alarm clock that uses the Adafruit Industries DS1307 RTC Breakout board
 * and a 16x2 Parallel LCD Display
 *
 * Uses the default Wire and LiquitCrystal libraries
 * and the Adafruit RTC library
 *
 * v0.1 30.04.2013
 * Adapted from http://www.adafruit.com/products/746
*/

#include <Wire.h>          // I2C Wire Library for communicating with the DS1307 RTC
#include "RTClib.h"        // Date and time functions for the DS1307 RTC connected
#include <LiquidCrystal.h> // Display functions for the LCD Display 

RTC_DS1307 rtc;                         // Create a realtime clock called rtc
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);  // Create an LCD called lcd 

DateTime now;        // Creates a DateTime object called now so that we can read from the RTC module

boolean displayAlarmSet = false;  // Whether we are in the show time mode or show alarm set mode
boolean alarm = false;   // Whether the alarm is set or not
boolean armed = false;   // Whether the alarm is armed or not

int alarmHrs = 12;   // You can set the alarm time in code, here
int alarmMins = 00;

// User input to set alarm time
const int alarmSetPin=6;           // Used to change to alarm set mode
const int incrementAlarmHrsPin=7;  // Used to increment the alarm hours in alarm set mode
const int incrementAlarmMinsPin=8; // Used to increment the alarm minutes in alarm set mode
const int piezoPin = 9;            // Used for the piezoelectric sounder
const int alarmArmedPin=10;        // Use to enable the alarm to go off


void setup () {
  Wire.begin();      // Enables the communication for the LCD
  rtc.begin();       // Enables the RTC
  lcd.begin(16, 2);  // Enables he LCD
  lcd.print("  It's Alive!");    // Print a message, centered, to the LCD to confirm is working
  delay(1000);                    // Wait a moment so we can read it
  lcd.clear();       // Clear the LCD

  // Set several pins for input and output
  pinMode(alarmSetPin, INPUT);   
  pinMode(incrementAlarmHrsPin, INPUT);
  pinMode(incrementAlarmMinsPin, INPUT);
  pinMode(piezoPin, OUTPUT);
  pinMode(alarmArmedPin, INPUT);
  
}

void loop () {
  now = rtc.now(); // Get the current time
 
  int alarmArmed=digitalRead(alarmArmedPin);
  if (alarmArmed==HIGH){
   armed=true;
  } else {
   armed=false;
  }

  // Determine whether to sound the alarm or not
 if(armed){        // If the alarm is armed and...
  if (!alarm){     // If we are not currently sounding the alarm
    checkAlarm();  // Check to see if it is the time it should be triggered
  } 
  else {
    soundAlarm();  // Otherwise, we should be sounding the alarm, so do it.
  }
}
  // Check whether we are in Alarm Set mode
  int setMode = digitalRead(alarmSetPin);  // Read the pin that the switch is on 
  if (setMode==HIGH){      // If the pin is high
    displayAlarmSet=true;  // Set displayAlarmSet true. It's used by updateDisplay to switch between showing alarm or current time
    setAlarm();            // Go read the switches to set the alarm
  }
  else {                   // If we aren't in set mode
    displayAlarmSet=false; // We are not is net mode so make sure the flag is correct
  }

  // Refresh the display
  updateDisplay();
}

// Update the display with either the current time or the time the alarm is set for
void updateDisplay(){
   
   if(displayAlarmSet){   // If we are in alarm set mode, DISPLAY ALARM SET TEXT
    lcd.setCursor(0, 0);  // Set the cursor at the column zero, upper row
    lcd.print("Set alarm time: ");
    lcd.setCursor(4, 1);  // Move the cursor to column four, lower row
    lcd.print(" ");       // Write over digits of the time that was previously displayed
    lcd.setCursor(5, 1);  // Move to the next column so the time will be centered
    if (alarmHrs<10){     // Integers of 0-9 are only one digit. If so...
      lcd.print(0);       // ... add a zero in front of it     
    }  
    lcd.print(alarmHrs);  // Print the current alarm hour
    lcd.setCursor(7, 1);  // Move to the next column
    lcd.print(":");       // And print the colon
    lcd.setCursor(8, 1);  // Move to the next column
    if (alarmMins<10){    // Integers of 0-9 are only one digit. If so...
      lcd.print(0);       // ... add a zero in front of it
    }  
    lcd.print(alarmMins); // Print the current alarm minutes
    lcd.setCursor(10, 1); // Move to the next column
    lcd.print("  ");      // Write spaces over the digits of time previously displayed
  } 
  else {                  // If we are in NOT alarm set mode, DISPLAY CURRENT TIME

    int h = now.hour();   // Get the hours right now and store them in an integer called h
    int m = now.minute(); // Get the minutes right now and store them in an integer called m
    int s = now.second(); // Get the seconds right now and store them in an integer called s

    lcd.setCursor(0, 0);  // Set the cursor at the column zero, upper row...
    if(armed){
      lcd.print("* The time is: ");
    }
    else {
      lcd.print("  The time is: ");  // ...with spaces to clear characters from setting alarm. 
    }
    lcd.setCursor(4, 1);  // Move the cursor to column four, lower row

    if (h<10){            // Add a zero, if necessary, as above
      lcd.print(0); 
    }  
    lcd.print(h);         // Display the current hour  
    lcd.setCursor(6, 1);  // Move to the next column
    lcd.print(":");       // And print the colon
    lcd.setCursor(7, 1);  // Move to the next column
    if (m<10){            // Add a zero, if necessary, as above
      lcd.print(0); 
    }  
    lcd.print(m);         // Display the current minute
    lcd.setCursor(9, 1);  // Move to the next column
    lcd.print(":");       // And print the colon
    lcd.setCursor(10, 1); // Move to the next column
    if (s<10){            // Add a zero, if necessary, as above
      lcd.print(0);
    }  
    lcd.print(s);         // Display the current second
  }

}

// Check whether to sound the alarm
void checkAlarm(){
  if(alarmHrs==now.hour() && alarmMins==now.minute() && now.second()==0){  // If the alarm time is now, and it's zero seconds
    alarm=true;  // set the alarm flag to be true. The next time the main loop executes, the alarm will be activated
  } 
}

// Increment hours or minutes
void setAlarm(){
  int hrs=digitalRead(incrementAlarmHrsPin); 
  int mins=digitalRead(incrementAlarmMinsPin);

  if (hrs==HIGH){    // If the hours switch is pressed
    alarmHrs+=1;     // Increment the hours upward
    delay(200);      // Wait a moment between incrementing the numbers
    if(alarmHrs>23){ // if the hour is over 23, set it back to 0
      alarmHrs=0; 
    }
  }
  if (mins==HIGH){    // If the minutes switch is pressed
    alarmMins+=1;     // Increment the minutes upward
    delay(200);       // Wait a moment between incrementing the numbers
    if(alarmMins>59){ // if the minute is over 59, set it back to 0
      alarmMins=0; 
    }
  }
}

void soundAlarm() {
  float alarmFrequency=1400;  // The value for the alarm tone in Hz
  float period = (1.0 / alarmFrequency) * 1000000;
  long beepDuration=250000;   // the time in microseconds
  long elapsedTime = 0;

  while (elapsedTime < beepDuration) {
    digitalWrite(piezoPin,HIGH);
    delayMicroseconds(period / 2);
    digitalWrite(piezoPin, LOW);
    delayMicroseconds(period / 2);
    elapsedTime += (period);
  }
  digitalWrite(piezoPin, LOW);         
  delayMicroseconds(beepDuration);

  // Listend for either button to be pressed and if so, turn off the alarm
  int hrs=digitalRead(incrementAlarmHrsPin); 
  int mins=digitalRead(incrementAlarmMinsPin);

  if (hrs==HIGH || mins==HIGH){
    alarm=false;
  }
}

which also compiles pretty much cleanly, with only the same warning about comparing signed and unsigned values in the DateTime constructor in RTClib.

Having established that the code in the book still compiles over 10 years and who knows how many library updates later, how about you show your sketch that you're having problems with, properly formatted in a code block, so that someone might have a chance of telling you where you've gone astray?

The first thing is, I don't understand what a code block means.
I copied and pasted the sketch from the book, and I have verified that all the required libraries are installed.
This morning when I went to repeat the test, I did not get any error message, just the fact that nothing appeared on the LCD display.
I've included screenshots of the sketch and the breadboard setup.
Thanks again for all the help.

Instructions suggest that you have a wiring problem.

Alternatively, do you have the same LCD as is used in the code/libraries you are using?

Can you include a photograph of your hardware please.

A code block is code between curly braces { code is here }
you use them on structures like the if instruction.

So code that says:-
if( this == that ) do this one instruction

Suppose you wanted to do more instructions then you would use
if( this == that ) {
do this instruction
and this instruction
and this instruction
and finally this instruction
}

This is pseudo code, you don't actually write it this way, but this is how you can / should think when you are reading code. There should be the same number of {'s and }'s otherwise you will get an error.

2 Likes

Here's the photo of my actual breadboard setup. Realize that the LCD illustration in the book is the mirror image of my setup, i.e., numbers 1 to 16 run in the opposite direction.
Another thing that doesn't make sense to me is the display on the LCD doesn't change at all when I go from one end of the 10K pot to the other! I've never had that happen before. I even tried several other denominations of potentiometer, but they'll do the same. Thanks for all your help.

The wiper on the pot is supposed to go the Vo pin. In your photo, it appears to be going to D7.

In your LiquidCrystal constructor, you have specified pin 12 to be RS, and yet it goes to D6 on the display.

You have also specified pin 11 to be E, and yet it goes to D4 on the display.

You have grounded D5 on the display.

You have specified pin 5 to be D4 (d0 in the constructor), and yet it goes to E on the display.

You have specified pin 4 to be D5 (d1 in the constructor), and yet it goes to R/W on the display.

You have specified pin 3 to be D6 (d2 in the constructor), and yet it goes to RS on the display.

You have specified pin 2 to be D7 (d3 in the constructor), and yet it goes to Vo on the display.

On the bright side, you did hook up Vss and Vdd and the LED backlight properly.

In wiring up my LCD I followed the text in the ebook. See the photo.
As I tried to explain last time, the numbers 1 to 16 on my LCD run from right to left in the photo of my breadboard. But if I follow the directions in the book, the LCD in the picture in the book would have to be numbered in the opposite direction.
Am I to understand that I should just ignore the numbers 1 and 16 on my LCD and wire it according to the picture in the book? Thanks for clarifying this.

Yes, and I didn't understand that the first time you said it. Why do you think this? Is it because the pin labels are upside down, as you look at it.

I think that is where you are going wrong. You are getting hold of the "wrong end of the stick" so to speak.

You need to wire it up according to then physical layout diagram Figure 0708 and check it against the schematic in Figure 0709.

Yes Mike, as I look at my LCD in my photo, the numbers 1 and 16 are upside down.
I did rewire the LCD according to your instructions, and it did work the way it was supposed to.
Too bad the schematic wasn't included in the text, as it generally is. Cuz I do normally double check my setup against the schematic. Here you have to go to the website to download it, and then the printing is so fine that you need a magnifying glass to read it!
My lingering question is, is there an error in the text, or are these LCDs numbered from left to right or right to left, depending on the manufacturer? The ones I got seem to be a no-name brand that I got in my Elegoo super starter kit, and also in their sensor kit.
Thanks again for your help.

No they are the same.
One thing you are forgetting is that the way the board is wired up on the physical layout diagram is upside down. Which gives you the impression of it being numbered backwards.

Glad you got it working.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.