Seismic Data Logger using Arduino UNO and ADS1115

Hi, guys. I have been working on this project for a while now. The geophones are thrust into the ground with spikes attached to the bottom. If there is any vibration, the magnets are set into motion. Then, there is a change in the magnetic lines of force, which induces EMF is induced. The induced EMFs are passed into ADS1115 (a programmable amplifier) because the EMF is too small for the Arduino ADC ports to measure. So, I utilize two ADS1115 in this project, and the geophones are attached in a differential mode as seen on the circuit diagram.
What I am having a tough time with is how to use the time stamp from Arduino to know the time it takes (in milliseconds) for each geophone to record an anomaly whenever a button is pressed for the detonation of acoustic waves. Because I want to be using artificial methods of creating vibration. Below is my code for the project.

#include <SD.h>
#include <SPI.h>
#include "DS3231.h"
#include <Wire.h>
#include <Adafruit_ADS1015.h>
#include <LiquidCrystal_I2C.h>
#include <EEPROMex.h>
const int READY_LED = 5;
const int ERROR_LED = 6;
int vibrateDigitalIn = 2;
boolean bIsVibrating = false;

Adafruit_ADS1115 ads_1(0x48);  /* Use this for the 16-bit version */
Adafruit_ADS1115 ads_2(0x4A);

//Adafruit_ADS1015 ads;     /* Use thi for the 12-bit version */

LiquidCrystal_I2C lcd(0x27,16,2);  // set the LCD address to 0x27 for a 16 chars and 2 line display

File Seismic_file;
DS3231 rtc(SDA, SCL);
int CS_pin = 10; // Pin 10 on Arduino Uno

double Voltage1,  Voltage2, Voltage3,  Voltage4,Time1, Time2, Time3, Time4, Time0;

int addressFloat;

uint8_t Card[8]  = {0x1f,0x11,0x17,0x15,0x15,0x16,0x1c,0x7};
uint8_t Card1[8]  = {0x00,0x00,0x18,0x08,0x08,0x08,0x10,0x00};


// SM24
const float SM24_V_M_S_FACTOR = 28.8;
String g_recvString = "";
double g_scaleFactor = 1.0;
unsigned long timer = 0;
long loopTime = 5000;   // microseconds
uint8_t antiAliasFilterBW = B11;  // 50Hz

void setup() {
  Serial.begin(38400);
  timer = micros();
  lcd.init();                      // initialize the lcd 
  lcd.backlight();

  lcd.createChar(0, Card);
  lcd.createChar(1, Card1);
  addressFloat     = EEPROM.getAddress(sizeof(float));
  
  pinMode(READY_LED, OUTPUT);
  pinMode(ERROR_LED, OUTPUT);
  pinMode(CS_pin, OUTPUT);
  pinMode(vibrateDigitalIn,INPUT);

  digitalWrite(READY_LED, LOW);   // turn the LED on (HIGH is the Voltage1 level)
  digitalWrite(ERROR_LED, LOW);   // turn the LED on (HIGH is the Voltage1 level)
  ads_1.setGain(GAIN_SIXTEEN);    // 16x gain  +/- 0.256V  1 bit = 0.125mV  0.0078125mV
  ads_1.begin();

  ads_2.setGain(GAIN_SIXTEEN);    // 16x gain  +/- 0.256V  1 bit = 0.125mV  0.0078125mV
  ads_2.begin();
  int i = 0;

  lcd.setCursor(0, 0);
  lcd.print("((((Seismic))))");
  lcd.setCursor(2, 1);
  lcd.print("Data Logger");
  lcd.setCursor(13, 1);
  // draw SD card symbol
  lcd.write(0);
  lcd.setCursor(14, 1);
  // draw SD card symbol
  lcd.write(1);
  delay(3000);

  
 
  // SD Card Initialization
  if (SD.begin())
  {
   // Serial.println("SD card is ready to use.");
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("SD card is ready");
    lcd.setCursor(6, 1);
    lcd.print("to use");
    delay(3000);
  } 
  else
    {
    while(1){ 
   // Serial.println("SD card initialization failed");
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("SD card init");
    lcd.setCursor(6, 1);
    lcd.print("Failed!!!");
      digitalWrite(ERROR_LED, HIGH);
      delay(1000);
      digitalWrite(ERROR_LED, LOW);
      delay(1000);
    }
  }

  
 // Serial.println("Date         Time       Volt1(mV) Vel1(m/s) Volt2(mV) Vel2(m/s) Volt3(mV) Vel3(m/s) Volt4(mV) Vel4(m/s)\n");
  Seismic_file = SD.open("Seismic.CSV", FILE_WRITE);

  if (Seismic_file) {
    Seismic_file.println("Voltage1(mV), Time1(ms), Voltage2(mV), Time2(ms), Voltage3(mV), Time3(ms), Voltage4(mV), Time4(ms)\n");
    // Change this text according
    // to what you are measuring; it works as a header for the saved data!
    Seismic_file.close(); // close the file
  }
  // if the file didn't open, print an error:
  else {
    //Serial.println("error opening Seismic.csv");

  }

  
while(bIsVibrating = (digitalRead(vibrateDigitalIn))) {
    lcd.clear();
    lcd.setCursor(3, 0);
    lcd.print("Waiting for");
    lcd.setCursor(0, 1);
    lcd.print("(((Shot Waves)))");
    digitalWrite(ERROR_LED, HIGH);
    delay(50);
    digitalWrite(ERROR_LED, LOW);
    delay(50);
    }
      
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("(((Shot Waves)))");
    lcd.setCursor(3, 1);
    lcd.print("Detected!!!");
    delay(1000);
}

