Strange behaviour of Serial.println

In the code below at line 128 is DEBUGPRINTLN("xxxxxxxxxxxxxxxxxxxxxxxxxxxxx");

This is debugging code so that I can see how far it gets before it fails. DEBUGPRINTLN is a macro for "Serial.println" so that it is easy to turn on/off debugging code. Anyway I have noticed that if I change the number of "X" in the string then the output changes, the output from earlier Serial.println and/or subsequent Serial.println gets cropped off like
"inte⸮v"

If I remove that statement at line 128 it doesn't get past around line 123, if it put it in it gets a bit further, why would changing the Serial.println cause the program functionality to change?

I'm using an Arduino Nano. Any ideas what I should be looking for to fix this?

/*
 * File                 DraftDetector2.ino
 *
 * Synopsis             DraftDetector using data logger
 *
 * Author               Chris Hunter

 *
 * Version              2.0 - June 2015
 *
 * License              This software is released under the terms of the GNU Public License (GPL) version 2.0
 *                      Full details of licensing terms can be found in the "LICENSE" file, distributed with this code
 *
 * Instructions
 *
 *
 */

#include "DraftDetector.h"
#include <EEPROM.h>
#include <RTClib.h>
//#include <SdFat.h>
#include <avr/sleep.h>
#include <avr/power.h>
#include <avr/wdt.h>
//For SD Card and DS1305
#include <SPI.h>
//For BMP085 pressure/temp sensor
//#include <Wire.h>

//eeprom addresses and default values
//reading interval in minutes, 2 bytes
#define EADR_INTERVAL 0 
#define DF_INTERVAL 3 
//is a BMP085 present?
#define EADR_BMP 2 
//is an SD Card present?
#define EADR_SD 4 
#define EADR_SD_V 6

// Create a new object to interact with the RTC
RTC_DS3231 rtc;

char mode = 'R';

//BMP085
int temperature = 0;
long pressure = 0;
boolean bmpUp = false;

//3.3V
int loggerVotlage;

int intZeroCount = 0; //number of times interrupt0 has been called
int honeymoon = 6; //initial period
bool watchdog = false;

/****************************************************************
 * Standard Arduino Set up routine
 ****************************************************************/
void setup() {
    Serial.begin(9600);
    //Serial.setTimeout(1000);

    pinMode(LED, OUTPUT);
    wdt_disable();
    
    //RTC config
    if (! rtc.begin()) {
      Serial.println("Couldn't find RTC");
      Serial.flush();
      while (1) delay(100);
    }
    //we don't need the 32K Pin, so disable it
    rtc.disable32K();
    rtc.clearAlarm(1);
    rtc.clearAlarm(2);
    
    Serial.println("Enter S[etup] C[ontinuous]");
    
    //loop for 20 secs to allow user to change mode
    byte i = 20;
    //int flash = HIGH;
    pinMode(LED, OUTPUT);
    digitalWrite(LED, HIGH);
    
    mode='R';
    
    while (i-- > 0) {
      DEBUGPRINTLN(i);
        //setWdt();
        if (Serial.available() > 0) {
            // read the incoming byte:
            byte serialByte = Serial.read();
            if (serialByte == 's' || serialByte == 'S') {
                //set-up mode, configure and then enter run mode
                mode = 'S';
                configure();
                mode = 'R';

                break;
            } else if (serialByte == 'c' || serialByte == 'C') {
                //interactive mode
                mode = 'C';
                break;
            }
        }
        
        //wdt_reset();
        //digitalWrite(LED, flash);
        //flash != flash;
        delay(500);

    }//while(i)
    
                
    digitalWrite(LED, LOW);
    delay(10);
    
    Serial.print("Clock: ");
    char dateBuf[28];
    getFormattedTime(dateBuf);
    Serial.println(dateBuf);

    int interval = 3;
    EEPROM.get(EADR_INTERVAL, interval);
    displayVal("interval", interval);
//DEBUGPRINTLN("xxxxxxxxxxxxxxxxxxxxxxxxxxxxx");

    int hasBmp=0;
    EEPROM.get(EADR_BMP, hasBmp);
    displayVal("BMP", hasBmp);

    int hasSD=0;
    EEPROM.get(EADR_SD, hasSD);
    displayVal("SD", hasSD);

    int curV = 0;
    EEPROM.get(EADR_SD_V, curV);
    displayVal("Threshold", curV);

    Serial.print("Mode ");
    Serial.println(mode);

    //in case we are stuck (resetting on watchdog)
    //take a reading, that way we may have some data
    //startUpPeripherals();
    //takeReading(true);
    //shutDownPeripherals();
}



