Arduino RTC Adjustment Sketch

Definitions and Declarations

/*

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


Setup and Loop

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

}

Functions

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;

}