Skip to content

Commit 7c8fbc3

Browse files
authored
Merge pull request #9 from xspanger3770/develop
Develop - 4.7.0
2 parents d87fa4e + d6e229b commit 7c8fbc3

File tree

15 files changed

+815
-71
lines changed

15 files changed

+815
-71
lines changed

README.md

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
# ZejfSeis
22

3-
ZejfSeis is a Java application designed to display data measured by a homemade seismometer. It communicates with [ZejfCSeis](https://github.com/xspanger3770/ZejfCSeis) through a TCP connection and provides real-time data display, browsing of stored data and also displaying nearby earthquakes that might have been detected.
3+
ZejfSeis is a user-friendly and easy to use Java application that allows for the display and analysis of seismic data captured by a homemade seismometer. With its intuitive interface, users can easily access a range of useful features, including real-time seismic plot display, spectrogram visualization, and browsing of recorded data in a drum-like style. In addition to these functionalities, the application offers a convenient and efficient way to store recorded earthquakes in a local database for later review and analysis. Whether you're a professional seismologist or simply an enthusiast, ZejfSeis is a powerful tool that can help you gain a deeper understanding of the Earth's seismic activity!
44

5-
## Socket connection
5+
## Getting started
66

7-
To connect to a running [ZejfCSeis](https://github.com/xspanger3770/ZejfCSeis) server, go to `Settings->Socket` and enter the IP address and port number of the server.
7+
To begin your seismology journey, it's recommended that you first review my tutorial on setting up the seismometer itself, which can be found at the following link: [Seismometer tutorial](https://github.com/xspanger3770/ZejfSeis/tree/develop/arduino). This guide provides clear and concise instructions for assembling and calibrating the seismometer, ensuring that it's ready to capture accurate seismic data.
8+
9+
## Data source
10+
11+
There are two ways of connecting ZejfSeis application to a running seismometer. The easiest way is to plug your Arduino directly to your computer's USB port and use `Connection->Serial Port` option in the upper menu, which will establish a direct connection and allow you to view incoming data with ease.
12+
13+
Alternatively, you can opt for the slightly more involved approach of setting up a [ZejfCSeis](https://github.com/xspanger3770/ZejfCSeis) server on a separate device. While this requires a bit more setup time, it provides the benefit of running the project continuously and enabling you to connect to the running server from anywhere by simply entering its address under `Connection->Server`.
814

915
## Realtime tab
1016
The Realtime tab contains two main features. On the top is an interactive plot of the incoming data, which scales automatically based on the highest amplitude in the given time frame. The default setting for the time frame duration is 5 minutes and can be changed in `Settings->Realtime`.
@@ -13,15 +19,15 @@ The Realtime tab contains two main features. On the top is an interactive plot o
1319

1420
The bottom section of the Realtime tab is a Spectrogram panel, which allows you to analyze the waveform in more detail and helps you distinguish between noise and real earthquakes. You can adjust the colors by setting the Spectrogram gain field in `Settings->Realtime` so that background noise is displayed as a dark blue color.
1521

16-
![](https://user-images.githubusercontent.com/100421968/230724558-52bbcdf1-1ace-4fac-b23d-15c901bb1f0a.png)
22+
![](https://user-images.githubusercontent.com/100421968/232130962-271493b3-8b2e-41bc-902b-3cf56cbbf69a.png)
1723

1824
## Drum tab
1925

2026
The Drum tab allows you to browse the recorded data. Each line represents a time interval, with its start labeled on the left side (red numbers indicating hours and gray ones minutes). By default, each line represents 10 minutes of data. For navigation, you can scroll with your mouse, or you can use the buttons on the upper control panel. The `<` button will move the drum by one line, and `<<` will move it by 10 lines. By pressing the `Now` button, you will move the drum to the latest data. To access older data, you can use the `Goto` button and enter a specific date and time.
2127

22-
The drum can be configured by accessing `Settings->Drum Settings`. By changing the value of `Gain`, you can adjust the scale of the waveform, and you can increase the `Decimate` field to lower the waveform resolution for better performance.
28+
The drum can be configured by accessing `Settings->Drum`. By changing the value of `Gain`, you can adjust the scale of the waveform, and you can increase the `Decimate` field to lower the waveform resolution for better performance.
2329

24-
![](https://user-images.githubusercontent.com/100421968/230572243-ad604679-4adf-420e-9f8f-30c36f75cf50.png)
30+
![](https://user-images.githubusercontent.com/100421968/232131108-2ccce048-c082-4465-bd44-5f26395e212f.png)
2531

2632
### Data explorer
2733

@@ -51,4 +57,4 @@ The status can be one of the following: `Unknown`, `Not Detected`, `Broken`, `No
5157

5258
## Filters
5359

54-
All the data displayed in the application are filtered using a band-pass filter, meaning that frequencies outside the range specified at `Settings->Filter` will get attenuated. Additionally, there is a quick filter selector at the top of the main window. These filters makes it easier seeing earthquakes at different distances by filtering some noise out from the signal.
60+
All the data displayed in the application are filtered using a band-pass filter, which makes frequencies outside the range will get attenuated. You can configure the filter using the `Filters` menu. You can either select one of the prepared filters or create custom one in `Filters->Custom`. These filters makes it easier seeing earthquakes at different distances by filtering some noise out from the signal.
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
#include <ADS1256.h>
2+
#include <SPI.h>
3+
#include <filters.h>
4+
#include <limits.h>
5+
6+
// FILTER
7+
8+
const float cutoff_freq = 20.0;
9+
const float sampling_time = 1 / 400.0;
10+
IIR::ORDER order = IIR::ORDER::OD4;
11+
12+
Filter filter(cutoff_freq, sampling_time, order);
13+
14+
// ADC
15+
16+
#define PIN_DRDY 9
17+
18+
float clockMHZ = 7.68; // crystal frequency used on ADS1256
19+
float vRef = 2.5; // voltage reference
20+
21+
// Construct and init ADS1256 object
22+
ADS1256 adc(clockMHZ, vRef, false); // RESETPIN is permanently tied to 3.3v
23+
24+
// SAMPLING
25+
26+
const int SAMPLE_RATES[5] = { 20, 40, 60, 100, 200 };
27+
28+
int sample_rate;
29+
long sample_time_micros;
30+
31+
// RUNTIME
32+
33+
unsigned long last_time;
34+
unsigned long current_time;
35+
36+
double reading;
37+
long double sum;
38+
int count;
39+
long value;
40+
41+
byte log_num;
42+
int shift;
43+
44+
char ch;
45+
46+
void get_sample_rate()
47+
{
48+
int index = 1;
49+
Serial.println("Please select sample rate");
50+
while (true) {
51+
char ch = Serial.read();
52+
index = ch - '0';
53+
if (index >= 0 && index < 5) {
54+
break;
55+
}
56+
}
57+
58+
shift = 0;
59+
sample_rate = SAMPLE_RATES[index];
60+
sample_time_micros = 1000000 / sample_rate;
61+
62+
Serial.print("Selected ");
63+
Serial.print(sample_rate);
64+
Serial.println(" sps");
65+
66+
last_time = 0;
67+
sum = 0;
68+
count = 0;
69+
log_num = 0;
70+
shift = 0;
71+
}
72+
73+
void setup()
74+
{
75+
Serial.begin(115200);
76+
77+
get_sample_rate();
78+
79+
adc.begin(ADS1256_DRATE_500SPS, ADS1256_GAIN_64, false);
80+
}
81+
82+
void loop()
83+
{
84+
if (!(digitalRead(PIN_DRDY))) {
85+
reading = filter.filterIn((adc.readCurrentChannel() / (2.0 * vRef)) * 0x7FFFFF);
86+
sum += reading;
87+
count++;
88+
}
89+
90+
current_time = micros();
91+
92+
if (abs(current_time - last_time) >= sample_time_micros + shift) {
93+
value = round(sum / count);
94+
sum = 0;
95+
count = 0;
96+
97+
Serial.print('s');
98+
Serial.print(shift);
99+
Serial.print('l');
100+
Serial.print(log_num);
101+
Serial.print('v');
102+
Serial.println(value);
103+
104+
last_time = current_time;
105+
log_num++;
106+
}
107+
108+
if (Serial.available()) {
109+
ch = Serial.read();
110+
if (ch == '-' && shift != INT_MIN) {
111+
shift--;
112+
} else if (ch == '+' && shift != INT_MAX) {
113+
shift++;
114+
} else if (ch == 'r') {
115+
get_sample_rate();
116+
}
117+
}
118+
}
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
#include <ADS126X.h>
2+
#include <SPI.h>
3+
#include <filters.h>
4+
#include <limits.h>
5+
6+
// FILTER
7+
8+
float cutoff_freq = 20.0;
9+
const float sampling_time = 1 / 1200.0;
10+
IIR::ORDER order = IIR::ORDER::OD4;
11+
12+
Filter filter(cutoff_freq, sampling_time, order);
13+
14+
// ADC
15+
16+
#define PIN_DRDY 9
17+
#define PIN_CS 10
18+
19+
#define POS_PIN ADS126X_AIN1
20+
#define NEG_PIN ADS126X_AIN0
21+
#define ADS_SAMPLE_RATE ADS126X_RATE_1200
22+
23+
ADS126X adc;
24+
25+
// SAMPLING
26+
27+
const int SAMPLE_RATES[5] = { 20, 40, 60, 100, 200 };
28+
29+
int sample_rate;
30+
long sample_time_micros;
31+
32+
// RUNTIME
33+
34+
#define CALIBRATION_SECONDS 20
35+
#define IGNORE 20
36+
37+
bool calibrating;
38+
long offset;
39+
40+
unsigned long last_time;
41+
unsigned long current_time;
42+
43+
long double sum;
44+
unsigned int count;
45+
long value;
46+
47+
byte log_num;
48+
int shift;
49+
50+
char ch;
51+
52+
void get_sample_rate()
53+
{
54+
int index = 1;
55+
Serial.println("Please select sample rate");
56+
while (true) {
57+
char ch = Serial.read();
58+
index = ch - '0';
59+
if (index >= 0 && index < 5) {
60+
break;
61+
}
62+
}
63+
64+
shift = 0;
65+
sample_rate = SAMPLE_RATES[index];
66+
sample_time_micros = 1000000 / sample_rate;
67+
68+
cutoff_freq = sample_rate / 2.0;
69+
filter.setCutoffFreqHZ(cutoff_freq);
70+
71+
Serial.print("Selected ");
72+
Serial.print(sample_rate);
73+
Serial.println(" sps");
74+
75+
last_time = 0;
76+
sum = 0;
77+
count = 0;
78+
log_num = 0;
79+
shift = 0;
80+
calibrating = true;
81+
offset = 0;
82+
Serial.println("Offset calibration start, be patient...");
83+
}
84+
85+
void setup()
86+
{
87+
Serial.begin(115200);
88+
89+
get_sample_rate();
90+
91+
adc.begin(PIN_CS);
92+
delay(10);
93+
adc.setRate(ADS_SAMPLE_RATE);
94+
delay(10);
95+
adc.startADC1();
96+
delay(10);
97+
adc.setGain(ADS126X_GAIN_32);
98+
delay(10);
99+
adc.setFilter(ADS126X_SINC4);
100+
delay(10);
101+
adc.setBiasMagnitude(ADS126X_BIAS_MAG_0);
102+
delay(10);
103+
adc.setReference(ADS126X_REF_NEG_VSS, ADS126X_REF_POS_VDD);
104+
}
105+
106+
void loop()
107+
{
108+
bool rdy = !(digitalRead(PIN_DRDY));
109+
if (rdy) {
110+
if (calibrating && count >= IGNORE) {
111+
sum += adc.readADC1(POS_PIN, NEG_PIN);
112+
count++;
113+
} else {
114+
sum += filter.filterIn(adc.readADC1(POS_PIN, NEG_PIN)) - offset;
115+
count++;
116+
}
117+
}
118+
119+
current_time = micros();
120+
121+
if (calibrating) {
122+
if (count % (1200 * 5) == 0 && rdy) {
123+
Serial.println("wait...");
124+
}
125+
if (count >= CALIBRATION_SECONDS * 1200) {
126+
calibrating = false;
127+
offset = round(sum / count);
128+
sum = 0;
129+
count = 0;
130+
Serial.print("Offset calibration finish, offset = ");
131+
Serial.println(offset);
132+
}
133+
} else if (abs(current_time - last_time) >= sample_time_micros + shift) {
134+
value = round(sum / count);
135+
sum = 0;
136+
count = 0;
137+
138+
Serial.print('s');
139+
Serial.print(shift);
140+
Serial.print('l');
141+
Serial.print(log_num);
142+
Serial.print('v');
143+
Serial.println(value);
144+
145+
last_time = current_time;
146+
log_num++;
147+
}
148+
149+
if (Serial.available()) {
150+
ch = Serial.read();
151+
if (ch == '-' && shift != INT_MIN) {
152+
shift--;
153+
} else if (ch == '+' && shift != INT_MAX) {
154+
shift++;
155+
} else if (ch == 'r') {
156+
get_sample_rate();
157+
} else if (ch == 'c') {
158+
adc.calibrateSysOffsetADC1(POS_PIN, NEG_PIN);
159+
} else if (ch == 's') {
160+
adc.calibrateSelfOffsetADC1();
161+
} else if (ch == 'b') {
162+
adc.setGain(ADS126X_GAIN_32);
163+
}
164+
}
165+
}

arduino/README.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# Seismometer
2+
3+
The seimometer itself is Lehman type seismometer.
4+
5+
A Lehman type seismometer is a device used to detect ground motion caused by seismic activity. It uses a horizontal beam pendulum that is suspended from a stationary frame. The pendulum has a magnet attached to it and a copper coil is positioned nearby. When ground motion occurs, the magnet moves past the copper coil, inducing an electrical current which can be detected and recorded by a sensitive amplifier or data acquisition system. The Lehman seismometer is designed to be very sensitive, able to detect ground motion on the order of a few micrometers.
6+
7+
There are a lot of tutorials online of how you can build one. You can also get an inspiration from my setup:
8+
9+
__TODO insert pictures__
10+
11+
## A few important notes
12+
13+
### Damping
14+
15+
Damping is an essential aspect of seismometer design as it reduces unwanted noise and enhances sensitivity. In my design, a plastic plate is submerged in highly viscous fluid - motor oil. This fluid provides resistance to the pendulum's motion, causing it to come to rest gradually and reducing the amplitude of its oscillations. Without this damping mechanism, the pendulum would continue to swing due to inertia, making it difficult to distinguish between seismic waves and noise. Damping ensures the pendulum settles into a stable position and detects even the smallest ground movements, improving the instrument's precision. Other damping techniques, such as magnets or electrical feedback, may also be used to enhance seismometer sensitivity.
16+
17+
### Frame angle
18+
19+
The angle of the frame relative to the vertical determines the natural period of the pendulum in a seismometer. A lower angle results in a longer period, which allows for more precise detection of long-period waves generated by major earthquakes. However, increasing the period too much can cause the pendulum to become difficult to center, leading to it getting stuck on the sides of the coil. Finding the optimal angle, therefore, requires a careful balancing of these factors. In my case, I was only able to get about 12 seconds of resonant period before the design become unstable.
20+
21+
### The magnets
22+
23+
As you can see, I used two strong neodymium magnets on both sides of the copper coil to increase induction and the instrument's overall gain. It is crucial to ensure that the magnets are correctly oriented with the same poles facing each other. This results in a highly concentrated magnetic field inside the coil while reducing the magnetic field on the outside. The high concentration of the magnetic field inside the coil results in increased sensitivity, allowing the seismometer to detect even the smallest ground movements.
24+
25+
__TODO insert pictures__
26+
27+
While the current design of my seismometer has proven to be effective, there is still room for improvement. One area for enhancement is the use of materials, specifically the wooden beams. Wood has some degree of elasticity, which can cause the vertical beam to bend under the weight of the pendulum. To improve stability and sensitivity, better materials such as aluminum could be used instead. Additionally, the metal string that holds the pendulum may be too rigid, resulting in unwanted forces that deviate it from its central position. This can limit the maximum achievable resonance period and reduce the overall accuracy of the instrument. To overcome this issue, a more flexible string or cable could be used, allowing for smoother and more precise pendulum movements. By addressing these design considerations, the performance and accuracy of the seismometer can be further enhanced.
28+
29+
## ADC
30+
In my project, an analog to digital converter (ADC) is used to achieve this conversion. The ADC device is wired up to an Arduino microcontroller, which serves as the brain of the system. The Arduino reads the digital data from the ADC and takes care of time synchronization, ensuring that the recorded data is accurately time-stamped. Once the data is prepared by the Arduino, it is sent to ZejfCSeis. This is done via a USB connection, allowing for real-time data transfer and continuous monitoring of seismic activity.
31+
32+
The use of modern digital technology and open-source software tools has greatly improved the accessibility and affordability of seismometers, enabling a wider range of enthusiasts like me to study earthquakes and other seismic events.
33+
34+
Currently, 2 highly accurate ADC's are supported: 24-bit ADS1256 and 32-bit ADS1263 and support for more can be easily added.
35+
36+
### ADS1256
37+
38+
To use the ADS1256 analog to digital converter, you will first need two Arduino libraries: [ADS1256](https://github.com/adienakhmad/ADS1256) and [libFilter](https://github.com/MartinBloedorn/libFilter). Install them as any other Arduino libraries by pasting the folders into Arduino/libraries folder on your computer. After wiring up the ADS1256, use Arduino IDE to upload sketch `ADS1256_Seismo` located in this directory.
39+
40+
Here is the wiring for Arduino Nano - the two wires on the right connect directly to the seimometer main coil:
41+
42+
<img src=https://user-images.githubusercontent.com/100421968/231836782-62f4d2d0-edd1-488e-90dd-6f7269f3b97f.jpg width=600 height=420>
43+
44+
I was using this ADC for about one year and it worked perfectly fine as I was able to detect many earthquakes every day from around the world. Later I switched to the more accurate ADS1263 to push the sensitivity to the limit.
45+
46+
### ADS1263
47+
48+
Hooking up the ADS1263 is pretty simmilar to the ADS1256. The Arduino library for it can be found here: [ADS126X](https://github.com/Molorius/ADS126X) and after installing it you can upload `ADS1263_Seismo` sketch located in this directory.
49+
50+
__TODO image__

pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@
55
<version>0.0.1-SNAPSHOT</version>
66

77
<dependencies>
8+
<!-- https://mvnrepository.com/artifact/com.fazecast/jSerialComm -->
9+
<dependency>
10+
<groupId>com.fazecast</groupId>
11+
<artifactId>jSerialComm</artifactId>
12+
<version>2.7.0</version>
13+
</dependency>
814
<!-- https://mvnrepository.com/artifact/edu.emory.mathcs/JTransforms -->
915
<dependency>
1016
<groupId>edu.emory.mathcs</groupId>

0 commit comments

Comments
 (0)