• 1
    Step 1

    First step is to build the electronics.

    The logger is built on proto-board according to the following schematic:

    The following images show the locations of the components and the layout of the 'tracks':

  • 2
    Step 2

    Program the Ardulog using the Arduino software

    /*
    
    Ardulog voltage/current logger
    
    Copyright (c) 2015, Rob Reilink
    All rights reserved.
    
    Redistribution and use in source and binary forms, with or without modification,
    are permitted provided that the following conditions are met:
    
    1. Redistributions of source code must retain the above copyright notice, this 
       list of conditions and the following disclaimer.
    
    2. Redistributions in binary form must reproduce the above copyright notice, this
       list of conditions and the following disclaimer in the documentation and/or 
       other materials provided with the distribution.
    
    3. Neither the name of the copyright holder nor the names of its contributors may
       be used to endorse or promote products derived from this software without
       specific prior written permission.
    
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
    OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
    OF THE POSSIBILITY OF SUCH DAMAGE.
    
    
    */
    #include <SPI.h>
    #include <SD.h>
    
    const int chipSelect = 10;
    const int ledGreen = 5;
    const int ledOrange = 13; // shares pin with SD card sck -- only used in fatal()
    const int cardDetect = 6;
    
    const float calibration0 = 0.04271698113207547;  // gain for AD channel 0
    const float calibration1 = 0.026728723404255316;  // gain for AD channel 1
    
    
    char * logdir = "/log";
    String filename;
    unsigned long prevmillis = 0;
    
    void fatal(char *message) {
      Serial.println(message);
    
      for(;;) {
        digitalWrite(ledGreen, HIGH);
        pinMode(ledOrange, OUTPUT);
        SPI.end();
    
        digitalWrite(ledOrange, HIGH);
        delay(100);
        digitalWrite(ledOrange, LOW);
        delay(100);
        digitalWrite(ledOrange, HIGH);
        delay(100);
        digitalWrite(ledOrange, LOW);
        delay(100);
        digitalWrite(ledOrange, HIGH);
        delay(100);
        digitalWrite(ledOrange, LOW);
        delay(400);   
      }
    }
    
    boolean cardDetected() {
      return !digitalRead(cardDetect);
    }
    
    
    void setup() {
      // Open serial communications and wait for port to open:
      Serial.begin(57600);
      pinMode(ledGreen, OUTPUT);
      pinMode(ledOrange, OUTPUT);
      pinMode(2, OUTPUT);
    
      Serial.println("Reset");
      if (!cardDetected()) {
        fatal("No card present");
      }
    
    
      Serial.print("Initializing SD card...");
    
      // see if the card is present and can be initialized:
      if (!SD.begin(chipSelect)) {
        fatal("Card failed, or not present");
      }
    
      if (!SD.mkdir(logdir)) {
        fatal("Could not create log dir");
      }
    
      Serial.println("ok");
      //writeline("==================");
    
      // find new filename
      int number = 1;
    
      while(1) {
        filename = "0000" + String(number); 
        filename = String(logdir) + String("/") + filename.substring(filename.length()-5) + ".txt";
        if (!SD.exists((char*)filename.c_str())) {
          break;
        }
        number+=1;
        if (number==10000) {
    
          fatal("Maximum number of log files exceeded");
        }
      }  
    
    
    
      prevmillis = millis();
    
      // setup timer 1 for 10Hz measurements
      cli();
      TCCR1A = 0;
      TCCR1B = 0;
      TCNT1 = 0;
      OCR1A = 6250 - 1;
      TCCR1B = _BV(WGM12) | _BV(CS12) ; // 16MHz :256
      TIMSK1 |= _BV(OCIE1A);
      sei();
    
    }
    
    byte toggle;
    long filterAD0 = 0;
    long filterAD1 = 0;
    int numAD = 0;
    
    
    ISR(TIMER1_COMPA_vect) {
        toggle = !toggle;
        digitalWrite(2, toggle);
        
        analogRead(0); // dummy read reduces crosstalk
        filterAD0 += (analogRead(0) - filterAD0 / 10);
        analogRead(1); // dummy read reduces crosstalk
        filterAD1 += (analogRead(1) - filterAD1 / 10);
        
        
        numAD += 1;
        
        
        
    }
    
    
    
    void writeline(String line) {
      File logFile;
      
      byte written = 0;
      
      if (!cardDetected()) {
        fatal("SD card removed");
      }
      
      logFile = SD.open(filename.c_str(), FILE_WRITE);
      if (logFile) {
        written = logFile.println(line);
        if (written) {
          Serial.println(line);
          digitalWrite(ledGreen, HIGH);
          delay(100);
          digitalWrite(ledGreen, LOW);
          
        }
      }
      logFile.close();
      
      // in case of error abort to prevent writing on a newly inserted sd card
      if (!written) {
        fatal("Error writing to the SD card"); 
      }
    }
    
    
    void loop() {
    
      // make a string for assembling the data to log:
      String dataString = "";
      long ad0, ad1;
    
      do {
        cli();
        if (numAD<10) {
          sei();
          continue;
        }
        
      } while(0);
      // interrupts are disabled and we have enough samples;
      ad0 = filterAD0 / 10;
      ad1 = filterAD1 / 10;
      numAD = 0;
      sei();
    
    
      dataString += String(calibration0 * ad0, 3);
      dataString += ",";
      dataString += String(calibration1 * ad1, 3);  
    
      writeline(dataString);
    
    
      while (millis() - prevmillis < 1000);
      prevmillis += 1000;
    
    }
    

  • 3
    Step 3

    Installing:

    - Build the electronics into a casing

    - Remove the red battery cable terminal from its connector. Pass it through the current sensor in its positive current direction (indicated by an arrow on the case). Connect the positive supply lead of the logger to the connector terminal and insert the terminal back into the connector

    - Remove the black battery cable terminal, connect the negative supply lead of the logger, and re-insirt the terminal into the connector