/*
SD card datalogger "Adjust.cpp"
Hardware: Duemilaove withAT238, Adafruit logger shield
and Arduino proto-shield with LCD shift register
Four analog inputs on DA9S pins 1 - 4 to A0-A3
RTC with I2C on A4 and A5
Serial 20x4 LCD using D2,D3,D4
Two switches on D5 & D6, which also has a LED
External digital I/O on DA9S pins 7,8,9, with LEDs using D7,D8 & D9
SD SPI interface using D10,D11,D12 & D13
The SD card has year and month directiries pre-made
There is one CSV file created per day
John Saunders 7/25/2012
The analog reference is 3.072 V to ger 3mv/count from the Duemilanove 3.3V
*/
#define DS1307_I2C_ADDRESS 0x68
#define leftSW 5
#define rightSW 6
#include <SerialLCD.h>
#include <Wire.h>
const int chipSelect = 10;
SerialLCD lcd(2);
// The order of DS1397 values is: secs,mins,hours,weekday(not used),date,month,year(2 digit)
const char recFileIndex[] = {99,99,99,98,8,3,0}; //These are DS1307 addresses or 99=skip
const char recDateIndex[] = {99,99,99,98,3,0,8};
const char recTimeIndex[] = {6,3,0,98,99,99,99}; //98 is a flag for midnight
const byte aPin[] = {0,1,2,3}; // the analog pin to be measured
const byte D9pin[] = {1,2,3,4}; // the D9 pin to which it is connected
const byte dPin[] = {7,8,9};
const char LCDColAddr[] = {0,10,0,10}; // for analog LCD placing
const char LCDRowAddr[] = {2,2,3,3};
// for each range 3V - 24 V by 3 there are specific calculations, per the range,Index for the input 0- 7
const int mult[] = {9,6,9,6,6,9,10,12};
const int divide[] = {3,1,1,5,4,5,5,5};
const char header[] = {"Date,Time,Pin 1,Pin2,Pin 3,Pin4,Pin7,Pin8,Pin9"};
const char intTimeIndex[] = {7,6,4,3}; //RTC addresses for options for recording interval
const char* settingStrings[] = {"minutes","hours","Pin 1 range","Pin 2 range","Pin 3 range","Pin 4 range","Finished"};
const char* intervalStrings[] = {"1 sec","10 sec","1 min","10 min"};
const byte adjustAddr[] = {0x01,0x02,0x08,0x09,0x0A,0x0B}; //For adjusting & saving setup parametyers
const byte adjustLimit[] = {59,23,7,7,7,7};
char oldDay = '0'; // To find midnight to write the header
char newDay;
char interval = '0'; // the previous value of the selected element of recTime
byte intIndex; // Index into intIndex, stored in DS1307 at address 0x0C
byte rangeIndex[4]; // Index into mult and divide, stored in DS1307 at addresses 0x08-0x0x0B
char D8prev = 1; // State of left button
boolean cardOK = true;
boolean initCount = true;
// These are templates to be populated from the RTC. Put here to help stability
char recDate[] = {"mm/dd/20yy, "};
char recTime[] = {"hh:mm:ss "};
int analogIn[] = {-1,-1,-1,-1};
char analogString[4][7];
char dateFilename[] = {"yy/mm/ARdd.CSV"};
boolean adjustments(byte);
boolean recordHeaders(char *);
boolean recordData(char *);
void makeTimings();
int makeAnalog(int,int,byte dploc = 3);
void setup()
{
lcd.begin();
Wire.begin();
analogReference(EXTERNAL); // set by potentiometer to 3.072 volts (3 mv/count)
pinMode(leftSW,INPUT_PULLUP);
pinMode(rightSW,INPUT_PULLUP);
pinMode(7,INPUT_PULLUP);
pinMode(8,INPUT_PULLUP);
pinMode(9,INPUT_PULLUP);
byte countdown;
for (countdown=0; countdown < 10; countdown++) {
lcd.clear();
lcd.print("Press left switch");
lcd.printStr("for setup options",2);
lcd.setCursor(0,3);
lcd.print(10-countdown);
if(digitalRead(leftSW) == 0) {
break;
}
delay(300);
}
if (countdown < 10) {
lcd.clear();
lcd.print("Entering setting mode");
byte selection = 0;
while(digitalRead(leftSW) == 0) {
delay(100);
}
while(true) {
lcd.clear();
lcd.print("Adjust ");
lcd.printStr(settingStrings[selection]);
lcd.setCursor(0,2);
lcd.print("Press left switch");
lcd.setCursor(0,3);
lcd.print("to select this");
delay(1000);
if(digitalRead(leftSW) == 0) {
if(selection == 6) {
break;
}
else {
D8prev = 0;
adjustments(selection);
}
}
selection++;
if (selection > 6) {
selection = 0;
}
}
} //End of setting mode
// retrieve and display the range and interval settings from the RTC RAM
lcd.clear();
lcd.print("Range settings:");
lcd.setCursor(0,2);
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(0x08);
Wire.endTransmission();
Wire.requestFrom(DS1307_I2C_ADDRESS,5);
for(char i=0;i<4;i++) {
rangeIndex[i] = Wire.read();
if(rangeIndex[i]>7) {
rangeIndex[i] = 0;
}
if(i==2) {
lcd.setCursor(0,3);
}
lcd.print("Pin");
lcd.print(D9pin[i]);
lcd.print('=');
lcd.print(3*(rangeIndex[i]+1));
lcd.print("V ");
}
intIndex=Wire.read();
Wire.endTransmission();
lcd.setCursor(0,4);
lcd.print("Press left switch ");
do {
delay(300);
}
while(digitalRead(leftSW)==1);
D8prev=0;
}
void loop()
{
int analogReading[4];
byte analogCount[4];
if(digitalRead(rightSW)==0) { //This permits safe SD removal
lcd.clear();
lcd.print("Stopped to remove SD");
lcd.setCursor(0,2);
lcd.print("Re-booting...");
setup();
}
makeTimings(); // Generate the filename and date and time strings
if ( initCount == true) {
for(byte i=0;i< 4;i++) {
analogReading[i] = 0;
analogCount[i] = 0;
analogIn[i] = 0;
interval = recTime[intTimeIndex[intIndex]];
}
initCount = false;
}
// Display th date,time,analog values and selected interval
lcd.clear();
lcd.print(recDate);
lcd.print(recTime);
// read four analog pIns and display their values
for (int i = 0; i < 4; i++) {
byte range = rangeIndex[i];
byte dpLoc = 2;
if(range < 3) {
dpLoc++;
}
analogReading[i] += analogRead(aPin[i]);
analogCount[i]++;
lcd.setCursor(LCDColAddr[i],LCDRowAddr[i]);
lcd.print('P');
lcd.print(D9pin[i]);
lcd.print('=');
if(analogCount[i] >= mult[range]) {
analogIn[i] = analogReading[i]/divide[range];
analogCount[i] = 0;
analogReading[i] = 0;
}
makeAnalog(i,analogIn[i],dpLoc);
lcd.printStr(analogString[i]);
}
lcd.setCursor(0,4); // bottom line
lcd.print("Rec. Int. = ");
lcd.printStr(intervalStrings[intIndex]);
char D8now = digitalRead(leftSW);
oldDay = newDay;
// Run-time change of recording interval
if((D8now == 0) && (D8prev == 1)) {
intIndex ++;
if(intIndex >= 4) {
intIndex = 0;
}
// store this value into the DS1307 at address 0x0C
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(0x0C);
Wire.write(intIndex);
Wire.endTransmission();
}
interval = recTime[intTimeIndex[intIndex]];
D8prev = D8now;
delay(70);
}
boolean adjustments(byte adrInx) {
byte adjustValue;
byte adjustBCD;
char D8now;
lcd.clear();
lcd.print("Adj. ");
lcd.printStr(settingStrings[adrInx]);
lcd.print('=');
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(adjustAddr[adrInx]);
Wire.endTransmission();
Wire.requestFrom(DS1307_I2C_ADDRESS,1);
adjustBCD = Wire.read();
Wire.endTransmission();
adjustValue = (adjustBCD & 0x0F) + (10*(adjustBCD>>4));
lcd.setCursor(0,2);
lcd.print("Left SW: adjust");
lcd.setCursor(0,3);
lcd.print("Right SW: done");
while(digitalRead(rightSW) == 1) {
lcd.setCursor(17,0);
if(adrInx>1) {
lcd.print(3*(adjustValue + 1));
}
else {
lcd.print(adjustValue);
}
lcd.print(' ');
D8now = digitalRead(leftSW);
if((D8now == 0) && (D8prev == 1)) {
adjustValue++;
if(adjustValue > adjustLimit[adrInx]) {
adjustValue = 0;
}
}
D8prev = D8now;
}
adjustBCD=(adjustValue % 10) + (adjustValue/10*16);
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(adjustAddr[adrInx]);
Wire.write(adjustBCD);
Wire.endTransmission();
return true;
}
void makeTimings() {
char timeValue;
char LSDigit;
char MSDigit;
// Read the time values and assign to the template strings
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(0);
Wire.endTransmission();
Wire.requestFrom(DS1307_I2C_ADDRESS,7);
for(char i=0;i<7;i++) {
timeValue = Wire.read();
LSDigit = (timeValue & 0x0F) + '0';
MSDigit = ((timeValue >> 4) & 0x07) +'0';
if(recFileIndex[i] < 98) {
dateFilename[recFileIndex[i]] = MSDigit;
dateFilename[recFileIndex[i] + 1] = LSDigit;
}
if(recDateIndex[i] < 98) {
recDate[recDateIndex[i]] = MSDigit;
recDate[recDateIndex[i] + 1] = LSDigit;
}
if(recTimeIndex[i] < 98) {
recTime[recTimeIndex[i]] = MSDigit;
recTime[recTimeIndex[i] + 1] = LSDigit;
}
if(recTimeIndex[i] == 98) {
newDay = LSDigit;
}
}
Wire.endTransmission();
return;
}
int makeAnalog(int j,int k,byte dploc) {
int div;
int rem;
int mod = 10000;
byte leading = 0;
byte i = 4;
byte pos = 0;
dploc=constrain(dploc,0,3);
if(k < 0) {
analogString[j][pos++] = '-';
k = -k;
}
while(mod >= 1) {
div = k/mod;
rem = k % mod;
if(leading == 1 || div > 0) {
analogString[j][pos++] = div + '0';
leading = 1;
}
if(leading == 0 && div == 0 && i <= dploc) {
analogString[j][pos++] = div + '0';
}
if(dploc > 0 && i == dploc) {
analogString[j][pos++] = '.';
}
k = rem;
mod = mod/10;
i--;
}
analogString[j][pos] = 0;
return pos;
}