A variable not declared in scope error!

Hi Guys,

I’ve got a bug in my program and can’t for the life of me work out my it is giving me the error:

'sec’was not declared in scope

Here is my code:

#include <SPI.h>
#include <Wire.h>
#include <Dhcp.h>
#include <Dns.h>
#include <Ethernet.h>
#include <EthernetClient.h>
#include <EthernetServer.h>
#include <EthernetUdp.h>
#include <util.h>


// Enter a MAC address for your controller below.
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
IPAddress timeServer(132, 163, 4, 101); // time-a.timefreq.bldrdoc.gov NTP server char timeServer[]="time.nist.gov";// time.nist.gov NTP server or use ip(129, 6, 15, 28)
unsigned int localPort = 8888;// local port to listen for UDP packets
const int NTP_packetSize = 48;// NTP time stamp is in the first 48 bytes of the message
byte packetBuffer[NTP_packetSize]; //buffer to hold incoming and outgoing packets 
const int DS3232_I2C_Address=0x68;


// A UDP instance to let us send and receive packets over UDP
EthernetUDP Udp;

void setup() 
{
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) 
  {
    ; // wait for serial port to connect. Needed for Leonardo only
  }
  Wire.begin();
  // start Ethernet and UDP
  if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");
    // no point in carrying on, so do nothing forevermore:
    for(;;)
      ;
  }
  Udp.begin(localPort);
  sendNTPpacket(timeServer); // send an NTP packet to a time server
  // wait to see if a reply is available
  delay(1000);  
  if ( Udp.parsePacket() ) {  
    // We've received a packet, read the data from it
    Udp.read(packetBuffer,NTP_packetSize);  // read the packet into the buffer
    //the timestamp starts at byte 40 of the received packet and is four bytes,
    // or two words, long. First, esxtract the two words:
    unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
    unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);  
    // combine the four bytes (two words) into a long integer
    // this is NTP time (seconds since Jan 1 1900):
    unsigned long secsSince1900 = highWord << 16 | lowWord;  
    Serial.print("Seconds since Jan 1 1900 = " );
    Serial.println(secsSince1900);               
    // now convert NTP time into everyday time:
    Serial.print("Unix time = ");
    // Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
    const unsigned long seventyYears = 2208988800UL;     
    // subtract seventy years:
    unsigned long epoch = secsSince1900 - seventyYears;  
    // print Unix time:
    Serial.println(epoch);                               
    // print the hour, minute and second:
    Serial.print("The UTC time is ");       // UTC is the time at Greenwich Meridian (GMT)
    Serial.print((epoch  % 86400L) / 3600); // print the hour (86400 equals secs per day)
    Serial.print(':');  
    if ( ((epoch % 3600) / 60) < 10 ) {
      // In the first 10 minutes of each hour, we'll want a leading '0'
      Serial.print('0');
    }
    Serial.print((epoch  % 3600) / 60); // print the minute (3600 equals secs per minute)
    Serial.print(':'); 
    if ( (epoch % 60) < 10 ) {
      // In the first 10 seconds of each minute, we'll want a leading '0'
      Serial.print('0');
    }
    Serial.println(epoch %60); // print the second 
  }
  byte secs = byte(epoch%60L);
  byte mins = byte((epoch%3600L)/60L);
  byte hrs = byte((epoch%86400L)/3600L);
  setDS3232time(secs, mins, hrs, 7, 3, 7, 13);   // set DS3232 seconds, minutes, hours, day of week, date, month, year
}


void loop() 
{
  // put your main code here, to run repeatedly:
}

// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
  return ( (val/10*16) + (val%10) );
}

// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
  return ( (val/16*10) + (val%16) );
}

void setDS3232time(byte second, byte minute, byte hour, byte dayOfWeek, byte dayOfMonth, byte month, byte year)
// sets time and date data to DS3232
{
  Wire.beginTransmission(DS3232_I2C_Address);  
  Wire.write(0x00); // sends 00h - seconds register
  Wire.write(decToBcd(second));     // set seconds
  Wire.write(decToBcd(minute));     // set minutes
  Wire.write(decToBcd(hour));       // set hours
  Wire.write(decToBcd(dayOfWeek));  // set day of week (1=Sunday, 7=Saturday)
  Wire.write(decToBcd(dayOfMonth)); // set date (1~31)
  Wire.write(decToBcd(month));      // set month
  Wire.write(decToBcd(year));       // set year (0~99)
  Wire.endTransmission();
}

// send an NTP request to the time server at the given address 
unsigned long sendNTPpacket(IPAddress &address)
{
  // set all bytes in the buffer to 0
  memset(packetBuffer, 0, NTP_packetSize); // standard C function
  // Initialize values needed to form NTP request
  // (see URL above for details on the packets)
  //Serial.println("2");
  packetBuffer[0] = 0b11100011;   // LI, Version, Mode
  packetBuffer[1] = 0;     // Stratum, or type of clock
  packetBuffer[2] = 6;     // Polling Interval
  packetBuffer[3] = 0xEC;  // Peer Clock Precision
  // 8 bytes of zero for Root Delay & Root Dispersion
  packetBuffer[12]  = 49; 
  packetBuffer[13]  = 0x4E;
  packetBuffer[14]  = 49;
  packetBuffer[15]  = 52;

  // all NTP fields have been given values, now
  // you can send a packet requesting a timestamp:         
  Udp.beginPacket(address, 123); //NTP requests are to port 123
  Udp.write(packetBuffer,NTP_packetSize);
  Udp.endPacket();
}

I get the error on the line:

setDS3232time(secs, mins, hrs, 7, 3, 7, 13);

Basically I’m trying to sync my RTC (Real Time Clock) with a NTP server. I’ve got the code working in principle i.e. I can get the time of the NTP server and can write the time to the RTC if I manually enter values in the function “setDS3232time” for secs, mins and hrs variables.

Normally I can find these types of errors pretty easily but I can’t see why its saying I haven’t declared them when I have in the setup loop. Actually they are declared just before I make the function call.

Can anyone see why I getting this error?

Cheers

Adam

On my Arduino IDE 1.0.5 the error is

sketch_aug03a.ino: In function 'void setup()':
sketch_aug03a:80: error: 'epoch' was not declared in this scope

and is at line:

 byte secs = byte(epoch%60L);

Because you declare epoch under the if() scope:

if ( Udp.parsePacket() ) {  
...
    unsigned long epoch = secsSince1900 - seventyYears;  
...
}
byte secs = byte(epoch % 60L);      // epoch out of scope

epoch is declared within the if block " if ( Udp.parsePacket() ) { " - it can’t be used outside it.

You will have to declare it before that block, but set the value within the block.

Thanks guys for your input.

I was under the impression if you declare variables within a function you can use them anyware in the function, but that function only. Did’t know that if you declare variables inside Control Structures they can’t be used elsewhere in the function.

Knowing this little piece of knowledge has really helped me out a lot.

Thanks again and it now all works.

I’ve posted the code below because someone may find it useful.

I’m using a DS3232 RTC module available from Freetronics and the datasheet is attached. The controller is a EtherMega also available from Freetronics.

Use this code for setting the time on the RTC via a NTP server. Run this one first:

#include <SPI.h>
#include <Wire.h>
#include <Dhcp.h>
#include <Dns.h>
#include <Ethernet.h>
#include <EthernetClient.h>
#include <EthernetServer.h>
#include <EthernetUdp.h>
#include <util.h>


// Enter a MAC address for your controller below.
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
IPAddress timeServer(132, 163, 4, 101); // time-a.timefreq.bldrdoc.gov NTP server char timeServer[]="time.nist.gov";// time.nist.gov NTP server or use ip(129, 6, 15, 28)
unsigned int localPort = 8888;// local port to listen for UDP packets
const int NTP_packetSize = 48;// NTP time stamp is in the first 48 bytes of the message
byte packetBuffer[NTP_packetSize]; //buffer to hold incoming and outgoing packets 
const int DS3232_I2C_Address=0x68;