/****************************************************************
 * Standard Arduino Loop routine
 ****************************************************************/
void loop() {
  Serial.begin(9600);
  Serial.println("looping");
  
   /* if (watchdog) {
        handleWatchdog();
    }*/
    
    if (mode != 'C') {
        digitalWrite(LED, HIGH);

        //runReadings();
        
        //DEBUGPRINTLN(">>>>> HERE <<<<<<<<");
        //byte old_ADCSRA = ADCSRA;
        //ADCSRA = 0;
        //ADMUX = 0; // turn off internal Vref
        //wdt_disable();


digitalWrite(LED, LOW);
delay(500);
digitalWrite(LED, HIGH);
delay(500);
digitalWrite(LED, LOW);
        sleepNow();

        DEBUGPRINTLN(">> AWAKE <<");
        // put ADC back
        //ADCSRA = old_ADCSRA;
        

    } else {
        //continuous mode
        //wdt_reset();
        startUpPeripherals();
        takeReading(false);
        delay(500);
    }
}



void sleepNow(void)
{
    Serial.println("Going to sleep");  
    
  sleep_enable();
  attachInterrupt (0, irqZeroHandler, FALLING);
        
  set_sleep_mode (SLEEP_MODE_PWR_DOWN);  

   cli();
  sleep_bod_disable();
  sei();
  sleep_cpu();
  /* wake up here */
  sleep_disable();

}


/*****************************************************************
 * Interrupt handler for interrupt 0 - external
 *****************************************************************/
void irqZeroHandler() {
    // cancel sleep as a precaution
    sleep_disable();
    // must do this as the pin will probably stay low for a while
    detachInterrupt(0);    
}


/*****************************************************************
 * IThe watchdog fired, take action
 *****************************************************************/
void handleWatchdog(){
  //wdt_reset();
        watchdog = false;
        Serial.begin(9600);
        delay(50);
        Serial.println("Watchdog interrupted!");

        //turn off the BMP if it is on, if not turn off the SD
        //since these have been known to cause hangs...
        
        int hasBmp=0;
    EEPROM.get(EADR_BMP, hasBmp);
    int hasSD=0;
    EEPROM.get(EADR_SD, hasSD);
        if (hasBmp) {
            hasBmp = false;
            EEPROM.write(EADR_BMP, 0);
        } else if (hasSD) {
            hasSD = false;
            EEPROM.write(EADR_SD, 0);
        }
}



/*****************************************************************
 * Take a batch of readings
 *****************************************************************/
void runReadings() {
    //setWdt();

    if (honeymoon > 0) {
        honeymoon--;  
        DEBUGPRINT(honeymoon);
        DEBUGPRINT(" Woke up at ");
        char dateBuf[28];
        getFormattedTime(dateBuf);
        DEBUGPRINTLN(dateBuf);
        for(int i=0; i<5; i++) {
            digitalWrite(LED, HIGH);
            delay(500);
            digitalWrite(LED, LOW);
            delay(500);
        }

        //wdt_reset();

    getFormattedTime(dateBuf);
        DEBUGPRINTLN(dateBuf);
        //wdt_reset();
    }

    //we wake up every minute check if we need to do anything
    DEBUGPRINT("intCount: ");
    DEBUGPRINTLN(intZeroCount);
    int interval;
    interval = EEPROM.get(EADR_INTERVAL, interval);
    if (intZeroCount++ > interval) {
        intZeroCount = 0;        
        //warm up and take a reading
        startUpPeripherals();
        takeReading(true);
        //take DD_READ_SECS number of readings as a batch
        for (int loopCt=0; loopCt < DD_READ_SECS; loopCt++) {
            takeReading(false);
            delay(1000);
        }
        DEBUGPRINTLN("Readings taken");
        
        //shutDownPeripherals();
    }
}



/*****************************************************************
 * Take a reading
 *****************************************************************/
void takeReading(bool warmUp) {

    //DEBUGPRINTLN("Taking anemometer reading");
    //wdt_disable();
    if (warmUp) {
        DEBUGPRINTLN("Warming up anemometer");
        //wait for the anemometer to warm up
        delay(DD_WARM_MS);
    }

    //setWdt();
    int hasBmp=0;
    EEPROM.get(EADR_SD, hasBmp);
    

    delay(50);
    float anem = readDraft();

    //internal datalogger voltage
    int loggerVoltage = vccCheck();

    //battery voltage on pin A1
    int vBat = analogRead(1);

char dateBuf[28];
    getFormattedTime(dateBuf);
    Serial.print(dateBuf);
    Serial.print(" ");

    char sdbuf[50];
    snprintf(sdbuf, 40, " %04d %04d %lu %03d %03d",
            anem,
            temperature,
            pressure,
            loggerVoltage,
            vBat);
    Serial.println(sdbuf);

    //writeSDData(dateBuf, sdbuf);
}

/*****************************************************************
 * Read the draft detector (ensure StartPeripherals has been called
 * first)
 *****************************************************************/
float readDraft() {

    //Read the anemometer on A0, average 10 readings
    int aVal = 0;
    int avSum = 0;
    for (int i = 0; i < 10; i++) {
        analogRead(0);
        delay(20);
        aVal = analogRead(0);
        avSum += aVal;
    }
    //DEBUGPRINT("aVal=");
    //DEBUGPRINTLN(aVal);
    return avSum / 10;
}



/*****************************************************************
 * get the date/time and format it as a string
 *****************************************************************/
/*
* format the RTC date
*/
void getFormattedTime(char * datebuf) {
  Serial.println("Entering getFormattedTime");
  DateTime now = rtc.now();
  //DEBUGPRINTLN(now.year(), DEC);
  snprintf(datebuf, 20, "%02d/%02d/%02d %d:%02d:%02d",
  now.year(),
  now.month(),
  now.day(),
  now.hour(),
  now.minute(),
  now.second() );
}

/****************************************************************
 * Configure the system
 ****************************************************************/
void configure() {
    //wdt_disable();

    //clear any serial
    while (Serial.available() > 0) {
        char t = Serial.read();
    }

    //Date/time
    char dateBuf[28];
    
    getFormattedTime(dateBuf);
    Serial.print("Clock: ");
    Serial.println(dateBuf);
    
    DateTime t = rtc.now();
    
    promptWithDefault("Year", t.year());
    int year = readSerialInt(t.year());
    promptWithDefault("Month", t.month());
    int month = readSerialInt(t.month());
    promptWithDefault("Day", t.day());
    int day = readSerialInt(t.day());
    promptWithDefault("Hour", t.hour());
    int hour = readSerialInt(t.hour());
    promptWithDefault("Minutes", t.minute());
    int minute = readSerialInt(t.minute());
    promptWithDefault("Seconds", t.second());
    int second = readSerialInt(t.second());
    rtc.adjust(DateTime(year, month, day, hour, minute, second));

    getFormattedTime( dateBuf);
    Serial.print("Clock set to ");
    Serial.println(dateBuf);

    //reading interval for the anemometer
    int interval = 30;
    EEPROM.get(EADR_INTERVAL, interval);
    promptWithDefault("Interval (mins)", interval);
    interval = readSerialInt(interval);
    EEPROM.put(EADR_INTERVAL, interval);

    int hasBmp=0;
    EEPROM.get(EADR_BMP, hasBmp);
    promptWithDefault("BMP 0/1", hasBmp);
    hasBmp = readSerialInt(hasBmp);
    DEBUGPRINTLN(hasBmp);
    EEPROM.put(EADR_BMP, hasBmp);

    int hasSD=0;
    EEPROM.get(EADR_SD, hasSD);
    promptWithDefault("SD 0/1", hasSD);
    hasSD = readSerialInt(hasSD);
    DEBUGPRINTLN(hasSD);
    EEPROM.put(EADR_SD, hasSD);

    int curV = vccCheck();
    DEBUGPRINTLN(curV);
    promptWithDefault("SD min V", curV - 10);
    curV = readSerialInt(curV - 10);
    EEPROM.put(EADR_SD_V, curV);
    DEBUGPRINT("voltage setting");
    //DEBUGPRINTLN(curV);

}


/*****************************************************************
 * read an int from over serial, retun -1 if nothing
 *
 * Serial.parseInt() really only good if the input is guaranteed to be only an int
 *****************************************************************/
int readSerialInt(int origVal) {
    int val = origVal;
    char ch;
    int serBufIdx = 0;
    char serialBuf[4] = {0, 0, 0, 0}; //longest int to read
    while (serBufIdx < 4) {
        //DEBUGPRINT("Serial available=");
        //DEBUGPRINTLN(Serial.available());
        while (!Serial.available()); //wait for some input
        ch = Serial.read();
        if (ch < 0) break;
        if (ch > 47 && ch < 58) {
            //ch is a digit
            serialBuf[serBufIdx++] = ch;
        } else {
            break;
        }
    }
    if (serBufIdx > 0) {
        val = atoi(serialBuf);
    }
    return val;
}

/****************************************************************
 * Issue a prompt over serial
 ****************************************************************/
void promptWithDefault(const char prompt[], int defaultVal) {
    Serial.print(prompt);
    Serial.print("? [");
    Serial.print(defaultVal, DEC);
    Serial.println("]");
}

void displayVal(const char message[], int val) {
    Serial.print(message);
    Serial.print("=");
    Serial.println(val, DEC);
}

/****************************************************************
 * Switch on the SD and draft detector
 ****************************************************************/
void startUpPeripherals() {

    //FET to control SD card power
    pinMode(FET, OUTPUT);
    digitalWrite(FET, LOW);

    pinMode(DD_PWR, OUTPUT);
    digitalWrite(DD_PWR, LOW);

    delay(200);

}

/****************************************************************
 * Power down the SD and Draft Detector
 ****************************************************************/
void shutDownPeripherals() {

    delay(20);
    //pinMode(SD_CS, OUTPUT);
    //digitalWrite(SD_CS, HIGH);
    //pinMode(RTC_CS, OUTPUT);
    //digitalWrite(RTC_CS, HIGH);
    //FET to control SD card power
    pinMode(FET, OUTPUT);
    digitalWrite(FET, HIGH);
    //turn off draft detector
    pinMode(DD_PWR, OUTPUT);
    digitalWrite(DD_PWR, HIGH);
}



/*****************************************************************
 * Use internal comparator to check Vcc at the atmega
 *****************************************************************/
int vccCheck() {
    // For 168/328 boards
    const long InternalReferenceVoltage = 1056L; // Adjust this value to your boards specific internal BG voltage x1000
    // REFS1 REFS0          --> 0 1, AVcc internal ref. -Selects AVcc external reference
    // MUX3 MUX2 MUX1 MUX0  --> 1110 1.1V (VBG)         -Selects channel 14, bandgap voltage, to measure
    ADMUX = (0 << REFS1) | (1 << REFS0) | (0 << ADLAR) | (1 << MUX3) | (1 << MUX2) | (1 << MUX1) | (0 << MUX0);

    delay(50); // Let mux settle a little to get a more stable A/D conversion
    // Start a conversion  
    ADCSRA |= _BV(ADSC);
    // Wait for it to complete
    while (((ADCSRA & (1 << ADSC)) != 0));
    // Scale the value
    int results = (((InternalReferenceVoltage * 1023L) / ADC) + 5L) / 10L; // calculates for straight line value 
    return results;
}