void loop() {
  double output;
  digitalWrite(READY_LED, HIGH);
    /* Be sure to update this value based on the IC and the gain settings! */
  //float   multiplier = 3.0F;    /* ADS1015 @ +/- 6.144V gain (12-bit results1) */
  float multiplier = 0.0078125F; /* ADS1115  @ +/- 6.144V gain (16-bit results1) */
 Voltage1 = ads_1.readADC_Differential_2_3()* multiplier;
 Voltage2 = ads_1.readADC_Differential_0_1()* multiplier;
Voltage3 = ads_2.readADC_Differential_2_3()* multiplier;
 Voltage4 = ads_2.readADC_Differential_0_1()* multiplier;
  

 

  
  //VALUES ON SD CARD
  Seismic_file = SD.open("Seismic.CSV", FILE_WRITE);
  if (Seismic_file) {
    Seismic_file.print(Time0);
    Seismic_file.print(",");
    Seismic_file.print(Voltage1);
    Seismic_file.print(",");
    Seismic_file.print(Time1);
    Seismic_file.print(",");
    Seismic_file.print(Voltage2);
    Seismic_file.print(",");
    Seismic_file.print(Time2);
    Seismic_file.print(",");
    Seismic_file.print(Voltage3);
    Seismic_file.print(",");
    Seismic_file.print(Time3);
    Seismic_file.print(",");
    Seismic_file.print(Voltage4);
    Seismic_file.print(",");
    Seismic_file.print(Time4);
    Seismic_file.print("\n");

    Seismic_file.close(); // close the file
  }
  // if the file didn't open, print an error:
  else {
    //Serial.println("error opening Seismic.CSV");
  }
  getSerialData();
  output = EEPROM.readFloat(addressFloat);
  if(output <= 1.0){
      ///*
 //VALUES ON LCD
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("T1:");
    lcd.setCursor(4,0);
    lcd.print(Time1);
    lcd.setCursor(8, 0);
    lcd.print("T2:");
    lcd.setCursor(12,0);
    lcd.print(Time2);
    lcd.setCursor(0,1);
    lcd.print("T3:");
    lcd.setCursor(4,1);
    lcd.print(Time3);
    lcd.setCursor(8, 1);
    lcd.print("T4:");
    lcd.setCursor(12,1);
    lcd.print(Time4);
     sendToPC(&Time1, &Time2, &Time3, &Time4);
     }
      else
     {
       ///*/
 //VALUES ON LCD
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("V1:");
    lcd.setCursor(4,0);
    lcd.print(Voltage1);
    lcd.setCursor(8, 0);
    lcd.print("V2:");
    lcd.setCursor(12,0);
    lcd.print(Voltage2);
    lcd.setCursor(0,1);
    lcd.print("V3:");
    lcd.setCursor(4,1);
    lcd.print(Voltage3);
    lcd.setCursor(8, 1);
    lcd.print("V4:");
    lcd.setCursor(12,1);
    lcd.print(Voltage4);
      sendToPC(&Voltage1, &Voltage2, &Voltage3, &Voltage4);
    } 

}

What made you think that your question has anything to do with the Website and Forum section which is clearly stated to be for "Improvements for the web system, applications to moderator, spam, etc."? I have suggested to the Moderator to move it to the Project Guidance section.

