[PLUG] Arduino issue
Denis Heidtmann
denis.heidtmann at gmail.com
Mon Sep 26 03:44:31 UTC 2016
On Sat, Sep 24, 2016 at 5:56 PM, Russell Senior <russell at personaltelco.net>
wrote:
> >>>>> "Denis" == Denis Heidtmann <denis.heidtmann at gmail.com> writes:
>
> Denis> I am developing a logging program. The Arduino is a Uno R2. It
> Denis> has an ATAfruit SD shield w/ RTC. For testing purposes I record
> Denis> data once per second. When I am finished testing I will be
> Denis> taking data much less frequently, although there might be random
> Denis> times when a few data points are only one second apart.
>
> Denis> I convert the data ( a long; two strings, 3 ints) to a string in
> Denis> CSV format. But often not all the data gets assembled into the
> Denis> string. It seems that the += operation does not append the
> Denis> string to be added.
>
> Denis> I removed the references to the SD card and the failures went
> Denis> away, or so it seems. I need to run it for a longer time, but
> Denis> before I removed the SD stuff the problem showed up in two to
> Denis> four seconds. So let's assume that the issue was the SD writing.
>
> Denis> How might I go about exploring this issue?
>
> Can you post the relevant code?
Since I do not know what code is relevant, I must post the entire thing,
warts and all. The function which has been my focus is the csv_data, so it
is filled with spurious Serial.print commands. I have since found that +=
will append ints to Strings. Changing csv_data to use that feature does
not change the behavior: things do not get added to the string being
assembled. Note that initially the code worked fine. Then I noticed that
some items did not appear in the returned string. Finally most recently no
complete strings get returned. Then I found that if I removed the code
relating to the SD, the problem went away.
What I believe the cause of the gradual change from good to bad is that I
regularly remove the SD from the Arduino, put it in the laptop, view the
data, then delete the files before unmounting it and returning it to the
Arduino. I notice that although I empty the trash the laptop reports that
there is still some space used, an amount that has been slowly increasing
over the days I have been exploring this issue. (It would not surprise me
if formatting the SD would make the problem go away for a while.)
As to keeping data in ram; other threads in use, etc.: I thought that the
Arduino was single-threaded, and I have no clue which data is stored where.
Looks like version 1.6.9 of the Arduino IDE. I am running Ubuntu 16.04 The
SD library is SD Built-in by Arduino, SparkFun Version 1.0.8
Please excuse the long post. Feel free to discard any irrelevant code
below.
-Denis
/*
hot water heater logger
9/13/2016 added limit to # records in file
9/21/2016 changing to using difference between successive reading
as a way to detect change in state. Of questionable
accuracy in detecting water in use.
The circuit:
* Flue TC pin 0 amp gain 325 type J TC
* Cold H2O pin 1 amp gain 1000 type J TC
* temp. of cold water pipe at input to tank rises
* when no water is being used. It drops to the
* temp. of water supply when the water is used.
* Hot H2O pin 2 type 36 sensor
*
* SD card attached to SPI bus as follows:
** MOSI - pin 11
** MISO - pin 12
** CLK - pin 13
** CS - pin 10
*/
#include <SPI.h>
#include <SD.h>
#include <Wire.h>
#include "RTClib.h"
RTC_DS1307 rtc;
const int chipSelect = 10;
const int flue_pin = 0;//amp gain approx. 360
const int cold_pin = 1;//amp gain approx. 1000
const int hot_pin = 2;//type 36, no gain
const int d_flueToff = -10; //burner going off diff
const int d_flueTon = +10; //burner going on diff
const int d_coldTon = -1; //water going on diff
const int d_coldToff = +2; //water going off diff
long t1; //unix time
const int report_interval = 600; //seconds
const int maxcount = 1008; // limits # records in file.
int rem1; //remainder of time/interval
boolean burn_on; //burner is on
boolean H2O_on; //water is in use
volatile boolean close_file = false;
const int greenLEDpin=4;
const int redLEDpin=3;
String dataString;
String filename;
File dataFile;
int Tflue1,Tflue2,Tcold1,Tcold2,Thot;
void setup() {
pinMode(redLEDpin, OUTPUT);
pinMode(greenLEDpin, OUTPUT);
// Open serial communications:
Serial.begin(9600);
attachInterrupt(digitalPinToInterrupt(2),button_press,RISING);
Serial.print("Initializing SD card...");
// see if the card is present and can be initialized:
if (!SD.begin(chipSelect)) {
Serial.println("Card failed, or not present");
fail_flash(2);
}
Serial.println("card initialized.");
if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
fail_flash(3);
}
//short wait on reset or power on w/ rapid green flashing
for(int i = 1; i<16; i++){
digitalWrite(greenLEDpin,HIGH);
delay(150);
digitalWrite(greenLEDpin,LOW);
delay(150);
}
}
void loop() {
int count = 0;
//Generate file name:
filename = "D";
time_temp(t1,Tflue1,Tcold1,Thot);//initial data
String foo = String(t1);
int n = foo.length();
foo = foo.substring(n-7); //7 digits of seconds to make name
filename += foo;
filename += ".csv";
//now set initial states
burn_on = false; //arbitrary
H2O_on = false; //arbitrary
rem1 = t1%report_interval;
Serial.println("");
Serial.println("");
Serial.println(filename);
dataFile = SD.open(filename,FILE_WRITE);
if(!dataFile){
Serial.print(filename);
Serial.println(" failed to open");
fail_flash(4);
}
String title =
"unix-time,burner-status,water-status,hot-water-T(dn),flue-T(dn),cold-water-T(dn)";
// expect: seconds, burn_on or off, H2O_on or off, C = dn/2-52.2,
C=.285*dn+rT, C=.0926*dn +rT
// the above calculations need to be updated.
Serial.println(title);
foo = csv_data(t1,burn_on,H2O_on,Thot,Tflue1,Tcold1);
Serial.println(foo);
dataFile.println(title);
dataFile.println(foo);
while(count < maxcount){ // Limits # records in file:
boolean report = true;//make this true to record all data
long t2;
digitalWrite(greenLEDpin,HIGH);
delay(100);
digitalWrite(greenLEDpin,LOW);
delay(900);
time_temp(t2, Tflue2, Tcold2, Thot); // new data
int rem2=t2%report_interval;
if (rem2<rem1){
report = true;
//Serial.print("new time:");
}
rem1=rem2;
if (burn_on){
if (Tflue2 - Tflue1 < d_flueToff){
burn_on = false;
report = true;
Serial.print("burner going off:");
}
}
else {
if (Tflue2 - Tflue1 > d_flueTon){
burn_on = true;
report = true;
Serial.print("burner turning on:");
}
}
Tflue1 = Tflue2;
if (H2O_on){
if (Tcold2 - Tcold1 > d_coldToff){
H2O_on = false;
report = true;
Serial.print("water going off:");
}
}
else {
if (Tcold2 -Tcold1 < d_coldTon){
H2O_on = true;
report = true;
Serial.print("water turning on");
}
}
Tcold1 = Tcold2;
if (report || close_file){ // record final data point on close
dataString = csv_data(t2,burn_on,H2O_on,Thot,Tflue2,Tcold2);
Serial.println(dataString);
dataFile.println(dataString);
count++;
}
if(close_file){
Serial.println("closing file");
dataFile.close();
delay(1000);//ignore switch bounce
digitalWrite(redLEDpin, LOW);
while(1){ //wait forever for RESET
digitalWrite(greenLEDpin, HIGH);
delay(1500);
digitalWrite(greenLEDpin, LOW);
delay(500);
}
}
} //end while
Serial.println("closing file");
dataFile.close();
} // end loop
//Get time and data:
void time_temp(long &t_sec, int &flue_T, int &cold_T, int &hot_T){
DateTime now = rtc.now();
t_sec = now.unixtime();
flue_T = analogRead(flue_pin);
cold_T = analogRead(cold_pin);
hot_T = analogRead(hot_pin);
}
//ISR:
void button_press(){
close_file = true;
digitalWrite(redLEDpin, HIGH);
}
//assemble data into a csv string:
String csv_data(long t, boolean burn_state, boolean H2O_state, int hot_T,
int flue_T, int cold_T){
String dum;
String foo = String(t);
foo += ",";
if(burn_state){
foo += "burn_on,";
} else {
foo += "burn_off,";
}
if(H2O_state){
foo += "H2O_on,";
} else {
foo += "H2O_off,";
}
dum = String(hot_T);
Serial.print(hot_T);
Serial.print(" hot len =");
Serial.println(dum.length());
foo += dum;
foo += ",";
dum = String(flue_T);
Serial.print(flue_T);
Serial.print(" flue len =");
Serial.println(dum.length());
foo += dum;
foo += ",";
dum = String(cold_T);
Serial.print(cold_T);
Serial.print(" cold len =");
Serial.println(dum.length());
foo += dum;
return foo;
}
//rapid LED error flashing
void fail_flash(int n){
while(1){
for(int i=1;i<=n;i++){
digitalWrite(redLEDpin, HIGH);
delay(150);
digitalWrite(redLEDpin, LOW);
delay(150);
}
delay(1000);
}
}
More information about the PLUG
mailing list