Go Down

Topic: Global variable value changes mysteriously between initialization and setup() (Read 936 times) previous topic - next topic

snugRugBug

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: [Select]

#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: [Select]


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: [Select]

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!

PaulS

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

snugRugBug

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 :~

AWOL

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

That should save a fair bit of RAM
"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.

PaulS

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.

gardner


Code: [Select]

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


AWOL

"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.

snugRugBug

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...

snugRugBug

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: [Select]

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
}
};

snugRugBug

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

Code: [Select]

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: [Select]

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.

PeterH


Code: [Select]

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.
I only provide help via the forum - please do not contact me for private consultancy.

snugRugBug

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

Go Up