// A UDP instance to let us send and receive packets over UDP
EthernetUDP Udp;

void setup() 
{
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) 
  {
    ; // wait for serial port to connect. Needed for Leonardo only
  }
  Wire.begin();
  // start Ethernet and UDP
  if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");
    // no point in carrying on, so do nothing forevermore:
    for(;;)
      ;
  }
  Udp.begin(localPort);
  sendNTPpacket(timeServer); // send an NTP packet to a time server
  // wait to see if a reply is available
  delay(1000);
  unsigned long epoch; 
  if ( Udp.parsePacket() ) {  
    // We've received a packet, read the data from it
    Udp.read(packetBuffer,NTP_packetSize);  // read the packet into the buffer
    //the timestamp starts at byte 40 of the received packet and is four bytes,
    // or two words, long. First, esxtract the two words:
    unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
    unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);  
    // combine the four bytes (two words) into a long integer
    // this is NTP time (seconds since Jan 1 1900):
    unsigned long secsSince1900 = highWord << 16 | lowWord;  
    Serial.print("Seconds since Jan 1 1900 = " );
    Serial.println(secsSince1900);               
    // now convert NTP time into everyday time:
    Serial.print("Unix time = ");
    // Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
    const unsigned long seventyYears = 2208988800UL;     
    // subtract seventy years:
    epoch = secsSince1900 - seventyYears;  
    // print Unix time:
    Serial.println(epoch);                               
    // print the hour, minute and second:
    Serial.print("The UTC time is ");       // UTC is the time at Greenwich Meridian (GMT)
    Serial.print((epoch  % 86400L) / 3600); // print the hour (86400 equals secs per day)
    Serial.print(':');  
    if ( ((epoch % 3600) / 60) < 10 ) {
      // In the first 10 minutes of each hour, we'll want a leading '0'
      Serial.print('0');
    }
    Serial.print((epoch  % 3600) / 60); // print the minute (3600 equals secs per minute)
    Serial.print(':'); 
    if ( (epoch % 60) < 10 ) 
    {
      // In the first 10 seconds of each minute, we'll want a leading '0'
      Serial.print('0');
    }
    Serial.println(epoch %60); // print the second 
  }
  byte secs = epoch%60L;
  byte mins = (epoch%3600L)/60L;
  byte hrs = (epoch%86400L)/3600L;
  setDS3232time(secs, mins, hrs, 7, 3, 7, 13);   // set DS3232 seconds, minutes, hours, day of week, date, month, year
}


void loop() 
{
  // put your main code here, to run repeatedly:
}

// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
  return ( (val/10*16) + (val%10) );
}

// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
  return ( (val/16*10) + (val%16) );
}

void setDS3232time(byte second, byte minute, byte hour, byte dayOfWeek, byte dayOfMonth, byte month, byte year)
// sets time and date data to DS3232
{
  Wire.beginTransmission(DS3232_I2C_Address);  
  Wire.write(0x00); // sends 00h - seconds register
  Wire.write(decToBcd(second));     // set seconds
  Wire.write(decToBcd(minute));     // set minutes
  Wire.write(decToBcd(hour));       // set hours
  Wire.write(decToBcd(dayOfWeek));  // set day of week (1=Sunday, 7=Saturday)
  Wire.write(decToBcd(dayOfMonth)); // set date (1~31)
  Wire.write(decToBcd(month));      // set month
  Wire.write(decToBcd(year));       // set year (0~99)
  Wire.endTransmission();
}