/*****************************************************************
 * Set the watch dog to use an interrupt
 *****************************************************************/
void setWdt() {
    /*SREG &= ~(1 << SREG_I); //disable global interrupts
    //prepare the watchdog's register
    WDTCSR |= ((1 << WDCE) | (1 << WDE));
    //set the "Interrupt Mode" with a timeout of 8 sec
    WDTCSR = (1 << WDCE) | (1 << WDE);
    SREG |= (1 << SREG_I); //re-enable global interrupts*/
    
    // Clear the reset flag, the WDRF bit (bit 3) of MCUSR.
MCUSR = MCUSR & B11110111;
  
// Set the WDCE bit (bit 4) and the WDE bit (bit 3) 
// of WDTCSR. The WDCE bit must be set in order to 
// change WDE or the watchdog prescalers. Setting the 
// WDCE bit will allow updtaes to the prescalers and 
// WDE for 4 clock cycles then it will be reset by 
// hardware.
WDTCSR = WDTCSR | B00011000; 

// Set the watchdog timeout prescaler value to 1024 K 
// which will yeild a time-out interval of about 8.0 s.
WDTCSR = B00100001;

// Enable the watchdog timer interupt.
WDTCSR = WDTCSR | B01000000;
MCUSR = MCUSR & B11110111;
}

ISR(WDT_vect) {
    watchdog = true;
}

Don’t you think it would have helped to actually share the exact macro?

Add a flush() after every print() to make sure they are synchronous with the code steps

1 Like

The logical conclusion would be you need to look for the problem no in Serial.println, but rather in your DEBUGPRINTLN macro, which, of course, you did not show us...

Here's the header with the macro, nothing special

#include "Arduino.h"

//Send debug info to serial
#define DEBUG
#ifdef DEBUG
#define DEBUGPRINT(x)  Serial.print(x);
#define DEBUGPRINTLN(x)  Serial.println(x);
#else
#define DEBUGPRINT(x)
#define DEBUGPRINTLN(x)
#endif

//Pins
#define LED 7
//#define LED 13
#define SD_CS SS
#define RTC_CS 9
#define FET 6
#define DD_PWR 4

//Actions
#define ACT_SETUP B00000001
#define ACT_INT0  B00000010
#define ACT_INT1  B00000100

//the file to write to on the SD card
#define FILENAME "Logger.txt"

//number of seconds for which to read the Draft Detector 
//it typically takes around 30 secs to settle
#define DD_READ_SECS 10
#define DD_WARM_MS 30000

//BMP085 stuff
#define BMP085_ADDRESS 0x77  // I2C address of BMP085

///////////////////// end BMP085 ///////////////////

Good point, I'll do that, thanks.

With your macro this won’t work as you don’t handle multiple parameters

DEBUGPRINTLN(now.year(), DEC);

(But it’s commented out)

Okay, @J-M-L advice to use serail.flush has helped me narrow down the issue, thanks all.

Good

Have fun

PS

I’m often using this for debug

#define DEBUG 1    // SET TO 0 OUT TO REMOVE TRACES

#if DEBUG
#define D_SerialBegin(...) Serial.begin(__VA_ARGS__);
#define D_print(...)       Serial.print(__VA_ARGS__)
#define D_write(...)       Serial.write(__VA_ARGS__)
#define D_println(...)     Serial.println(__VA_ARGS__)
#else
#define D_SerialBegin(bauds)
#define D_print(...)
#define D_write(...)
#define D_println(...)
#endif

instead of Serial.print() or Serial.write() you use D_print() and D_write()

if you set the #DEBUG macro to 0 then all traces and opening of the Serial port will go away and it handles any number of parameters

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.