For loop causing a hang, separate instructions pass

Hi (newbie to this forum - this my first post, not a newbie to C)

I'm having a strange issue with a for loop within a function. Here's the code:

void ConvertRcvHexString2Int(char *RcvHexString, uint16_t *LocalIntArray) {

// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
const uint8_t field_index[datalog_int_fields] = { 2, 6, 8, 10, 12, 16, 20, 24, 28, 32, 34, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92, 96};
const uint8_t field_width[datalog_int_fields] = { 4, 2, 2, 2, 4, 4, 4, 4, 4, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4};
uint16_t temp_int;
uint8_t i;

for (i = 0; i < 6; i++) {

// temp_int = ConvertHexString2Int(RcvHexString, field_index[i], field_width[i]);
// LocalIntArray[i] = temp_int;
}

i = 0;   temp_int = ConvertHexString2Int(RcvHexString, field_index[i], field_width[i]);   LocalIntArray[i] = temp_int;
i = 1;   temp_int = ConvertHexString2Int(RcvHexString, field_index[i], field_width[i]);   LocalIntArray[i] = temp_int;
i = 2;   temp_int = ConvertHexString2Int(RcvHexString, field_index[i], field_width[i]);   LocalIntArray[i] = temp_int;
i = 3;   temp_int = ConvertHexString2Int(RcvHexString, field_index[i], field_width[i]);   LocalIntArray[i] = temp_int;
i = 4;   temp_int = ConvertHexString2Int(RcvHexString, field_index[i], field_width[i]);   LocalIntArray[i] = temp_int;
i = 5;   temp_int = ConvertHexString2Int(RcvHexString, field_index[i], field_width[i]);   LocalIntArray[i] = temp_int;

}

The goal of the function is to convert fields of 2 or 4 hex digits to one integer. The problem I face is that the code hangs on the Arduino (pro mini) when I use the FOR loop, but that it executes fine if I write out the FOR loop. (the actual code goes from i=0 to 26, but I shortened it for simplicity). Anyone having a clue?

Post your code
Remember to use code tags

I would rather not guess what the rest of your sketch does. Please post a complete sketch that illustrates the problem and use code tags when you post it

Here's the full code (and I hope I'm doing this right ...). Note that code is being developed in MS Visual Studio with Arduino extension.

Purpose of this program is to use an Arduino pro mini to capture a serial bit bitstream from a hobby (LiPo, NimH, Pb, etc) charger and store the data as CSV file on an SD card.
A pushbutton is used to instruct the Arduino to start/stop datalogging (works fine)
The data from the charger is received as a 100 hex digit stream (by function RcvHexStringFromDatalogSerial - this capture works fine).
Function ConvertHexString2Int converts each hex field (from RcvHexString) to an integer:

  • 2 arrays with int pointers to point where each field starts & how wide each field is.
  • recursively call hex2int to convert each hex digit to int (works fine too)
    Write to SD has been implemented for the hex data, not yet for the CSV data.

In below code the for loop is commented out and replaced by 27 individual code lines (the for loop crashes the Arduino - the individual lines work ???)

/*
 Name:		DataLogger.ino
 Created:	5/3/2020 1:37:22 PM
 Author:	Johan
*/
#include <SoftwareSerial.h>
#include <string.h>
#include <SdFat.h>
#include <SPI.h>

#define max_logfiles        99
#define SerialBufferSize    64
#define datalog_buffersize 128
#define datalog_int_fields  27

// Global variables using the SD utility library functions:
SdFat sd;
File fpDataFile;

// SPI/SD pins
#ifdef ARDUINO_AVR_PRO
const uint8_t SD_chipSelect = 10;
#else ifdef ARDUINO_AVR_DUEMILANOVE
const uint8_t SD_chipSelect = 4;
#endif
const uint8_t SPI_SS = 10; // No idea if this pin is actually used on Due or Pro Mini
const uint8_t SPI_MOSI = 11;
const uint8_t SPI_MISO = 12;
const uint8_t SPI_SCK = 13;
// Other pins
const uint8_t buttonPin = 8;
const uint8_t LEDPin = 7;
// Variables to keep track of the button/dlog states
bool b1down = false;
bool dlog_state = false;

const uint8_t DataRxPin = 6;  // Serial port to charger
const uint8_t DummyTxPin = 5; // TX not used, but required by SoftwareSerial
SoftwareSerial DatalogSerial(DataRxPin, DummyTxPin, 1); //RX, T

