-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathiotree_v.0.9.3.ino
252 lines (225 loc) · 7.33 KB
/
iotree_v.0.9.3.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
/* Dendrometro de precisão para mensurar tamanho inicial e
* variações de crescimento do diâmetro das árvores
* (DAP - diametro a altura do peito com casca).
*
* Code by 3ecologias.net <[email protected]>
*
* notes:
* 1 lap lapV =~ 0.5 volts (v) vcc 5v
* 1 lap lapC =~ 7.9 cm
* perimetro extra cE =~ 4 cm
* perimetro total cT =~ 64 cm
* diametro inicial dI =~ 1.2732 cm
* diametro final dT =~ 20.3718 cm
* led vermelho: pre-calibragem
* led verde: modo de cálculo do diâmetro (DAP) e do crescimento (ICAd) em cm.
*
* steps:
* 1. ajuste o carretel do sensor e acople o dispositivo na árvore com o dispositivo desligado;
* 2. ligue o dispositivo para habilitar o modo de calibragem, medição inicial do diâmetro, crescimento e catalogo de dados;
* 3. o modo de calibragem do sensor verifica se o carretel realizou no mímino uma volta completa;
* 4. o modo de medição do DAP e ICAd captura por 20 segundos o valor inicial do diâmetro;
* 5. o modo de crescimento coleta, a cada minuto, o valor do diâmetro (DAP) e compara com o último valor do DAP para registrar o incremento do diâmetro (ICAd);
* 6. o modo de catalogo armazena, a cada minuto, um log em CSV no SDCard com os valores de hora, data e o DAP: inicial, final e o ICAd.
* 7. Para salvar o log, basta voltar o carretel para a posição inicial e aguardar o led vermelho acender. Depois disso, desligue o dispositivo e remova o SDCard.
*/
// =*= RTC CLOCK DS1307 AND SDCARD CONFIG =*=
#include <Wire.h>
#include <TimeLib.h>
#include <DS1307RTC.h>
#include <SdFat.h>
// SPI pinout
#define PIN_SPI_CLK 13
#define PIN_SPI_MOSI 11
#define PIN_SPI_MISO 12
#define PIN_SD_CS 4
#define PIN_OTHER_DEVICE_CS -1
#define SD_CARD_SPEED SPI_FULL_SPEED
#define FILENAME "datalogger.csv"
SdFat sd;
SdFile csv;
// =*= END SDCARD CONFIG =*=
// scope of constant
const int sensorPin = A0; // pin that the dendro string pot sensor is attached to
const int ledPre = 6;
const int ledCap = 5;
const float Pi = 3.14159265359;
// scope of variables
// modules
bool record = true;
bool calibrate = true;
bool measurement = false;
bool growth = false;
bool catalog = false;
bool calibrateState = true;
bool meansurementState = false;
// global variables
float sensorValue = 0;
float lapC = 780; // perimetro (cm) x 100
float lapV = 49; // volts (V) x 100
float cE = 200; // perimetro (cm) x 100
float baseline = 49; // perimetro externo inicial
int laps = 0;
float cI = 0; // perimetro inicial (cm)
float cL = 0; // perimetro final (cm)
float dI = 0; // diametro inicial (cm)
float dL = 0; // diametro final (cm)
float dapI = 0; // diametro inicial a altura do peito (cm)
float dapL = 0; // diametro final a altura do peito (cm)
float ICAd = 0.0000; // incremento de diametro (cm)
float voltage = 0;
String dataLogger ="";
tmElements_t tm;
void setup() {
// Setup SdCard Pins
pinMode(PIN_SPI_MOSI, OUTPUT);
pinMode(PIN_SPI_MISO, INPUT);
pinMode(PIN_SPI_CLK, OUTPUT);
//Disable SPI devices
pinMode(PIN_SD_CS, OUTPUT);
digitalWrite(PIN_SD_CS, HIGH);
#if PIN_OTHER_DEVICE_CS > 0
pinMode(PIN_OTHER_DEVICE_CS, OUTPUT);
digitalWrite(PIN_OTHER_DEVICE_CS, HIGH);
#endif //PIN_OTHER_DEVICE_CS > 0
Serial.begin(9600);
// turn on LED to signal the start of the calibration and capture period:
pinMode(ledPre, OUTPUT);
pinMode(ledCap, OUTPUT);
// Setup SD card boot
if (!sd.begin(PIN_SD_CS, SD_CARD_SPEED)) {
Serial.println("SD card begin error");
return;
}
}
// sdcard create csv file
void initSdFile()
{
if (sd.exists(FILENAME) && !sd.remove(FILENAME))
{
Serial.println("Failed init remove file");
return;
}
if (!csv.open(FILENAME, O_RDWR | O_CREAT)) {
Serial.println("Failed open file");
} else {
Serial.println("Sdcard saving!");
}
}
void loop() {
Serial.println("===== IOTr3es =====");
Serial.println("===== BUILDING MODULES =====");
sensorValue = analogRead(sensorPin);
voltage = (sensorValue * (5.0 / 1023.0)) * 100;
// calibration mode
while (calibrate == true) {
Serial.println("===== CALIBRATE MODE =====");
sensorValue = analogRead(sensorPin);
voltage = (sensorValue * (5.0 / 1023.0)) * 100;
digitalWrite(ledPre, HIGH);
// check pot minimum sensor value
if (voltage >= baseline) {
for (int i = 0; i < 10; i++) {
voltage = (sensorValue * (5.0 / 1023.0)) * 100;
cI = getcI(lapC, lapV, voltage);
cI = cI + cE;
dI = cI / Pi;
Serial.println("===== CALIBRATE SENSOR =====");
delay(100);
}
digitalWrite(ledPre, LOW);
calibrate = false;
measurement = true;
}
Serial.println("===== CALIBRATE WAITING =====");
Serial.println("voltage" );
Serial.println(rawData(voltage));
delay(1000);
}
// meansurement mode
while (measurement == true) {
Serial.println("===== MEANSUREMENT MODE =====");
digitalWrite(ledCap, HIGH);
sensorValue = analogRead(sensorPin);
voltage = (sensorValue * (5.0 / 1023.0)) * 100;
// check pot minimum sensor value
if (voltage >= baseline) {
for (int i = 0; i < 20; i++) {
sensorValue = analogRead(sensorPin);
voltage = (sensorValue * (5.0 / 1023.0)) * 100;
cI = getcI(lapC, lapV, voltage);
cI = cI + cE;
dapI = cI / Pi;
delay(100);
}
measurement = false;
growth = true;
} else {
measurement = false;
calibrate = true;
}
}
// growth mode
while (growth == true) {
digitalWrite(ledCap, HIGH);
for (int i = 0; i >= 60; i++) {
digitalWrite(ledCap, LOW);
delay(100);
sensorValue = analogRead(sensorPin);
voltage = (sensorValue * (5.0 / 1023.0)) * 100;
digitalWrite(ledCap, HIGH);
Serial.println("===== GROWTH TIME =====");
}
if (record == true) {
Serial.println("===== INIT SDCARD MODULE =====");
initSdFile();
csv.println("HOUR, MINUTE, SECOND, DAY, MONTH, YEAR, DAP-I, DAP-L, ICAD");
record = false;
}
// get dap last
sensorValue = analogRead(sensorPin);
voltage = (sensorValue * (5.0 / 1023.0)) * 100;
// get last DAP value in cm
cI = getcI(lapC, lapV, voltage);
cL = cI + cE;
dapL = cL / Pi;
if (dapL > dapI) {
ICAd = dapL - dapI;
if (RTC.read(tm)) {
dataLogger = String(tm.Hour) + "," + String(tm.Minute) + "," + String(tm.Second) + "," + String(tm.Day) + "," + String(tm.Month) + "," + String(tmYearToCalendar(tm.Year)) + "," + String(rawData(dapI)) + "," + String(rawData(dapL)) + "," + String(rawData(ICAd));
csv.println(dataLogger);
Serial.println("Datalogger ok");
}
} else {
ICAd = dapI - dapL;
if (RTC.read(tm)) {
dataLogger = String(tm.Hour) + "," + String(tm.Minute) + "," + String(tm.Second) + "," + String(tm.Day) + "," + String(tm.Month) + "," + String(tmYearToCalendar(tm.Year)) + "," + String(rawData(dapI)) + "," + String(rawData(dapL)) + "," + String(rawData(ICAd));
csv.println(dataLogger);
Serial.println("Datalogger ok");
}
}
delay(10000);
if (voltage <= baseline) {
digitalWrite(ledCap, LOW);
csv.close();
Serial.println("SDCard saved!" );
record = true;
growth = false;
calibrate = true;
}
}
}
// Function to get length
float getcI(float lapC, float lapV, float voltage){
float _cIraw;
float cIraw;
_cIraw = lapC * voltage;
cIraw = _cIraw / lapV;
return cIraw;
}
// Function to convert data to cm
float rawData(float value){
float rawD;
rawD = value / 100;
return rawD;
}