This sort of carelessness makes unnecessary work for the Moderators.

...R

Robin2: What made you think that your question has anything to do with the Website and Forum section which is clearly stated to be for "Improvements for the web system, applications to moderator, spam, etc."? I have suggested to the Moderator to move it to the Project Guidance section.

This sort of carelessness makes unnecessary work for the Moderators.

...R

I am new here :(

To determine the approximate time elapsed between two events, save the value of millis() at event detection 1, then again at event detection 2, and subtract time1 from time2. Be sure to use unsigned long variables for times.

It will be approximate because the internal clock on the Arduino is not very accurate, and changes with temperature.

need more details on the geophones.

if you plant your geophones 10 meters from the center, then the opposite ones are 20 meters apart. a seismic wave travels at about 1,450 m/s in water up to about 5,000 m/s in granite.

are you talking about a sesimc wave hitting the west most geophone, then the south most, then the east most, then the north most, and from that you will try to establish direction ?

there is some bit of the puzzle that is unclear.

assume a spike on GP-West, you log the time of the event then a spike on GP-south, you log the time then a spike on GP-East, log the time spike on GP-North, log the time.

you can then determine the relative time difference for each spike.

as was noted the internal clock is not super accurate, but I would assume that for this purpose, the relative times would be pretty repetitive from one reading to the next.

dave-in-nj: need more details on the geophones.

if you plant your geophones 10 meters from the center, then the opposite ones are 20 meters apart. a seismic wave travels at about 1,450 m/s in water up to about 5,000 m/s in granite.

are you talking about a seismic wave hitting the west most geophone, then the south most, then the east most, then the north most, and from that you will try to establish direction?

there is some bit of the puzzle that is unclear.

assume a spike on GP-West, you log the time of the event then a spike on GP-south, you log the time then a spike on GP-East, log the time spike on GP-North, log the time.

you can then determine the relative time difference for each spike.

as was noted the internal clock is not super accurate, but I would assume that for this purpose, the relative times would be pretty repetitive from one reading to the next.

Thanks so much, your comment is helpful. There are different arrays of the geophone, which can basically the Single Ended Spread and Split Spread. I want to measure the time it takes in milliseconds for each geophone to record any change in analogue input after seismic waves are being generated. The logger could be close to the source while the geophones are spread in an array of choice as shown in the attached picture

https://en.wikipedia.org/wiki/Geophone#/media/File:Single_End_Spread_&_Split_Stread.jpg

jremington: To determine the approximate time elapsed between two events, save the value of millis() at event detection 1, then again at event detection 2, and subtract time1 from time2. Be sure to use unsigned long variables for times.

It will be approximate because the internal clock on the Arduino is not very accurate, and changes with temperature.

Thanks for the timely reply. Can you please help me with a sample code. I am using ADS1115 for the ADC measurement. I wanted to use array for the scanning of the sensors, but it wasn't helpful or I wasn't doing it right.

May I ask why you are using ADC's?

It would seem from your descripton you are looking to time SPIKES from the geophones. So I'd have thought it would be sufficient to produce a digital signal which you could then time.

THE ADCs you are using use sigma-delta conversion so give good precision but VERY SLOW conversion. Depending on the characteristics of the received signal you will need several samples to see the wave shape. At the highest rate 860sps it will take 12msec to take ten samples from one channel. Then you will need to compare four waves that are different in size shape and time.

Not an easy task

Also - I dont believe your diagram shows a ground connection to the time module & LCD.

johnerrington:
May I ask why you are using ADC’s?

It would seem from your descripton you are looking to time SPIKES from the geophones.
So I’d have thought it would be sufficient to produce a digital signal which you could then time.

THE ADCs you are using use sigma-delta conversion so give good precision but VERY SLOW conversion.
Depending on the characteristics of the received signal you will need several samples to see the wave shape.
At the highest rate 860sps it will take 12msec to take ten samples from one channel.
Then you will need to compare four waves that are different in size shape and time.

Not an easy task

Also - I dont believe your diagram shows a ground connection to the time module & LCD.

I used ADS1115 because the signals generated by the geophones are sinusoidal. With that ADC module, I can be able to measure these signals without causing damages to the Atmega328 chip.

What are the diatances involved between geophones & stimulus source? What is the approx speed of sound in earth?

Most geophones have a natural frequency of 10Hz. At 860sps that allows 86 samples per wave which is sufficient to show the shape and size. What criterion will you use to compare the four waves?