void setup() {
    // ---------------- Run once ----------------------
    // the setup function runs once when you press reset or power the board

    //button pin modes
    pinMode(buttonPin, INPUT_PULLUP); //button1 func
    pinMode(LEDPin, OUTPUT);          //LED     func
    pinMode(DataRxPin, INPUT_PULLUP); //Data    func
    pinMode(DummyTxPin, OUTPUT);
    digitalWrite(LEDPin, LOW);
    digitalWrite(DummyTxPin, LOW);

    Serial.begin(57600);  // initialize USB serial:
    delay(200);
    Serial.println();
    Serial.println("-------------------------------------------------");
    Serial.println("Arduino SD Datalogger connected OK to serial port");
    Serial.println("-------------------------------------------------");

    card_info(SD_chipSelect);
}

void loop() {
    // ---------------- Main loop ---------------------
    // the loop function runs over and over again until power down or reset
    bool ButtonPressed;
    char SerialBuffer[SerialBufferSize]; // Array to store messages
                                           // With this buffer one can create more complex lines than can be done with std serial.println
    sprintf(SerialBuffer, "Loop - ");
    Serial.print(SerialBuffer);
    ButtonPressed = areButtonsPressed();
    //    Serial.print("ButtonPressed: ");
    //    Serial.println(ButtonPressed);
    wait(10);

    if (ButtonPressed == true) {
        if (dlog_state == true) {
            Serial.println("End_datalog");
            end_datalog();
            dlog_state = false;
            digitalWrite(LEDPin, LOW);
            DatalogSerial.end();  // End 2nd serial stream of datalog data
        }
        else {
            Serial.println("Init_datalog");
            dlog_state = true;
            digitalWrite(LEDPin, HIGH);
            DatalogSerial.begin(9600); // Setup card 2nd serial stream of datalog data
            init_datalog();
        }
    }
    else {
        if (dlog_state == true) {
            Serial.println("Continue_datalog");
            continue_datalog();
        }
        else { Serial.println("Do nothing"); }
    }
}

bool areButtonsPressed() {
//handle buttons -------------------------------------------

    bool ButtonPressed = false;

    // detect button down press (digitalRead(buttonPin)==0)
    // only move to next step when button is released (digitalRead(buttonPin)==1)

    if (b1down == false && digitalRead(buttonPin) == 0) {
        b1down = true;
        ButtonPressed = true;
    }
    // detect button up/release
    else if (b1down == true && digitalRead(buttonPin) == 1) {
        b1down = false;
    }
    //    Serial.print("buttonstate: ");
    //    Serial.println(b1down);

    return ButtonPressed;
}

// ---------------- SD Card functions ----------------------

