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