8266 What causes my "Exception 3" Error?

My program will use an array defined as a "structure."
I was able to fill it in in a test mode, but when I try to put a value to any element the program will compile, but the operation finds an "Exception 3" and resets.
I've deleted most of the code for simplicity.
The part that gives the trouble is in the "loop" where I have reduced things to two "for" loops - One to define the strings CDC[j] and CDT[j] and a second one to fill in some values. (In the final version real values will be filled in. For test purposes I have simply used the index j .
By now I've tried many variations on this, and seem to have located the problem - but I don't understand why it is a problem, nor what I'm doing wrong.

Any help will be appreciated.

#include <ESP8266WiFi.h>
#include "HTTPSRedirect.h"
#include "DebugMacros.h"

float x ;
float h;
float t;
String sheetHumid = "";
String sheetTemp = "";

String sheetXXX  = "";
String sheetYYY  = "";
String sheetZZZ  = "";
String datastring = "";

const char* ssid = "A47FB0";                //replace with our wifi ssid
const char* password = "96880104";         //replace with your wifi password

const char* host = "script.google.com";

//const char *GScriptId = "1wF7PdOpxmfXFZWarJS7847TOcYhkSF9iVGZkqhVQMmU"; // Replace with your own google script id
// this worked:  const char *GScriptId = "AKfycbzPAOKrYAOrmFpmyCqZ9d8u984JmOpZkS70c_iiZA2F3UDZqwyK"; // Replace with your own google script id
//                         AKfycbzPAOKrYAOrmFpmyCqZ9d8u984JmOpZkS70c_iiZA2F3UDZqwyK

 const char *GScriptId = "AKfycbyb1uS4foQKRAhde3MVJJ_GZIqv-zNrTejmUngZVzk6EYfw8CI"; // Replace with your own google script id
//https://script.google.com/macros/s/AKfycbyb1uS4foQKRAhde3MVJJ_GZIqv-zNrTejmUngZVzk6EYfw8CI/exec
//                        AKfycbyb1uS4foQKRAhde3MVJJ_GZIqv-zNrTejmUngZVzk6EYfw8CI



//https://script.google.com/macros/s/AKfycbzPAOKrYAOrmFpmyCqZ9d8u984JmOpZkS70c_iiZA2F3UDZqwyK/exec
const int httpsPort = 443; //the https port is same

// echo | openssl s_client -connect script.google.com:443 |& openssl x509 -fingerprint -noout
const char* fingerprint = "";

//const uint8_t fingerprint[20] = {};

String url = String("/macros/s/") + GScriptId + "/exec?value=Steri.";  // Write Teperature to Google Spreadsheet at cell A1
// Fetch Google Calendar events for 1 week ahead

  String url2 = String("/macros/s/") + GScriptId + "/exec?cal";  // Write to Cell A continuosly
//  String url2 = String("/macros/s/") + GScriptId + "/exec?value=Temp=xx=-re";  // Write to Cell A continuosly
//  the above change made NO DIFFERENCE!!??
//   What writes "Humidity" into B1 ?? This is done in the webapp.

//replace with sheet name not with spreadsheet file name taken from google
String payload_base =  "{\"command\": \"appendRow\", \
                    \"sheet_name\": \"TempSheet\", \
                       \"values\": ";
String payload = "";

HTTPSRedirect* client = nullptr;

// used to store the values of free stack and heap before the HTTPSRedirect object is instantiated
// so that they can be written to Google sheets upon instantiation

//////////////////////////// 
// Before setup:
// ng enum State : byte { 0, 1, 2 };
 
 //enum State : byte { WU, ST, CD };

//----- Here we set up variables for making up the payload to be used later in the  loop ---

  int j ;
struct Celldata {
  uint8_t  temp;  // this will be the actual temperature minus 150 degrees, and will ALWAYS be between  0 and 255.
  byte     cyc;
  byte     extra;
                 } // End of struct Celldata
Celldata[15];  // for now, try with only 15 slots. Eventually 60.

//  String adder = "";  //
// -------------- end of payload variables setup
//  
void setup() {

    delay(100);
  Serial.begin(115200);
  Serial.println();
  Serial.print("Connecting to wifi: ");
  Serial.println(ssid);
  
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  // Use HTTPSRedirect class to create a new TLS connection
  client = new HTTPSRedirect(httpsPort);
  client->setInsecure();
  client->setPrintResponseBody(true);
  client->setContentTypeHeader("application/json");
  Serial.print("Connecting to ");
  Serial.println(host);          //try to connect with "script.google.com"

  // Try to connect for a maximum of 5 times then exit
  bool flag = false;
  for (int i = 0; i < 5; i++) {
    int retval = client->connect(host, httpsPort);
    if (retval == 1) {
      flag = true;
      break;
    }
    else
      Serial.println("Connection failed. Retrying...");
  }

  if (!flag) {
    Serial.print("Could not connect to server: ");
    Serial.println(host);
    Serial.println("Exiting...");
    return;
  }
// Finish setup() function in 1 second since it will fire watchdog timer and will reset the chip.
//So avoid too many requests in setup()

  Serial.println("\nWrite into cell 'A1'");
  Serial.println("------>");
  // fetch spreadsheet data
  client->GET(url, host);
  
  Serial.println("\nGET: Fetch Google Calendar Data:");
  Serial.println("------>");
  // fetch spreadsheet data
  client->GET(url2, host);

 Serial.println("\nStart Sending Sensor Data to Google Spreadsheet");

  
  // delete HTTPSRedirect object
  delete client;
  client = nullptr;

}  // End of setup

void loop() {

delay(1000);
  sheetXXX  = "mcb XXX mcb";
  sheetYYY  = "mcb YYY mcb";
  sheetZZZ  = "mcb ZZX mcb";
  

  static int error_count = 0;
  static int connect_count = 0;
  const unsigned int MAX_CONNECT = 20;
  static bool flag = false;

     for (  int  j = 0 ; j <=7 ; j++) {  // Celldata was defined for  15  cells for now
    
// ----------------------------
      String CDT[j];  
      String CDC[j];
 // this causes error 3 - then resets     CDT[j] = j;  // mcb 11:34 pm  "sss"; - This causes error 3.
/// ----------------------      
                                
    Serial.print("  ");
    Serial.print(j);
    Serial.print(" = ");
    CDC[j] = j;  // >> Error Exception 3
  //  Serial.println(CDC[j]);
    
              }  // end of "for" loop - puitting something into each cerll.
     Serial.println(); // to end line from above.
    
       for (  int  j = 0 ; j <=5 ; j++) {  // Celldata was defined for  15  cells for now
   //   Serial.println("In For loop");

    Serial.print("Data so far. j= ");
    Serial.print(j);
    Serial.print("  CDC= ");
//    CDC[j] = j;
    //Serial.print(CDC[j]); // error CDC not defined in this scope
    Serial.print("  ");
    Serial.println();
                                        }  // end of for
    Serial.println("End of 2d for ");
    
    payload = payload_base + "\"" + sheetTemp + "," + sheetXXX +   "\"}";


  if (!flag) {
    client = new HTTPSRedirect(httpsPort);
    client->setInsecure();
    flag = true;
    client->setPrintResponseBody(true);
    client->setContentTypeHeader("application/json");
  } // End of if ??

  if (client != nullptr) {
    if (!client->connected()) {
      client->connect(host, httpsPort);
      client->POST(url2, host, payload, false);
      Serial.print("Sent : ");  Serial.println("Temp and Humid");
    }
  }
  else {
      error_count = 5;
  }

  if (connect_count > MAX_CONNECT) {
    connect_count = 0;
    flag = false;
    delete client;
    return;
  }

//  Serial.println("GET Data from cell 'A1':");
//  if (client->GET(url3, host)) {
//    ++connect_count;
//  }
//  else {
//    ++error_count;
//    DPRINT("Error-count while connecting: ");
//    DPRINTLN(error_count);
//  }

  Serial.println("POST or SEND Sensor data to Google Spreadsheet:");
  if (client->POST(url2, host, payload)) {
    ;
  }
  else {
    ++error_count;
  }

  if (error_count > 3) {
    Serial.println("Halting processor...");
    delete client;
    client = nullptr;
    Serial.printf("Final free heap: %u\n", ESP.getFreeHeap());
    Serial.printf("Final stack: %u\n", ESP.getFreeContStack());
    Serial.flush();
    ESP.deepSleep(0);
  }
  
  delay(3000);    // keep delay of minimum 2 seconds as dht allow reading after 2 seconds interval and also for google sheet
}  // loopend -  I think!

You are creating an array containing "j" elements, numbered 0 through j-1. You then attempt to assign a value to element j, which does not exist.

Regards,
Ray L.

Hi RayLivingston -
You seem to understand my problem, but I don't!

"You are creating an array containing "j" elements, numbered 0 through j-1. You then attempt to assign a value to element j, which does not exist."

I intended to create an array CDT[j]
Which would have elements numbered with the values 0 though j-1.

I would then like to fill these elements with data.
Initially I tried to combine these two steps, without success.

Now I have modified the code so that the elements are defined in a loop,
cycling through j:,
String CDT[j]; // for a range of j values.

This compiles OK.
Next, I try to fill the elements. For convenience, I try to fill them with the value of the index "j" but I have also tried using "a". In either case, the compiler says:

'CDC' was not declared in this scope - for the line CDC[j] = j;
(Same error if I say CDC[j] = "a"; )

I thought that I had declared it - CDC[j] - in the loop above.

Where am I going astray? This seems to be simple, but I'm missing something!

Strip loop() to the bare minimum, and you have this:

    for (  int  j = 0 ; j <=7 ; j++) 
    {
        String CDT[j]; 
        String CDC[j];
        CDC[j] = j;
    }

So...
When j = 0, you create an array of length 0, then try to initialize the first element, which does not exist.
When j = 1, you create an array of length 1, then try to initialize the second element, which does not exist.
When j = pick ANY number...

Regards,
Ray L.

Thanks - so far!

You've shown me the error of my ways - but now I have to figure out how to do what I really WANT to do.

That is, I want to create an array of strings, and then to fill the elements with string data.

I now understand how NOT to do it, but the correct solution still evades me.

A hint would be appreciated!

int arraySize = 7;

String CDC[arraySize];

for (int  j = 0; j < arraySize-1; j++)
{
        CDC[j] += j;
}

Regards,
Ray L.

Thanks VERY much for your help.
I think I now know a lot more about strings, BUT I still have my problem.

Ultimately I want to fill a line of a Google Spreadsheet with some values. I have been following a "cookbook" illustration supplied from the site

I can add additional columns, the data in each column (on an added row) being in the form of a String.

My actual project (not included here) results in two "bytes," a temperature and a "condition" or "state" which can be one of four values. The actual routine will run for less than an hour, and I'd like to report to the spreadsheet (after a run is complete) for each minute the temperature and the state, thus requiring 60 Strings with each String containing the data for that minute.

Thus, what I would really like (in order to use the method I am following) is a way to create 60 Strings, each of which will be filled with the data appropriate for that minute, and to plug these into the line that gets sent to the spreadsheet at the conclusion of a program "run cycle."

I thought that the ideal mechanism for doing this was to use "for" loops, ultimately running through 60 items or Strings; once to accumulate the data, and again to arrange it for transmission to the spreadsheet for display. This is what I tried to used the CDT[j] for, where j would represent the String or data or minute number. The String length would be fixed, and there would eventually be 60 of them. (For the display the format of each String would be would be "TTT SS" where TTT is a 3-character temperature value and SS is a 2-character state value - both in ASCII.)

Is it possible to do this with an "array of strings"?

Hello again - problem solved!

I apologize for not realizing that your succinct statement containing the solution was all that I needed.
I was confused by the fact that in defining the string size, and later for the index to the string number, the [j] is performing two different functions.

Now that I've gotten back to the program (and tried implementing your proposed solution) I understand that what I want to do IS possible, and that your simple implementation is the way to go.

Just a note of appreciation, and to say that all has ended well - so far!

  • Matt

Glad to hear you got it sorted out!

Regards,
Ray L.