void card_info(uint8_t SD_CS_pin) {

    if (!sd.begin(SD_CS_pin, SPI_FULL_SPEED)) {
        Serial.println("SD Card initialization failed - things to check:");
        Serial.println("* is an SD card inserted?");
        Serial.println("* is SD power switched ON?");
        //      while (1); // loop eternally - user to take action and restart
        sd.initErrorHalt();
    }
    else {
        Serial.println("Card is present.");

        //Class sd.card
        //  init
        //  type
        //  readCID
        //  readCSD

        // print the type of card
        Serial.print("Card type: ");
        switch (sd.card()->type()) {
        case SD_CARD_TYPE_SD1:
            Serial.println("SD1");
            break;
        case SD_CARD_TYPE_SD2:
            Serial.println("SD2");
            break;
        case SD_CARD_TYPE_SDHC:
            Serial.println("SDHC");
            break;
        default:
            Serial.println("Unknown");
        }


        // Skip the rest as all the messages take too much SRAM memory

        //    char Serial_string[80];
        //    unsigned int blocks;
        //    unsigned long int clusters;
        //    unsigned long int volumesize;
        //    float volumesize_Gb;

        //Class SD2card
        //  init
        //  type
        //  readCID
        //  readCSD
        //Class SDvolume
        //  init
        //  fatType
        //  blocksPerCluster
        //  clusterCount

        // Now we will try to open the 'volume'/'partition' - it should be FAT16 or FAT32
        //if (!sd.vol()->fatType()) {
        //    Serial.println("Could not find FAT16/FAT32 partition. Make sure you've formatted the card\n");
        //}

        // Block:  minimal addressable block  - defined by SD hardware - 512 bytes
        // Cluster: groups a number of blocks - defined during FAT formatting
        // Volume: contains lots of clusters

        //    blocks   = volume.blocksPerCluster();
        //    clusters = volume.clusterCount();

        //    sprintf(Serial_string, "Blocksize: 512 (bytes - SD card hardware defined)\n");            Serial.print(Serial_string);
        //    sprintf(Serial_string, "Blocks per cluster: %d (SD card formatting defined)\n", blocks);  Serial.print(Serial_string);
        //    sprintf(Serial_string, "Clusters:  %ld\n", clusters);                                     Serial.print(Serial_string);
        //    sprintf(Serial_string, "Total size (kB): (blocks * clusters) / (blocksize/2) = %ld\n\n", volume.blocksPerCluster() * volume.clusterCount() / 2);  Serial.print(Serial_string);

       //Class SDvolume
        //  fatType
        //  blocksPerCluster
        //  clusterCount
        // print the FAT-type
        // Serial.print("Volume type is: FAT");
        // Serial.println(sd.vol()->fatType(), DEC);

        // list all files in the card with date and size
        // sd.ls(LS_R | LS_DATE | LS_SIZE);

        //    volumesize = volume.blocksPerCluster();    // clusters are collections of blocks
        //    volumesize *= volume.clusterCount();       // we'll have a lot of clusters
        //    volumesize /= 2;                           // SD card blocks are always 512 bytes (2 blocks are 1KB)
        //    sprintf(Serial_string,"Volume size: %ld   (kB)\n",volumesize);  Serial.print(Serial_string);
        //    volumesize /= 1024;
        //    sprintf(Serial_string, "Volume size:    %ld   (MB)\n", volumesize);  Serial.print(Serial_string);
        //  Arduino sprintf does not support printing floats
        //    Serial.print("Volume size:       ");
        //    Serial.print((float)volumesize / 1024.0);
        //    Serial.println("(GB\n");

        Serial.println("Card info done");
    }
}

// ---------------- Datalog fuctions ----------------------

void init_datalog() {

    uint8_t i;
    char SerialBuffer[SerialBufferSize];
    char datalog_filename[15];

    // check for existing files
    // filename can not be longer than 8.3
    // increment the no if already present (max 99)
    for (i = 0; i < max_logfiles; i++)  {
        snprintf(datalog_filename, sizeof(datalog_filename), "Dlog_%2.2i.log", i);

        if (sd.exists(datalog_filename)) {
            sprintf(SerialBuffer, "File %s exists", datalog_filename); Serial.println(SerialBuffer);
        }
        else {
            // open the file
            fpDataFile = sd.open(datalog_filename, FILE_WRITE);
            if (fpDataFile) {
                sprintf(SerialBuffer, "File %s opened", datalog_filename); Serial.println(SerialBuffer);
                i = max_logfiles + 1; // break out of the loop
            }
            else {
                sprintf(SerialBuffer, "Failed to open file %s", datalog_filename); Serial.println(SerialBuffer);
                dlog_state = false;
            }
        }
    }

    if (i == max_logfiles)
    {
        //        sprintf(SerialBuffer, "Clean up log files, max %d reached", max_logfiles);Serial.println(SerialBuffer);
        digitalWrite(LEDPin, LOW);
        dlog_state = false;
    }
}

void continue_datalog() {

    uint8_t i;
    uint8_t j;
    uint8_t string_end;

    char     HexDatalogBuffer[datalog_buffersize];
    uint16_t IntDatalogBuffer1[datalog_int_fields] = { 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0 };

    if (RcvHexStringFromDatalogSerial(HexDatalogBuffer)) {
        string_end = strlen(HexDatalogBuffer);
        for (j = 0; j <= string_end; j++) {
          Serial.print(HexDatalogBuffer[j]);
        }
        Serial.println("");
//    Save raw string to SD
        if (string_end > 0) {
            ConvertRcvHexString2Int(HexDatalogBuffer, IntDatalogBuffer1);
            fpDataFile.write(HexDatalogBuffer);
        }
        for (i = 0; i < datalog_int_fields; i++) {
            Serial.print(IntDatalogBuffer1[i]);Serial.print(";");
        }
        Serial.println("");
    }
}

void end_datalog() {
    char SerialBuffer[SerialBufferSize];
    char datalog_filename[15];

    // close the SD file
    fpDataFile.getName(datalog_filename, 15);
    sprintf(SerialBuffer, "File %s closed", datalog_filename); Serial.println(SerialBuffer);
    fpDataFile.close();
}

