1+ /*
2+ *---------------------------------------------------------------------------------
3+ *
4+ * Copyright (c) 2025, SparkFun Electronics Inc.
5+ *
6+ * SPDX-License-Identifier: MIT
7+ *
8+ *---------------------------------------------------------------------------------
9+ */
10+
11+ // This example demonstrates how to read the soil moisture sensor and control the on-board LED.
12+ // The LED flash rate is based on how "wet" the soil is. The drier the soil, the faster the LED flashes.
13+
14+ #include " SparkFun_Soil_Moisture_Sensor.h" // CTRL+Click here to get the library: http://librarymanager/All#SparkFun_Soil_Moisture_Sensor
15+ #include < Wire.h>
16+
17+ SparkFunSoilMoistureSensor mySoilSensor; // Create an instance of the sensor class
18+
19+ // The plan:
20+ // The value of the sensor has the following range:
21+ // 0 = 100% wet soil (no resistance)
22+ // 1024 = 0% wet soil (infinite resistance) note: the sensors ADC is 10-bit 2^10 = 1024
23+ //
24+ // The LED will flash faster the drier the soil is. The LED will be effectively off when the soil is 100% wet.
25+ //
26+ // The flash rate is:
27+ // 0% Wet = 1 flash every <fast_value> seconds
28+ // / 10%-90% Wet = rate proportional to the percentage of wetness
29+ // 100% Wet = off
30+ //
31+ // To do this, the following is done:
32+ // 1. Read the sensor value
33+ // 2. Calculate the percentage of wetness and multiply by 10 using integer math (floor)- this gives a value of 0 to 10
34+ // 3. The LED flash_rate = value * increment_value, if value is 0, rate = <fast_value> seconds a value of 1 second for 0% wetness and
35+ // "off" for > 90% wetness
36+
37+
38+
39+ // Define our max dry value - note using a float here
40+ #define MAX_DRY_VALUE 1024.0
41+
42+ // Min flash rate in ms (2 seconds)
43+ #define FAST_FLASH_RATE 2000
44+
45+ // Max flash rate in ms (1 day) - basically off
46+ #define MAX_FLASH_RATE 86400000
47+
48+ // Define our increment value = 10000ms (10 seconds)
49+ #define FLASH_INCREMENT 10000
50+
51+ // Time between loop iterations - 5 second (should not be greater that FAST_FLASH_RATE)
52+ #define LOOP_DELAY FAST_FLASH_RATE
53+
54+ // Define a variable for the last blink time - in ms since boot
55+ uint32_t lastBlinkTime = 0 ;
56+
57+ // Define a variable for the blink rate - delay between blinks in ms
58+ uint32_t blinkRate = 0 ;
59+
60+ // Some Dev boards have their QWIIC connector on Wire or Wire1
61+ // This #ifdef will help this sketch work across more products
62+
63+ #ifdef ARDUINO_SPARKFUN_THINGPLUS_RP2040
64+ #define wirePort Wire1
65+ #else
66+ #define wirePort Wire
67+ #endif
68+
69+ // ----------------------------------------------------------------------------------------
70+ void setup ()
71+ {
72+
73+ // Set up the serial port for output
74+ Serial.begin (115200 );
75+
76+ while (!Serial)
77+ delay (10 ); // Wait for Serial to become available.
78+ // Necessary for boards with native USB (like the SAMD51 Thing+).
79+ // For a final version of a project that does not need serial debug (or a USB cable plugged in),
80+ // Comment out this while loop, or it will prevent the remaining code from running.
81+
82+ // print out the startup banner
83+ Serial.println ();
84+ Serial.println (" ------------------------------------------------------------" );
85+ Serial.println (" SparkFun Soil Sensor Example 3" );
86+ Serial.println (" Blink sensor LED based on soil moisture percentage" );
87+ Serial.println (" ------------------------------------------------------------" );
88+ Serial.println ();
89+
90+ // start the I2C bus
91+ wirePort.begin ();
92+
93+ // Check if the sensor is connected and initialize it
94+ if (mySoilSensor.begin () == false )
95+ {
96+ Serial.println (" Soil Moisture Sensor not detected at default I2C address. Verify the sensor is connected. Stopping." );
97+
98+ while (1 )
99+ ;
100+ }
101+
102+ Serial.println (" Soil Moisture Sensor found!" );
103+
104+ // print out the LED flash rate information
105+ Serial.println ();
106+ Serial.println (" LED will flash based on the soil moisture reading:" );
107+ Serial.print (" < 10% Wet = 1 flash every " );
108+ Serial.print (FAST_FLASH_RATE/1000 );
109+ Serial.println (" seconds" );
110+ Serial.print (" 10%-90% Wet = flash rate proportional to the percentage of wetness: " );
111+ Serial.print (FLASH_INCREMENT/1000 );
112+ Serial.println (" seconds per 10% range" );
113+ Serial.println (" > 90% Wet = LED off" );
114+ Serial.println ();
115+
116+ mySoilSensor.LEDOff ();
117+
118+ // setup the initial blink rate bin - off
119+ blinkRate= MAX_FLASH_RATE;
120+
121+ // initial last blink time - now!
122+ lastBlinkTime = millis ();
123+
124+ Serial.println (" Reading soil moisture sensor..." );
125+ Serial.println ();
126+
127+
128+ }
129+
130+ // ----------------------------------------------------------------------------------------
131+ void loop ()
132+ {
133+ // Let's get the soil moisture reading
134+ uint16_t soilMoisture = mySoilSensor.readMoistureValue ();
135+
136+ // Wet ration 0 - 1.0
137+ float wetRatio = ((MAX_DRY_VALUE - (float )soilMoisture) / MAX_DRY_VALUE);
138+
139+ // Output the value:
140+ Serial.print (" Soil Moisture: " );
141+ Serial.print (soilMoisture);
142+ Serial.print (" (sensor value), " );
143+ Serial.print (wetRatio * 100 );
144+ Serial.println (" % wet" );
145+
146+ // Update the blink rate based on the soil moisture reading
147+ updateBlinkRate (wetRatio);
148+
149+ // check if we need to flash the LED
150+ checkForLEDBlink ();
151+
152+ // delay our reading.
153+ delay (LOOP_DELAY);
154+ }
155+
156+ // ----------------------------------------------------------------------------------------
157+ // A function to update the blink rate based on the soil moisture ration (0 - 1.0)
158+ void updateBlinkRate (float wetRatio)
159+ {
160+
161+ // Calculate the delay rate "bin" (wet ratio * 10) for the LED based on this current reading
162+ // The rate bin is a value from 0 to 10
163+ uint32_t blinkRateBin = wetRatio * 10 ;
164+
165+ // What is the blink rate in ms?
166+ if (blinkRateBin == 0 )
167+ {
168+ // 0% wet - Flash at the fast rate
169+ blinkRate = FAST_FLASH_RATE;
170+ }
171+ else if (blinkRateBin > 8 )
172+ {
173+ // 90% - 100% wet - LED off
174+ blinkRate = MAX_FLASH_RATE; // 1 day - basically off
175+ }else {
176+ // 10%-90% wet - rate proportional to the percentage of wetness
177+ blinkRate = blinkRateBin * FLASH_INCREMENT;
178+ }
179+
180+ }
181+
182+ // ----------------------------------------------------------------------------------------
183+ // A function to check if we need to flash the LED based on elapsed time from last blink
184+ void checkForLEDBlink (void )
185+ {
186+ // do we need to flash the LED?
187+ if (millis () - lastBlinkTime > blinkRate)
188+ {
189+ // Wink the LED during the reading
190+ mySoilSensor.LEDOn ();
191+ delay (100 );
192+ mySoilSensor.LEDOff ();
193+
194+ lastBlinkTime = millis ();
195+ }
196+ }
0 commit comments