#include <ArduinoJson.h>
#include "Variables.h"
#include <Arduino.h>
bool group_switch_gauge_measurement = true; // Measure flag
struct group_pin_defs{
uint8_t solenoid_pin;
uint8_t flow_meter_pin;
};
typedef struct{
const int id;
const struct group_pin_defs mix_pin_defs;
const struct group_pin_defs alcohol_pin_defs;
float mix;
float alcohol;
int current_threshold;
int current_threshold_alcohol;
bool alcohol_switch;
bool mix_switch;
bool mix_reset_routine;
bool alcohol_reset_routine;
}group_vars_t;
/****************GROUP 1 VARIABLES**************************/
group_vars_t group1_vars = {
.id = 1,
.mix_pin_defs = {.solenoid_pin = G1_MIX_SOLENOID_PIN, .flow_meter_pin = G1_MIX_FLOW_METER_PIN},
.alcohol_pin_defs = {.solenoid_pin = G1_ALCOHOL_SOLENOID_PIN, .flow_meter_pin = G1_ALCOHOL_FLOW_METER_PIN},
.mix = 0,
.alcohol = 0,
.current_threshold = 50,
.current_threshold_alcohol = 20,
.alcohol_switch = false,
.mix_switch = false,
.mix_reset_routine = true,
.alcohol_reset_routine = true,
};
/****************GROUP 2 VARIABLES**************************/
group_vars_t group2_vars = {
.id = 2,
.mix_pin_defs = {.solenoid_pin = G2_MIX_SOLENOID_PIN, .flow_meter_pin = G2_MIX_FLOW_METER_PIN},
.alcohol_pin_defs = {.solenoid_pin = G2_ALCOHOL_SOLENOID_PIN, .flow_meter_pin = G2_ALCOHOL_FLOW_METER_PIN},
.mix = 0,
.alcohol = 0,
.current_threshold = 50,
.current_threshold_alcohol = 20,
.alcohol_switch = false,
.mix_switch = false,
.mix_reset_routine = true,
.alcohol_reset_routine = true,
};
/****************GROUP 3 VARIABLES**************************/
group_vars_t group3_vars = {
.id = 3,
.mix_pin_defs = {.solenoid_pin = G3_MIX_SOLENOID_PIN, .flow_meter_pin = G3_MIX_FLOW_METER_PIN},
.alcohol_pin_defs = {.solenoid_pin = G3_ALCOHOL_SOLENOID_PIN, .flow_meter_pin = G3_ALCOHOL_FLOW_METER_PIN},
.mix = 0,
.alcohol = 0,
.current_threshold = 50,
.current_threshold_alcohol = 20,
.alcohol_switch = false,
.mix_switch = false,
.mix_reset_routine = true,
.alcohol_reset_routine = true,
};
/****************GROUP 4 VARIABLES**************************/
group_vars_t group4_vars = {
.id = 4,
.mix_pin_defs = {.solenoid_pin = G4_MIX_SOLENOID_PIN, .flow_meter_pin = G4_MIX_FLOW_METER_PIN},
.alcohol_pin_defs = {.solenoid_pin = G4_ALCOHOL_SOLENOID_PIN, .flow_meter_pin = G4_ALCOHOL_FLOW_METER_PIN},
.mix = 0,
.alcohol = 0,
.current_threshold = 50,
.current_threshold_alcohol = 20,
.alcohol_switch = false,
.mix_switch = false,
.mix_reset_routine = true,
.alcohol_reset_routine = true,
};
StaticJsonDocument<1500> doc;
DynamicJsonDocument outgoing_json(1500);
// Initialise inputs
void init_inputs()
{
pinMode(G1_MIX_FLOW_METER_PIN, INPUT);
pinMode(G2_MIX_FLOW_METER_PIN, INPUT);
pinMode(G3_MIX_FLOW_METER_PIN, INPUT);
pinMode(G4_MIX_FLOW_METER_PIN, INPUT);
pinMode(G1_ALCOHOL_FLOW_METER_PIN, INPUT);
pinMode(G2_ALCOHOL_FLOW_METER_PIN, INPUT);
pinMode(G3_ALCOHOL_FLOW_METER_PIN, INPUT);
pinMode(G4_ALCOHOL_FLOW_METER_PIN, INPUT);
attachInterrupt(digitalPinToInterrupt(G1_MIX_FLOW_METER_PIN), flow_meter1_mix_isr, RISING);
attachInterrupt(digitalPinToInterrupt(G2_MIX_FLOW_METER_PIN), flow_meter2_mix_isr, RISING);
attachInterrupt(digitalPinToInterrupt(G3_MIX_FLOW_METER_PIN), flow_meter3_mix_isr, RISING);
attachInterrupt(digitalPinToInterrupt(G4_MIX_FLOW_METER_PIN), flow_meter4_mix_isr, RISING);
attachInterrupt(digitalPinToInterrupt(G1_ALCOHOL_FLOW_METER_PIN), flow_meter1_alcohol_isr, RISING);
attachInterrupt(digitalPinToInterrupt(G2_ALCOHOL_FLOW_METER_PIN), flow_meter2_alcohol_isr, RISING);
attachInterrupt(digitalPinToInterrupt(G3_ALCOHOL_FLOW_METER_PIN), flow_meter3_alcohol_isr, RISING);
attachInterrupt(digitalPinToInterrupt(G4_ALCOHOL_FLOW_METER_PIN), flow_meter4_alcohol_isr, RISING);
}
// Initialise outputs
void init_outputs()
{
pinMode(G1_MIX_SOLENOID_PIN, OUTPUT);
pinMode(G2_MIX_SOLENOID_PIN, OUTPUT);
pinMode(G3_MIX_SOLENOID_PIN, OUTPUT);
pinMode(G4_MIX_SOLENOID_PIN, OUTPUT);
pinMode(G1_ALCOHOL_SOLENOID_PIN, OUTPUT);
pinMode(G2_ALCOHOL_SOLENOID_PIN, OUTPUT);
pinMode(G3_ALCOHOL_SOLENOID_PIN, OUTPUT);
pinMode(G4_ALCOHOL_SOLENOID_PIN, OUTPUT);
digitalWrite(G1_MIX_SOLENOID_PIN, LOW); // turn the LED on (HIGH is the voltage level)
digitalWrite(G2_MIX_SOLENOID_PIN, LOW);
digitalWrite(G3_MIX_SOLENOID_PIN, LOW);
digitalWrite(G4_MIX_SOLENOID_PIN, LOW);
digitalWrite(G1_ALCOHOL_SOLENOID_PIN, LOW); // turn the LED on (HIGH is the voltage level)
digitalWrite(G2_ALCOHOL_SOLENOID_PIN, LOW);
digitalWrite(G3_ALCOHOL_SOLENOID_PIN, LOW);
digitalWrite(G4_ALCOHOL_SOLENOID_PIN, LOW);
}
// Set solenoid to high/low
void switch_solenoid(uint8_t pin, uint8_t state)
{
digitalWrite(pin, state);
}
void check_mix(group_vars_t *group, int max)
{
DynamicJsonDocument outgoing_json_data(200);
if(group->mix >= max){
group->mix_switch = false;
switch_solenoid(group->mix_pin_defs.solenoid_pin, LOW);
if(group->alcohol < group->current_threshold_alcohol){
group->alcohol_switch = true;
switch_solenoid(group->alcohol_pin_defs.solenoid_pin, HIGH);
}
String json_string;
outgoing_json_data["status"] = String("MIX_OUT_" + String(group->id));
serializeJson(outgoing_json_data, json_string);
Serial.println(json_string);
}
else if(group->mix >= group->current_threshold){
group->current_threshold += MIX_THRESHOLD_STEP;
if(!(group->alcohol_switch) && group->alcohol < ALCOHOL_MAX_THRESHOLD){
switch_solenoid(group->alcohol_pin_defs.solenoid_pin, HIGH);
group->alcohol_switch = true;
}
}
}
void check_alcohol(group_vars_t *group, int max)
{
DynamicJsonDocument outgoing_json_data(200);
if(group->alcohol >= max){
group->alcohol_switch = false;
switch_solenoid(group->alcohol_pin_defs.solenoid_pin, LOW);
if(group->mix < group->current_threshold){
group->mix_switch = true;
switch_solenoid(group->mix_pin_defs.solenoid_pin, HIGH);
}
String json_string;
outgoing_json_data["status"] = String("ALCOHOL_OUT_" + String(group->id));
serializeJson(outgoing_json_data, json_string);
Serial.println(json_string);
}
else if(group->alcohol >= group->current_threshold_alcohol){
group->current_threshold_alcohol += ALCOHOL_THRESHOLD_STEP;
if(!(group->mix_switch) && group->mix < MIX_MAX_THRESHOLD){
group->mix_switch = true;
switch_solenoid(group->mix_pin_defs.solenoid_pin, HIGH);
}
}
}
void check_mix_reset_routine(group_vars_t *group)
{
if(group->mix_reset_routine){
group->mix_switch = true;
switch_solenoid(group->mix_pin_defs.solenoid_pin, HIGH);
group->mix = 0;
group->mix_reset_routine = false;
group->current_threshold = MIX_THRESHOLD_STEP;
switch(group->id){
case 1:{
pulse_1_mix = 0;
break;
}
case 2:{
pulse_2_mix = 0;
break;
}
case 3:{
pulse_3_mix = 0;
break;
}
case 4:{
pulse_4_mix = 0;
break;
}
default:{
break;
}
}
}
}
void check_alcohol_reset_routine(group_vars_t *group)
{
if(group->alcohol_reset_routine){
group->alcohol_switch = false;
switch_solenoid(group->alcohol_pin_defs.solenoid_pin, HIGH);
group->alcohol = 0;
group->alcohol_reset_routine = false;
group->current_threshold_alcohol = ALCOHOL_THRESHOLD_STEP;
switch(group->id){
case 1:{
pulse_1_alcohol = 0;
break;
}
case 2:{
pulse_2_alcohol = 0;
break;
}
case 3:{
pulse_3_alcohol = 0;
break;
}
case 4:{
pulse_4_alcohol = 0;
break;
}
default:{
break;
}
}
}
}
void update_status(group_vars_t *group)
{
String json_string;
if((group->mix >= MIX_MAX_THRESHOLD) && (group->alcohol >= ALCOHOL_MAX_THRESHOLD)){
// Ignore status if limit is exceeded for both alcohol and mix
return;
}
outgoing_json["status"] = String("mixing-" + String(group->id));
outgoing_json["mix"] = group->mix;
outgoing_json["alcohol"] = group->alcohol;
outgoing_json["currentThresh_mix"] = group->current_threshold;
outgoing_json["currentThresh_alcohol"] = group->current_threshold_alcohol;
outgoing_json["alcohol_reset_routine"] = group->alcohol_reset_routine;
outgoing_json["pulse_mix"] = pulse_1_mix;
outgoing_json["pulse_alcohol"] = pulse_1_alcohol;
serializeJson(outgoing_json, json_string);
Serial.println(json_string);
//flow_meter1_mix_isr();
}
void measurement_task(void *pvParameters) {
// StaticJsonDocument<200> doc_data;
// DynamicJsonDocument outgoing_json_data(200);
while (1) {
if (group_switch_gauge_measurement) {
update_status(&group1_vars);
// update_status(&group2_vars);
// update_status(&group3_vars);
// update_status(&group4_vars);
check_alcohol_reset_routine(&group1_vars);
check_alcohol_reset_routine(&group2_vars);
check_alcohol_reset_routine(&group3_vars);
check_alcohol_reset_routine(&group4_vars);
check_mix_reset_routine(&group1_vars);
check_mix_reset_routine(&group2_vars);
check_mix_reset_routine(&group3_vars);
check_mix_reset_routine(&group4_vars);
check_mix(&group1_vars, MIX_MAX_THRESHOLD);
check_mix(&group2_vars, MIX_MAX_THRESHOLD);
check_mix(&group3_vars, MIX_MAX_THRESHOLD);
check_mix(&group4_vars, MIX_MAX_THRESHOLD);
check_alcohol(&group1_vars, ALCOHOL_MAX_THRESHOLD);
check_alcohol(&group2_vars, ALCOHOL_MAX_THRESHOLD);
check_alcohol(&group3_vars, ALCOHOL_MAX_THRESHOLD);
check_alcohol(&group4_vars, ALCOHOL_MAX_THRESHOLD);
flow_meter1_mix_isr();
flow_meter1_alcohol_isr();
// flow_meter1_alcohol_isr();
}
vTaskDelay(pdMS_TO_TICKS(500));
}
}
void jsonReceiveTask(void *pvParameters) {
Serial.begin(115200);
while (1) {
// Task to receive and process incoming JSON data from the serial port
if (Serial.available() > 0) {
String incomingChar = Serial.readString();
DeserializationError error = deserializeJson(doc, incomingChar);
String json_string;
if (error) {
Serial.print(F("deserializeJson() failed: "));
Serial.println(error.f_str());
continue;
}
if (doc["status"] == "intialization") {
calibration_multiplier_flow_1_keg = doc["G1_calibration_factor_mix"];
calibration_multiplier_flow_2_keg = doc["G2_calibration_factor_mix"];
calibration_multiplier_flow_3_keg = doc["G3_calibration_factor_mix"];
calibration_multiplier_flow_4_keg = doc["G4_calibration_factor_mix"];
calibration_multiplier_flow_1_alcohol = doc["G1_calibration_factor_alcohol"];
calibration_multiplier_flow_2_alcohol = doc["G2_calibration_factor_alcohol"];
calibration_multiplier_flow_3_alcohol = doc["G3_calibration_factor_alcohol"];
calibration_multiplier_flow_4_alcohol = doc["G4_calibration_factor_alcohol"];
g1_mix_max_vol = doc["g1_mix_max_vol"];
g1_mix_interval_vol = doc["g1_mix_interval_vol"];
g1_alcohol_max_vol = doc["g1_alcohol_max_vol"];
g1_alcohol_interval_vol = doc["g1_alcohol_interval_vol"];
g2_mix_max_vol = doc["g2_mix_max_vol"];
g2_mix_interval_vol = doc["g2_mix_interval_vol"];
g2_alcohol_max_vol = doc["g2_alcohol_max_vol"];
g2_alcohol_interval_vol = doc["g2_alcohol_interval_vol"];
g3_mix_max_vol = doc["g3_mix_max_vol"];
g3_mix_interval_vol = doc["g3_mix_interval_vol"];
g3_alcohol_max_vol = doc["g3_alcohol_max_vol"];
g3_alcohol_interval_vol = doc["g3_alcohol_interval_vol"];
g4_mix_max_vol = doc["g4_mix_max_vol"];
g4_mix_interval_vol = doc["g4_mix_interval_vol"];
g4_alcohol_max_vol = doc["g3_alcohol_max_vol"];
g3_alcohol_interval_vol = doc["g4_alcohol_interval_vol"];
// currentThreshold=g1_mix_interval_vol;
outgoing_json["status"] = "initialized";
outgoing_json["G1_calibration_factor_mix"] = calibration_multiplier_flow_1_keg;
outgoing_json["G2_calibration_factor_mix"] = calibration_multiplier_flow_2_keg;
outgoing_json["G3_calibration_factor_mix"] = calibration_multiplier_flow_3_keg;
outgoing_json["G4_calibration_factor_mix"] = calibration_multiplier_flow_4_keg;
outgoing_json["G1_calibration_factor_alcohol"] = calibration_multiplier_flow_1_alcohol;
outgoing_json["G2_calibration_factor_alcohol"] = calibration_multiplier_flow_2_alcohol;
outgoing_json["G3_calibration_factor_alcohol"] = calibration_multiplier_flow_3_alcohol;
outgoing_json["G4_calibration_factor_alcohol"] = calibration_multiplier_flow_4_alcohol;
// outgoing_json["current_threshold_G1"] = currentThreshold;
serializeJson(outgoing_json, json_string);
Serial.println(json_string);
}
else if (doc["status"] == "start_gauge_measurement") {
group_switch_gauge_measurement = true;
// Force a reset
group1_vars.alcohol_reset_routine = true;
group1_vars.mix_reset_routine = true;
group2_vars.alcohol_reset_routine = true;
group2_vars.mix_reset_routine = true;
group3_vars.alcohol_reset_routine = true;
group4_vars.mix_reset_routine = true;
group4_vars.alcohol_reset_routine = true;
group4_vars.mix_reset_routine = true;
}
else if (doc["status"] == "G1_RESET_ALCOHOL") {
group1_vars.alcohol_reset_routine = true;
}
else if (doc["status"] == "G1_RESET_MIX") {
group1_vars.mix_reset_routine = true;
}
else if (doc["status"] == "G2_RESET_ALCOHOL") {
group2_vars.alcohol_reset_routine = true;
outgoing_json["status"] = "RESETED_ALCOHOL";
serializeJson(outgoing_json, json_string);
Serial.println(json_string);
}
else if (doc["status"] == "G2_RESET_MIX") {
group2_vars.mix_reset_routine = true;
}
else if (doc["status"] == "G3_RESET_ALCOHOL") {
group3_vars.alcohol_reset_routine = true;
}
else if (doc["status"] == "G3_RESET_MIX") {
group3_vars.mix_reset_routine = true;
}
else if (doc["status"] == "G4_RESET_ALCOHOL") {
group4_vars.alcohol_reset_routine = true;
}
else if (doc["status"] == "G4_RESET_MIX") {
group4_vars.mix_reset_routine = true;
}
}
vTaskDelay(pdMS_TO_TICKS(500)); // Adjust the delay as needed
}
}
void setup() {
init_inputs();
init_outputs();
xTaskCreatePinnedToCore(measurement_task, "Task1", 4096, NULL, 0, NULL, 0);
xTaskCreatePinnedToCore(jsonReceiveTask, "JSONRecv", 2048, NULL, 1, NULL, 1);
}
float measure(float calibration_multiplier, int pulse) {
Serial.print("pulse:-");
Serial.println(pulse);
return (calibration_multiplier * pulse);
}
void flow_meter1_mix_isr()
{
pulse_1_mix++;
Serial.println(pulse_1_mix);
group1_vars.mix = measure(calibration_multiplier_flow_1_keg, pulse_1_mix);
if(group1_vars.mix >= group1_vars.current_threshold){
group1_vars.mix_switch = false;
switch_solenoid(group1_vars.mix_pin_defs.solenoid_pin, LOW);
}
}
void flow_meter2_mix_isr()
{
pulse_2_mix++;
group2_vars.mix = measure(calibration_multiplier_flow_2_keg, pulse_2_mix);
if(group2_vars.mix >= group2_vars.current_threshold){
group2_vars.mix_switch = false;
switch_solenoid(group2_vars.mix_pin_defs.solenoid_pin, LOW);
}
}
void flow_meter3_mix_isr()
{
pulse_3_mix++;
group3_vars.mix = measure(calibration_multiplier_flow_3_keg, pulse_3_mix);
if(group3_vars.mix >= group3_vars.current_threshold){
group3_vars.mix_switch = false;
switch_solenoid(group3_vars.mix_pin_defs.solenoid_pin, LOW);
}
}
void flow_meter4_mix_isr()
{
pulse_4_mix++;
group4_vars.mix = measure(calibration_multiplier_flow_4_keg, pulse_4_mix);
if(group4_vars.mix >= group4_vars.current_threshold){
group4_vars.mix_switch = false;
switch_solenoid(group4_vars.mix_pin_defs.solenoid_pin, LOW);
}
}
void flow_meter1_alcohol_isr()
{
pulse_1_alcohol++;
group1_vars.alcohol = measure(calibration_multiplier_flow_1_alcohol, pulse_1_alcohol);
if(group1_vars.alcohol >= group1_vars.current_threshold_alcohol){
group1_vars.alcohol_switch = false;
switch_solenoid(group1_vars.alcohol_pin_defs.solenoid_pin, LOW);
}
}
void flow_meter2_alcohol_isr()
{
pulse_2_alcohol++;
group2_vars.alcohol = measure(calibration_multiplier_flow_2_alcohol, pulse_2_alcohol);
if(group2_vars.alcohol >= group2_vars.current_threshold_alcohol){
group2_vars.alcohol_switch = false;
switch_solenoid(group2_vars.alcohol_pin_defs.solenoid_pin, LOW);
}
}
void flow_meter3_alcohol_isr()
{
pulse_3_alcohol++;
group3_vars.alcohol = measure(calibration_multiplier_flow_3_alcohol, pulse_3_alcohol);
if(group3_vars.alcohol >= group3_vars.current_threshold_alcohol){
group3_vars.alcohol_switch = false;
switch_solenoid(group3_vars.alcohol_pin_defs.solenoid_pin, LOW);
}
}
void flow_meter4_alcohol_isr()
{
pulse_4_alcohol++;
group4_vars.alcohol = measure(calibration_multiplier_flow_4_alcohol, pulse_4_alcohol);
if(group4_vars.alcohol >= group4_vars.current_threshold_alcohol){
group4_vars.alcohol_switch = false;
switch_solenoid(group4_vars.alcohol_pin_defs.solenoid_pin, LOW);
}
}
void loop() {
// Main loop code here
}