diff --git a/hardware/arduino/water_level/water_level.ino b/hardware/arduino/water_level/water_level.ino index 41fb913..a391630 100644 --- a/hardware/arduino/water_level/water_level.ino +++ b/hardware/arduino/water_level/water_level.ino @@ -1,5 +1,6 @@ // need 0.1uf cap between vcc and ground for proper operation // need 10k pull up resistor on scl and sda for i2c to work correctly +// need VCC hooked up to VREF pin 5 // Pin Mappings (Per TinyCore) // ATTiny Pin -- Arduino Pin @@ -18,21 +19,86 @@ #define I2C_ADDRESS 0x5F +// eTape sensor info / values for calculations +// 5-inch: 400-1000 ±20% +// Ref Resistance 1000 ±20% +// Active Length 4.9" (213 mm) +// 8-inch: 400-1500 ±20% +// Ref Resistance 1500 ±20% +// Active Length 8.4" (213mm) +// 12-inch: 400-2000 ±20% +// Ref Resistance 2000 ±20% +// Active Length 12.4" (315mm) +// 24-inch: 400-4000 ±20% +// Ref Resistance 4000 ±20% +// Active Length 24.34" (618mm) +// 32-inch: 400-5000 ±20% +// Ref Resistance 5000 ±20% +// Active Length 32.4" (823mm) + +#define SENSOR_PIN A3 // Pin 2 on physical package +#define SENSOR_REF_RESISTANCE 1000.0 +#define SENSOR_VALUE_MIN 400.0 +#define SENSOR_VALUE_MAX 1000.0 +#define SENSOR_ACTIVE_LENGTH 4.9 +#define Vin 3.3 + +// Average/Smoothing +#define NUM_SAMPLES 15 +int samples[NUM_SAMPLES]; + #include -void setup() { - pinMode(6, INPUT); - - Wire.begin(I2C_ADDRESS); - Wire.onRequest(requestEvent); -} - -void loop() { - delay(100); +// Map a value from one range of values to another -- support decimals +float longmap(float x, float in_min, float in_max, float out_min, float out_max) { + return out_min + ((1.0 * (x - in_min) * (out_max - out_min)) / (1.0 * (in_max - in_min))); } // function that executes whenever data is requested by master // this function is registered as an event, see setup() void requestEvent() { - Wire.write((uint8_t) analogRead(6)); // Only get 0 - 1023 back so move this into a 1 byte int + // Sensor readings averaged out + float average = 0; + for (uint8_t i = 0; i < NUM_SAMPLES; i++) { + samples[i] = analogRead(SENSOR_PIN); + delay(10); + } + for (uint8_t i = 0; i < NUM_SAMPLES; i++) { + average += samples[i]; + } + average /= NUM_SAMPLES; + + // convert the value to resistance + float buffer = average * Vin; + float Vout = (buffer) / 1024.0; + buffer = (Vin / Vout) - 1; + float R2 = SENSOR_REF_RESISTANCE * buffer; + + // Map resistance to water level + float height = longmap(R2, SENSOR_VALUE_MAX, SENSOR_VALUE_MIN, 0, SENSOR_ACTIVE_LENGTH); + + // Write the value + char data[4]; + dtostrf(height, 1, 2, data); + Wire.write(data); +} + +void setup(void) { + analogReference(DEFAULT); // DEFAULT == Vcc + pinMode(SENSOR_PIN, INPUT); + + // From arduino docs (https://www.arduino.cc/reference/en/language/functions/analog-io/analogreference/) + // After changing the analog reference, the first few readings from analogRead() may not be accurate. + // Fix this situation during setup prior to sending any values out (this chip may be on/off frequently so this is a real concern over time and needs to happen ahead of i2c sensor reads) + delay(100); + for (int i = 0; i < 6; i++) { + analogRead(SENSOR_PIN); + } + + Wire.begin(I2C_ADDRESS); + Wire.onRequest(requestEvent); +} + +void loop(void) { + delay(100); }