SapFlow Probe
A low-cost HRM probe for measuring a tree's water consumption
measure.cpp
Go to the documentation of this file.
1 #include "measure.h"
2 #include "lora.h"
3 
5 
6 float maxtemp; //< Used to store the max heater temperature
7 
8 int sample_timer(struct pt *pt)
9 {
10  PT_BEGIN(pt);
11  Serial.println("Initialized timer thread");
12  while(1)
13  {
14  sample_trigger = true;
15  PT_YIELD(pt); //< Give everyone a chance to see the trigger
16  sample_trigger = false; //< Clear the trigger
17  PT_TIMER_DELAY(pt,1000); //< Sample every 1000ms
18  }
19  PT_END(pt);
20 }
21 
22 int measure(struct pt *pt)
23 {
24  PT_BEGIN(pt);
25  Serial.print("Initializing measurement thread... ");
26  static Adafruit_MAX31865 upper_rtd = Adafruit_MAX31865(UPPER_CS);
27  static Adafruit_MAX31865 lower_rtd = Adafruit_MAX31865(LOWER_CS);
28  static Adafruit_MAX31865 heater_rtd = Adafruit_MAX31865(HEATER_CS);
29  upper_rtd.begin(MAX31865_2WIRE);
30  lower_rtd.begin(MAX31865_2WIRE);
31  heater_rtd.begin(MAX31865_2WIRE);
32  Serial.println("Done");
33  PT_YIELD(pt);
34  while(1)
35  {
36  // Wait for next sample trigger
37  PT_WAIT_UNTIL(pt, sample_trigger );
38  PT_WAIT_WHILE(pt, sample_trigger);
39  // Get the latest temperature
40  MARK();
41  latest.upper = upper_rtd.temperature(Rnom, Rref); MARK();
42  latest.lower = lower_rtd.temperature(Rnom, Rref); MARK();
43  latest.heater = heater_rtd.temperature(Rnom, Rref); MARK();
44  maxtemp = max(latest.upper, maxtemp); MARK();
45  maxtemp = max(latest.lower, maxtemp); MARK();
46  maxtemp = max(latest.heater, maxtemp); MARK();
47  DateTime t = rtc_ds.now(); MARK();
48  // Print to Serial terminal
49  cout << "Upper: " << latest.upper << " Lower: "; MARK();
50  cout << latest.lower << " Heater: " <<latest.heater; MARK();
51  cout << " Time: " << t.text() << endl; MARK();
52  // Save calculated sapflow
53  ofstream logfile = ofstream("demo_log.csv",
54  ios::out | ios::app ); MARK();
55  logfile << t.text() << ", "; MARK();
56  logfile << setw(6) << latest.upper << ", "; MARK();
57  logfile << setw(6) << latest.lower << ", "; MARK();
58  logfile << setw(6) << latest.heater << endl; MARK();
59  logfile.close(); MARK();//< Ensure the file is closed
60  }
61  PT_END(pt);
62 }
63 
64 // Calculates baseline temperature
65 int baseline(struct pt *pt)
66 {
67  PT_BEGIN(pt);MARK();
68  Serial.print("Initializing baseline thread... ");
69  // Declare persistant variable for this thread
70  static int i;
71  // Initialize the baseline (reference) temperature
72  reference.upper = 0;
73  reference.lower = 0;
74  maxtemp = -300; //< Any temperature should be greater than this.
75  Serial.println("Done");
76  // Take an average over the first 10 seconds
77  for(i = 0; i < 10; ++i){ MARK();
78  PT_WAIT_UNTIL(pt, sample_trigger); MARK();
79  PT_WAIT_WHILE(pt, sample_trigger); MARK();
82  }; MARK();
83  reference.upper /= i;
84  reference.lower /= i; MARK();
85  cout<<"Baseline: "<<reference.upper<<", "<<reference.lower<<endl; MARK();
86  PT_END(pt);
87 }
88 
89 
90 // Calculates temperature delta and sapflow
91 int delta(struct pt *pt)
92 {
93  PT_BEGIN(pt);MARK();
94  Serial.print("Initializing delta thread... ");
95  // Declare persistent variables for this thread
96  static int i;
97  static float flow;
98  // Initialize the flow value
99  flow = 0;
100  Serial.println("Done");
112  for(i = 0; i < 40; ++i ){ MARK();
113  PT_WAIT_UNTIL(pt, sample_trigger); MARK();
114  PT_WAIT_WHILE(pt, sample_trigger); MARK();
115  // Ratio of upper delta over lower delta
116  float udelt = latest.upper - reference.upper;
117  float ldelt = latest.lower - reference.lower;
118  cout << "Delta: " << udelt <<", " << ldelt << endl; MARK();
119  // Take the average before the log, since this ratio should converge
120  flow += udelt / ldelt;
121  }; MARK();
122  cout<<"Finished measurements."<<endl; MARK();
123  flow /= i; MARK();
124  // Complete the rest of the equation
125  flow = log(flow) * (3600.*2e-6/7e-3); MARK();
126  // Print the result
127  cout<<"Flow is "<<flow<<endl; MARK();
128  // Write the sapflow to the file.
129  ofstream sapfile = ofstream("demo.csv", ios::out | ios::app); MARK();
130  char * time = rtc_ds.now().text(); MARK();
131  cout << time << ", "; MARK();
132  cout << reference.upper << ", "; MARK();
133  cout << reference.lower << ", "; MARK();
134  cout << flow << ", " << endl; MARK();
135  sapfile << time << ", "<< reference.upper << ", "; MARK();
136  sapfile << reference.lower << ", "<< flow << ", "<< endl; MARK();
137  sapfile.close(); MARK();
138  // Send the data over LoRa
139  lora_init(); MARK();
140  build_msg(flow, "0", reference.upper, maxtemp); MARK();
141  send_msg(); MARK();
142 
143  PT_END(pt);
144 }
temperature::heater
float heater
Temperature (Celcius) at the heater probe.
Definition: measure.h:23
send_msg
void send_msg(void)
Sends a LoRa packet to the base station.
Definition: lora.cpp:83
rtc_ds
static RTC_DS3231 rtc_ds
Instance of our real-time clock.
Definition: schedule.h:11
sample_timer
int sample_timer(struct pt *pt)
Controls timing of the measurements.
Definition: measure.cpp:8
temperature::upper
float upper
Temperature (Celcius) at the upper probe.
Definition: measure.h:21
sample_trigger
static bool sample_trigger
global flag for synchronizing live data processing. Set by sample_timer()
Definition: measure.h:10
lora_init
void lora_init(void)
Initialize the LoRa radio.
Definition: lora.cpp:17
HEATER_CS
@ HEATER_CS
Heater RTD amplifier chip select. Output.
Definition: pinout.h:27
reference
static struct temperature reference
The baseline temperature reading, computed by the baseline() protothread.
Definition: measure.h:27
measure
int measure(struct pt *pt)
Captures a measurement from the three probes.
Definition: measure.cpp:22
temperature::lower
float lower
Temperature (Celcius) at the lower probe.
Definition: measure.h:22
cout
static ArduinoOutStream cout(Serial)
Allows use of streams to print to Serial via cout.
baseline
int baseline(struct pt *pt)
Calculates baseline temperature.
Definition: measure.cpp:65
Rref
#define Rref
Nominal reference resistor in ohms.
Definition: measure.h:13
MARK
#define MARK()
This macro records the line number and function name.
Definition: debug.h:72
UPPER_CS
@ UPPER_CS
Upper RTD amplifier chip select. Output.
Definition: pinout.h:25
Rnom
#define Rnom
Nominal RTD resistance in ohms.
Definition: measure.h:12
latest
static struct temperature latest
The most recent temperature reading, measured by the measure() protothread.
Definition: measure.h:26
delta
int delta(struct pt *pt)
Calculates temperature delta and sapflow.
Definition: measure.cpp:91
LOWER_CS
@ LOWER_CS
Lower RTD amplifier chip select. Output.
Definition: pinout.h:26
lora.h
build_msg
void build_msg(float flow, char *weight, float temp, float maxtemp)
Builds a JSON string to send over LoRa.
Definition: lora.cpp:58
measure.h