bool RcvHexStringFromDatalogSerial(char *RcvHexString) {

    // RcvHexStringFromDatalogSerial will:
    //  * wait until data is being received
    //  * check if the first character is a FormFeed
    //  * if yes, continue till the Carriage Return character is received.
    //  * return to the datalog subroutine
    //    (as there is a 600ms pauze - use this to process data)

    // A frame has a duration of 1second (408ms data, 600ms pauze)
    // Since we might start just after the beginning of a data bust
    // it can take max. 1.4 seconds to capture a burst  

    const uint8_t Frame_start_char = 12; // FF
    const uint8_t Frame_end_char   = 13; // CR + LF

    uint8_t i = 0; // serial buffer is max 63
    uint8_t bytes_received = 0;
    uint8_t k = 0; // one data string is 101 chars long
    bool Framestart_found = false;
    const int TIMEOUT = 1450;
    unsigned long time_now;
    char data; // data is received as an 8 bit ASCII coded byte

    // wait for the beginning of a log burst
    time_now = millis();
    while (millis() < time_now + TIMEOUT) {
        bytes_received = DatalogSerial.available();
        if (bytes_received != 0) {
            for (i = 1; i <= bytes_received; i++) { //i starts at 1 to skip the first FF byte
                data = DatalogSerial.read();
                if (data == Frame_start_char) {
                    digitalWrite(DummyTxPin, HIGH); // indicate the start of (reading) a data burst
                    Framestart_found = true;
                } else
                if (Framestart_found == true) {
                    RcvHexString[k] = data;
                    k++;
                }
            }
            if ((Framestart_found == true) && (data == Frame_end_char)) {
                digitalWrite(DummyTxPin, LOW); // indicate the end of (reading) a data burst
                RcvHexString[k] = '\0';
                return true;
                break; // end while
            }
        }
    }
    if (millis() >= time_now + TIMEOUT) {
        Serial.println("RcvHexString: timeout reached, no data received");
        Serial.println("Is the charger ON?");
        digitalWrite(LEDPin, LOW);
        dlog_state = false;
        return false;
    }
}

// ---------------- Support fuctions ----------------------