// send an NTP request to the time server at the given address 
unsigned long sendNTPpacket(IPAddress &address)
{
  // set all bytes in the buffer to 0
  memset(packetBuffer, 0, NTP_packetSize); // standard C function
  // Initialize values needed to form NTP request
  // (see URL above for details on the packets)
  //Serial.println("2");
  packetBuffer[0] = 0b11100011;   // LI, Version, Mode
  packetBuffer[1] = 0;     // Stratum, or type of clock
  packetBuffer[2] = 6;     // Polling Interval
  packetBuffer[3] = 0xEC;  // Peer Clock Precision
  // 8 bytes of zero for Root Delay & Root Dispersion
  packetBuffer[12]  = 49; 
  packetBuffer[13]  = 0x4E;
  packetBuffer[14]  = 49;
  packetBuffer[15]  = 52;

  // all NTP fields have been given values, now
  // you can send a packet requesting a timestamp:         
  Udp.beginPacket(address, 123); //NTP requests are to port 123
  Udp.write(packetBuffer,NTP_packetSize);
  Udp.endPacket();
}

Use this to read the synced time from the RTC.

#include <Wire.h>

const int DS3232_I2C_Address=0x68;

void setup()
{
  Wire.begin();
  Serial.begin(9600);
}

void loop()
{
   // setDS3232time(00, 31, 23, 2, 23, 7, 12);   // set DS3232 seconds, minutes, hours, day of week, date, month, year
   displayTime();
   delay(1000);
}

// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
  return ( (val/10*16) + (val%10) );
}

// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
  return ( (val/16*10) + (val%16) );
}

void readDS3232time(byte *second, byte *minute, byte *hour, byte *dayOfWeek, byte *dayOfMonth, byte *month, byte *year)
{
  Wire.beginTransmission(DS3232_I2C_Address);
  Wire.write(0); // set DS3232 register pointer to 00h
  Wire.endTransmission();  
  Wire.requestFrom(DS3232_I2C_Address, 7); // request 7 bytes of data from DS3232 starting from register 00h

  // A few of these need masks because certain bits are control bits
  *second     = bcdToDec(Wire.read() & 0x7f);
  *minute     = bcdToDec(Wire.read());
  *hour       = bcdToDec(Wire.read() & 0x3f);  // Need to change this if 12 hour am/pm
  *dayOfWeek  = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());
  *month      = bcdToDec(Wire.read());
  *year       = bcdToDec(Wire.read());
}

void displayTime()
{
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  
  // retrieve data from DS3232  
  readDS3232time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
  
  // send it to the serial monitor
  Serial.print(hour, DEC);// convert the byte variable to a decimal number when being displayed
  Serial.print(":");
  
  if (minute<10)
  {
      Serial.print("0");
  }
  
  Serial.print(minute, DEC);
  Serial.print(":");
  
  if (second<10)
  {
      Serial.print("0");
  }
  
  Serial.print(second, DEC);
  Serial.print("  ");
  Serial.print(dayOfMonth, DEC);
  Serial.print("/");
  Serial.print(month, DEC);
  Serial.print("/");
  Serial.print(year, DEC);
  Serial.print("  Day of week:");
  
  switch(dayOfWeek){
  case 1:
    Serial.println("Sunday");
    break;
  case 2:
    Serial.println("Monday");
    break;
  case 3:
    Serial.println("Tuesday");
    break;
  case 4:
    Serial.println("Wednesday");
    break;
  case 5:
    Serial.println("Thursday");
    break;
  case 6:
    Serial.println("Friday");
    break;
  case 7:
    Serial.println("Saturday");
    break;
  }
}

DS3232.pdf (922 KB)

See my reply #16 on:

http://forum.arduino.cc/index.php?topic=180672.15

adamatcooranbong:
I was under the impression if you declare variables within a function you can use them anyware in the function, but that function only. Did't know that if you declare variables inside Control Structures they can't be used elsewhere in the function.

It 's an impression because, in the books, teachers usually declare all variables at the beginning of the function.

But in C/C++ you can also declare variable "private" in one block like this:

void myfunc()
{ int x=1;
  { int y=2;
     Serial.println(y);  // y lives only in this block
     Serial.println(x);  // x lives in the block that is named myfunc() and is a function
  }
  Serial.println(x);
}

Basically { and } define a "block". Anything created within a block can be accessed only inside that block or any blocks that are inside it. You can think of the whole program as being surrounded by { and }, and the functions and global variables are within that block.