#include <PinChangeInterrupt.h>
#include <Tiny4kOLED.h>
#include <TinyWire.h>
#define statusLed 5 // Status LED Pin PB5
#define outPulse 4 // Pulsed Output Pin PB4
#define flowsensor 1 // Flow Sensor Input Pin PB1
#define prssensor 3 // Pressure Sensor Input Pin PB3
// Setup Flowmeter
volatile int flowPulseCount = 0; // Counts flow sensor pulses unsigned
int flowPulseCount_prev = 0; // Previous Counts of flow sensor
float l_sec = 0; // Calculated litres/sec
float l_min = 0; // Calculated litres/min
const float calFactor = 1.00; // flow calibration factor
// Setup Pressure
int prs_bar = 0; // Calculated pressure 2dp
const int low = 204; // Scaling values
const int high = 1023;
unsigned long currentTime;
unsigned long cloopTime;
// Setup I2C
#define I2C_SLAVE_ADDRESS 0x10 // Set i2c address to 10
volatile uint8_t i2c_regs[] = {0, 0};
// Tracks the current register pointer position
volatile byte reg_position;
const byte reg_size = sizeof(i2c_regs);
void setup() {
// join I2C network
TinyWire.begin(I2C_SLAVE_ADDRESS);
TinyWire.onRequest(requestEvent);
//Set IO
pinMode(flowsensor, INPUT);
pinMode(prssensor, INPUT);
pinMode(statusLed, OUTPUT);
// Flash Status Led at program start
flashStatusLed(4);
// Setup Interrupt for Flowmeter pulsing
attachPCINT(flowsensor, flow, RISING);
currentTime = millis();
cloopTime = currentTime;
}
void loop() {
currentTime = millis();
int flowPulseCount_now = flowPulseCount;
int flow_frequency = flowPulseCount_now - flowPulseCount_prev;
// Set Pulsed Output Low to start
digitalWrite(outPulse, LOW);
// Every second, calculate litres/second
if (currentTime >= (cloopTime + 1000))
{
cloopTime = currentTime; // Updates cloopTime
// Get Flow Reading
// Pulse frequency (Hz) = 4.8Q, Q is flow rate in L/min.
l_sec = (flow_frequency * 100 / 4.8) * calFactor; // (Pulse frequency x 100) / 4.8Q x Cal factor = flowrate in L/sec 2dp
// Get Pressure Reading
prs_bar = map(analogRead(prssensor), low, high, 0, 1000); // Scale pressure raw to 0 - 10.00 bar
i2c_regs[0] = l_sec;
i2c_regs[1] = prs_bar;
flowPulseCount_prev = flowPulseCount_now; // Update previous count for next calculation
// Calculate and accumulate volume for l/min
l_min = l_min + l_sec / 60;
}
if (l_min >= 1.00) {
digitalWrite(outPulse, HIGH); // Output pulse every 1 l/min
l_min = l_min - 1.00;
}
}
void flow() // Interrupt function - count pulses from flowmeter
{
flowPulseCount++;
}
void flashStatusLed(int count) {
for (int i = 0; i < count; i++) {
digitalWrite(statusLed, HIGH);
delay(130);
digitalWrite(statusLed, LOW);
delay(130);
}
}
void requestEvent() // Send Data to Raspberry Pi
{
for (int i = 0; i <= reg_size; i++) TinyWire.send(i2c_regs[i]);
}