void ConvertRcvHexString2Int(char *RcvHexString, uint16_t *IntArray) {

 //                                                    0  1  2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19  20  21  22  23  24  25  26
    const uint8_t  field_index[datalog_int_fields] = { 2, 6, 8, 10, 12, 16, 20, 24, 28, 32, 34, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92, 96};
    const uint8_t  field_width[datalog_int_fields] = { 4, 2, 2,  2,  4,  4,  4,  4,  4,  2,  2,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4};
    uint16_t temp_int;
    uint8_t i;

//    for (i = 0; i < datalog_int_fields; i++) {
//        Serial.print(i);
//        temp_int = ConvertHexString2Int(RcvHexString, field_index[i], field_width[i]);
//        IntArray[i] = temp_int;
//    }
//    Serial.print(" - ");

    i = 0;   temp_int = ConvertHexString2Int(RcvHexString, field_index[i], field_width[i]);   IntArray[i] = temp_int;
    i = 1;   temp_int = ConvertHexString2Int(RcvHexString, field_index[i], field_width[i]);   IntArray[i] = temp_int;
    i = 2;   temp_int = ConvertHexString2Int(RcvHexString, field_index[i], field_width[i]);   IntArray[i] = temp_int;
    i = 3;   temp_int = ConvertHexString2Int(RcvHexString, field_index[i], field_width[i]);   IntArray[i] = temp_int;
    i = 4;   temp_int = ConvertHexString2Int(RcvHexString, field_index[i], field_width[i]);   IntArray[i] = temp_int;
    i = 5;   temp_int = ConvertHexString2Int(RcvHexString, field_index[i], field_width[i]);   IntArray[i] = temp_int;
    i = 6;   temp_int = ConvertHexString2Int(RcvHexString, field_index[i], field_width[i]);   IntArray[i] = temp_int;
    i = 7;   temp_int = ConvertHexString2Int(RcvHexString, field_index[i], field_width[i]);   IntArray[i] = temp_int;
    i = 8;   temp_int = ConvertHexString2Int(RcvHexString, field_index[i], field_width[i]);   IntArray[i] = temp_int;
    i = 9;   temp_int = ConvertHexString2Int(RcvHexString, field_index[i], field_width[i]);   IntArray[i] = temp_int;
    i = 10;  temp_int = ConvertHexString2Int(RcvHexString, field_index[i], field_width[i]);   IntArray[i] = temp_int;
    i = 11;  temp_int = ConvertHexString2Int(RcvHexString, field_index[i], field_width[i]);   IntArray[i] = temp_int;
    i = 12;  temp_int = ConvertHexString2Int(RcvHexString, field_index[i], field_width[i]);   IntArray[i] = temp_int;
    i = 13;  temp_int = ConvertHexString2Int(RcvHexString, field_index[i], field_width[i]);   IntArray[i] = temp_int;
    i = 14;  temp_int = ConvertHexString2Int(RcvHexString, field_index[i], field_width[i]);   IntArray[i] = temp_int;
    i = 15;  temp_int = ConvertHexString2Int(RcvHexString, field_index[i], field_width[i]);   IntArray[i] = temp_int;
    i = 16;  temp_int = ConvertHexString2Int(RcvHexString, field_index[i], field_width[i]);   IntArray[i] = temp_int;
    i = 17;  temp_int = ConvertHexString2Int(RcvHexString, field_index[i], field_width[i]);   IntArray[i] = temp_int;
    i = 18;  temp_int = ConvertHexString2Int(RcvHexString, field_index[i], field_width[i]);   IntArray[i] = temp_int;
    i = 19;  temp_int = ConvertHexString2Int(RcvHexString, field_index[i], field_width[i]);   IntArray[i] = temp_int;
    i = 20;  temp_int = ConvertHexString2Int(RcvHexString, field_index[i], field_width[i]);   IntArray[i] = temp_int;
    i = 21;  temp_int = ConvertHexString2Int(RcvHexString, field_index[i], field_width[i]);   IntArray[i] = temp_int;
    i = 22;  temp_int = ConvertHexString2Int(RcvHexString, field_index[i], field_width[i]);   IntArray[i] = temp_int;
    i = 23;  temp_int = ConvertHexString2Int(RcvHexString, field_index[i], field_width[i]);   IntArray[i] = temp_int;
    i = 24;  temp_int = ConvertHexString2Int(RcvHexString, field_index[i], field_width[i]);   IntArray[i] = temp_int;
    i = 25;  temp_int = ConvertHexString2Int(RcvHexString, field_index[i], field_width[i]);   IntArray[i] = temp_int;
    i = 26;  temp_int = ConvertHexString2Int(RcvHexString, field_index[i], field_width[i]);   IntArray[i] = temp_int;
}

uint16_t ConvertHexString2Int(char *HexString, uint8_t FieldIndex, uint8_t FieldWidth) {

    char    c;
    uint8_t i;
    uint16_t convertedField = 0;

    c = HexString[FieldIndex];
    convertedField = Hex2Int(c);
    for (i = 1; i < FieldWidth; i++) {
        c = HexString[FieldIndex + i];
        convertedField = (convertedField * 16) + Hex2Int(c);
    }
    return convertedField;
}

uint16_t Hex2Int(char hexdigit) {
    uint16_t intdigit = 0;

    switch (hexdigit) {
       case '0': intdigit =  0; break;
       case '1': intdigit =  1; break;
       case '2': intdigit =  2; break;
       case '3': intdigit =  3; break;
       case '4': intdigit =  4; break;
       case '5': intdigit =  5; break;
       case '6': intdigit =  6; break;
       case '7': intdigit =  7; break;
       case '8': intdigit =  8; break;
       case '9': intdigit =  9; break;
       case 'A': intdigit = 10; break;
       case 'B': intdigit = 11; break;
       case 'C': intdigit = 12; break;
       case 'D': intdigit = 13; break;
       case 'E': intdigit = 14; break;
       case 'F': intdigit = 15; break;
       default : intdigit =  0;
    }
    return intdigit;
}

void wait(int w817) {

    unsigned long time_now;

    time_now = millis();
    while (millis() < time_now + w817) {
        // do nothing
    }
}

Uh-oh

I see no recursion.

a7

'Recursively' is indeed not the proper wording (/issue) here - I meant the 27 times FOR loop, but this is exactly what fails. Calling it 27 times in separate code lines works.

How does it fail? Is there an error message? Are the function results wrong?
Can you make a short demo sketch that demonstrates the problem?

I was hoping that was what would be posted in the first place. My fault for not being more specific

Here's the Arduino serial output when using 27 separate commands:

Loop - Continue_datalog
C830950201010853019402C100D8010000002FCE0000000000000000000000000000000000000000000000000000000012C1
12437;2;1;1;2131;404;705;216;256;0;0;12238;0;0;0;0;0;0;0;0;0;0;0;0;0;0;4801;
Loop - Continue_datalog
C830950201010853019402C100D8010000002FCE0000000000000000000000000000000000000000000000000000000012C1
12437;2;1;1;2131;404;705;216;256;0;0;12238;0;0;0;0;0;0;0;0;0;0;0;0;0;0;4801;
Loop - Continue_datalog

The first line is the hex stream, the second line is the converted CSV integer data (which is correct)

When using the for loop the Arduino already hangs here:

Loop - Do nothing
Loop - Do nothing
Loop - Init_datalog

The latter obviously doesn't say a lot as serial output always lags the real output. The 5 lines of for loop are however the only delta

Compiler statistics:
Compiling debug version of 'DataLogger' for 'ATmega328P (3.3V, 8 MHz) (Arduino Pro or Pro Mini)'
Program size: 17.806 bytes (used 58% of a 30.720 byte maximum) (7,60 secs)
Minimum Memory Usage: 1626 bytes (79% of a 2048 byte maximum)

So no memory overrun.

The 'for' loop works fine for me.

const int datalog_int_fields = 27;
uint16_t data[datalog_int_fields];

//                                                    0  1  2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19  20  21  22  23  24  25  26
const uint8_t  field_index[datalog_int_fields] = { 2, 6, 8, 10, 12, 16, 20, 24, 28, 32, 34, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92, 96};
const uint8_t  field_width[datalog_int_fields] = { 4, 2, 2,  2,  4,  4,  4,  4,  4,  2,  2,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4};

void ConvertRcvHexString2Int(char *RcvHexString, uint16_t *IntArray)
{
  uint16_t temp_int;
  uint8_t i;

  for (uint8_t i = 0; i < datalog_int_fields; i++)
  {
    Serial.print((int)i);
    temp_int = ConvertHexString2Int(RcvHexString, field_index[i], field_width[i]);
    IntArray[i] = temp_int;
  }
  Serial.print(" - ");


}

uint16_t ConvertHexString2Int(char *HexString, uint8_t FieldIndex, uint8_t FieldWidth)
{
  uint16_t convertedField = 0;

  for (uint8_t i = 0; i < FieldWidth; i++)
  {
    char c = HexString[FieldIndex + i];
    convertedField = (convertedField * 16) + Hex2Int(c);
  }
  return convertedField;
}

uint16_t Hex2Int(char hexdigit)
{
  if (hexdigit >= '0' && hexdigit <= '9')
    return hexdigit - '0';

  if (hexdigit >= 'A' && hexdigit <= 'F')
    return hexdigit - 'A' + 10;

  return 0;
}

char message[] = "123456789ABCDEF123456789ABCDEF123456789ABCDEF123456789ABCDEF123456789ABCDEF123456789ABCDEF123456789ABCDEF";
void setup()
{
  Serial.begin(115200);
  delay(200);

  ConvertRcvHexString2Int(message, data);

  for (uint8_t i = 0; i < datalog_int_fields; i++)
  {
    Serial.print(i);
    Serial.print(": ");
    Serial.println(data[i], HEX);
  }
}

void loop() {}

The output looks reasonable:

01234567891011121314151617181920212223242526 - 0: 3456
1: 78
2: 9A
3: BC
4: DEF1
5: 2345
6: 6789
7: ABCD
8: EF12
9: 34
10: 56
11: 789A
12: BCDE
13: F123
14: 4567
15: 89AB
16: CDEF
17: 1234
18: 5678
19: 9ABC
20: DEF1
21: 2345
22: 6789
23: ABCD
24: EF12
25: 3456
26: 789A

That's a very bold assertion.
The compiler/linker only reports static/global memory allocation.

1 Like

THX John, I'll review your code in detail this evening/weekend (and try difference in my code where applicable)

I'd get busy adding some F() macros

Not sure what this reply is supposed to mean.

Using the F() macro when printing text saves RAM by putting the text into flash memory

Serial.println(F("-------------------------------------------------"));
    Serial.println(F("Arduino SD Datalogger connected OK to serial port"));
    Serial.println(F("-------------------------------------------------"));

It's supposed to mean "you're wasting precious RAM - better keep those string literals in flash memory, where they belong"

Fixed

I doubt that this is cause of my issue. But point taken...