Pages: [1]   Go Down
Author Topic: Global variable value changes mysteriously between initialization and setup()  (Read 830 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 38
Don't eat yellow snow.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi, I'm building a little gizmo that logs phone calls, and can send its data to you via SMS. As I'm quite new here, I've encountered quite a few obstacles, but I'm now finally in the last stages of development.
The following problem, I think, is pretty isolated, so I'll put the appropriate code in this message, but I will also attach the whole thing, just in case. Please note: I'm still developing, so it's not that neat yet:

The problem:
I declared these global variables as follows
Code:
#include <SoftwareSerial.h> // required to send and receive AT commands from the GPRS Shield
#include <Wire.h> // required for I2C communication with the RTC

#define TELESCOPE_NUMS 0
#define ADMIN_NUMS 1

// pin numbers for RTC
#define DS3231_I2C_ADDRESS 104 // 0x68 // Address for RTC
#define DS3231_TIME_CAL_ADDR        0 // 0x00
#define DS3231_ALARM1_ADDR          7 // 0x07
#define DS3231_ALARM2_ADDR         11 // 0x0B
#define DS3231_CONTROL_ADDR        14 // 0x0E
#define DS3231_STATUS_ADDR         15 // 0x0F
//#define DS3231_AGING_OFFSET_ADDR   16 // 0x10
#define DS3231_TEMPERATURE_ADDR    17 // 0x11
// Declarations for GPRS shield
byte buffer[ 64 ]; // Buffer is used to transfer data from the GPRS line to the serial line
int count = 0, smsMemIndex;
char temp, lastCaller[13] = "blank", lastSmsSender[13] = "blank", smsBody[ 160 ];
boolean callIncoming = false, done = true, smsIncoming = false, smsBodyIncoming = false, airtimeBalanceIncoming = false, firstAirtimeCheck = false;

// Declarations for RTC
byte time[ 7 ]; // second, minute, hour, dow, day, month, year
byte time_A1[ 5 ]; // second_A1, minute_A1, hour_A1, day_A1, DY/DT
byte time_A2[ 4 ]; // minute_A2, hour_A2, day_A2, DY/DT
byte received[1]; // used to catch bytes sent from the clock
float temperature; // clock temperature is updated every 64 s

// Declarations for RemoteCallLogger
int phoneBookSize = 6;
char phoneBook[ 2 ][ 6 ][ 13 ] = {
  {
    "+27xxxxxxx3",
    "+27xxxxxxx0",
    "+27xxxxxxx9",  // telescope numbers
    "+27xxxxxxx4",
    "+27xxxxxxx6",
    "+27xxxxxxx2"                        }
  ,

  {
    "+27xxxxxxx4",
    "+27xxxxxxx4",
    "+2xxxxxxxxx5",  // admin numbers
    "eeeeeeeeeeee",
    "eeeeeeeeeeee",
    "eeeeeeeeeeee"                        }
};
char callerNames[ 2 ][ 6 ][ 6 ] = {
  {
    "TB1",
    "TB2",
    "TB3",   // telescope names
    "TB4",
    "TB5",
    "TB6"                   }
  ,
  {
    "Coert",
    "Ma",
    "Pa",
    "leeg",    // admin names
    "leeg",
    "leeg"                   }
};

char smsCommands[ 3 ][ 10 ] = {
  "REPORT\0", "RESET\0", "DIAL\0" }; // sms command strings
double airtimeBalance = 0.00;
double smsTariff = 0.00; // amount of airtime available, and cost per sms
int noOfCommands = 3, lastCommandIndex = -1;
int callsToday[ 6 ] = { // increments with every missed call from a telescope, resets every 24 hours
  0, 0, 0, 0, 0, 0};
int daysDown[ 6 ] = { // increments for each consecutive day there were no wissed call from a telescope, resets when a missed call is made
  0, 0, 0, 0, 0, 0};
int callsThisMonth[ 6 ] = { // increments with every missed call from a telescope, resets manually via sms
  0, 0, 0, 0, 0, 0 };
int lastMatchIdentifier = 0; // indicates whether the last missed call came from admin or a telescope
int lastMatchIndices[ 2 ] = { // indicates which one of each of the two phonebooks' numbers called last
  -1, -1 };
SoftwareSerial GPRS( 7, 8 ); // A softwareSerial line is defined for the GPRS Shield

And this is my setup()
Code:

void setup()
{
  Serial.begin(9600);
  delay(1000);

  // GPRS Shield startup code
  GPRS.begin( 9600 );
  delay(1000);
  setPowerStateTo(1);
  delay(1000);

  // RTC Startup code
  Wire.begin();
  delay(1000);
  for(int i = 0; i < 6; i++)
    Serial.println(callsToday[ i ]);

}

And my output:
Code:
4865
0
0
0
0
0

Question: I clearly initialized the array callsToday with all 0 values, so why is callsToday[0] = 4865?
And how can I fix it?

There isn't even a function I made that could have screwed with anything!

* RemoteCallLoggerV1e0safe.ino (29.56 KB - downloaded 11 times.)
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 631
Posts: 50039
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Have you got a clue how much SRAM you are using? How little you have?
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 38
Don't eat yellow snow.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Well, it's a Seeduino Stalker v2.3, and the website says its got 2 kB. I don't know how to check the amount of RAM I'm using smiley-confuse
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 308
Posts: 26467
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Start editing stuff like:
Code:
Serial.print( "Error: Invalid powerstate. Current powerstate = " );
to read
Code:
Serial.print( F("Error: Invalid powerstate. Current powerstate = ") );

That should save a fair bit of RAM
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 631
Posts: 50039
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I don't know how to check the amount of RAM I'm using
Look through your global variables. Add up the sizes of the arrays. Just looking at the arrays, I see nearly 600 bytes, of that 2K, gone.

There are some functions floating around to measure how much free memory you have, at run time (if any). It would be worth your while to find one of them and use it.
Logged

Ontario
Offline Offline
God Member
*****
Karma: 25
Posts: 887
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
char phoneBook[ 2 ][ 6 ][ 13 ] = {
char callerNames[ 2 ][ 6 ][ 6 ] = {
char smsCommands[ 3 ][ 10 ] = {

These could and should all be placed in PROGMEM.  See

http://www.arduino.cc/en/Reference/PROGMEM
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 38
Don't eat yellow snow.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ah... It worked. Thanks.
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 308
Posts: 26467
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
It worked
Which worked, and how can you be sure?
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Offline Offline
Newbie
*
Karma: 0
Posts: 38
Don't eat yellow snow.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Well, I used F() on a bunch of my strings, and callsToday[ 0 ] is now 0, the way it should be.
As for the PROGMEM, I'm reading about it now, and it seems wonderful, but also complicated. It's going to take me a while to learn this.
Maybe someone (if they're feeling extremely charitable) can send me some example code for converting my 3d char arrays to PROGMEM arrays?
I've googled it, and found some info, but to make sense of it all is going to be quite a task...
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 38
Don't eat yellow snow.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

OK, I'm busy playing with PROGMEM, but I have 1 question:
As shown below, you declare and initialise all the prog_char arrays, and then place them into the structure. Is there a shorthand way of doing this?
Maybe something along the lines of

char[][3] list = { "aq", "er", "qw" } ;

instead of

char[3] str1 = "aq";
char[3] str2 = "er";
char[3] str3 = "qw";
char[][3] list = { str1, str2, str3 } ;

?

Code:
prog_char string_0[] PROGMEM = "+2xxxxxxxxx3";   // "String 0" etc are strings to store - change to suit.
prog_char string_1[] PROGMEM = "+2xxxxxxxxx0";
prog_char string_2[] PROGMEM = "+2xxxxxxxxx9";
prog_char string_3[] PROGMEM = "+2xxxxxxxxx4";
prog_char string_4[] PROGMEM = "+2xxxxxxxxx6";
prog_char string_5[] PROGMEM = "+2xxxxxxxxx6";
prog_char string_6[] PROGMEM = "+2xxxxxxxxx4";   // "String 0" etc are strings to store - change to suit.
prog_char string_7[] PROGMEM = "+2xxxxxxxxx4";
prog_char string_8[] PROGMEM = "+2xxxxxxxxx5";
prog_char string_9[] PROGMEM = "eeeeeeeeeeee";
prog_char string_a[] PROGMEM = "eeeeeeeeeeee";
prog_char string_b[] PROGMEM = "eeeeeeeeeeee";

// Then set up a table to refer to your strings.

PROGMEM const char *string_table[ 2 ][ 6 ] =    // change "string_table" name to suit
{ { 
  string_0,
  string_1,
  string_2,
  string_3,
  string_4,
  string_5 },
{
  string_6,
  string_7,
  string_8,
  string_9,
  string_a,
  string_b
}
};
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 38
Don't eat yellow snow.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Also, I wrote this bit of code to make the transition between the new and old memory regimes smoother:

Code:
char* phoneBook(int a, int b)
{
 strcpy_P(strBuffer, (char*)pgm_read_word(&(numbers_table[a][b]))); // Necessary casts and dereferencing, just copy.
return strBuffer;
}


Would it matter if I made strBuffer a local variable? ie

Code:
char* phoneBook(int a, int b)
{
char[13] strBuffer;
 strcpy_P(strBuffer, (char*)pgm_read_word(&(numbers_table[a][b]))); // Necessary casts and dereferencing, just copy.
return strBuffer;
}

When I say "matter", I mean memory-wise.
Logged

UK
Offline Offline
Shannon Member
****
Karma: 223
Posts: 12630
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
char[13] strBuffer;
return strBuffer;

No no no, don't do that! You're returning the address of a local array variable which is allocated on the stack; as soon as the return completes the stack is unwound and the contents of the array cease to be defined. The calling code would be left with a pointer to the array which contained some valid-looking data, but was liable to be overwritten by any operation that caused the stack to be extended over the memory that had previously held the array.
Logged

I only provide help via the forum - please do not contact me for private consultancy.

Offline Offline
Newbie
*
Karma: 0
Posts: 38
Don't eat yellow snow.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

 smiley-lol
lol, I see what you're saying.
Took me a while to see, I'm still working on my greek degree (engineering)
Silly me
Logged

Pages: [1]   Go Up
Jump to: