/********* Pleasedontcode.com **********

	Pleasedontcode thanks you for automatic code generation! Enjoy your code!

	- Terms and Conditions:
	You have a non-exclusive, revocable, worldwide, royalty-free license
	for personal and commercial use. Attribution is optional; modifications
	are allowed, but you're responsible for code maintenance. We're not
	liable for any loss or damage. For full terms,
	please visit pleasedontcode.com/termsandconditions.

	- Project: "Fuzzy Control"
	- Source Code compiled for: Arduino Uno
	- Source Code created on: 2024-03-17 17:03:38

********* Pleasedontcode.com **********/

/****** SYSTEM REQUIREMENTS *****/
/****** SYSTEM REQUIREMENT 1 *****/
	/* Using fuzzy logic and the fuzzy library i have to */
	/* write a specific code where i have an output led */
	/* (pin 6) and input photorsistor (pin A0), and */
	/* ultrasonic for the detection of motion (pin 2 for */
	/* triger and 3 for echo) the fuzzy rule are Motion */
	/* detecte */
/****** END SYSTEM REQUIREMENTS *****/

/****** DEFINITION OF LIBRARIES *****/
#include <Ultrasonic.h> //https://github.com/ErickSimoes/Ultrasonic
#include <Fuzzy.h> //https://github.com/zerokol/eFLL

/****** FUNCTION PROTOTYPES *****/
void setup(void);
void loop(void);
void updateOutputs(void);

/***** DEFINITION OF DIGITAL INPUT PINS *****/
const uint8_t ultrasonic_sensor_HC_SR04_Echo_PIN_D3 = 3;

/***** DEFINITION OF ANALOG INPUT PINS *****/
const uint8_t Photoresistor_PIN_A0 = A0;

/***** DEFINITION OF DIGITAL OUTPUT PINS *****/
const uint8_t LED_LEDRGB_Blue_PIN_D6 = 6;
const uint8_t ultrasonic_sensor_HC_SR04_Trigger_PIN_D2 = 2;

/***** DEFINITION OF OUTPUT RAW VARIABLES *****/
/***** used to store raw data *****/
bool LED_LEDRGB_Blue_PIN_D6_rawData = 0;
bool ultrasonic_sensor_HC_SR04_Trigger_PIN_D2_rawData = 0;

/***** DEFINITION OF OUTPUT PHYSICAL VARIABLES *****/
/***** used to store data after characteristic curve transformation *****/
float LED_LEDRGB_Blue_PIN_D6_phyData = 0.0;
float ultrasonic_sensor_HC_SR04_Trigger_PIN_D2_phyData = 0.0;

/****** DEFINITION OF LIBRARIES CLASS INSTANCES *****/
Ultrasonic ultrasonic_sensor_HC_SR04(ultrasonic_sensor_HC_SR04_Trigger_PIN_D2, ultrasonic_sensor_HC_SR04_Echo_PIN_D3);

/****** FUZZY *****/
Fuzzy *fuzzy = new Fuzzy();

// FuzzyInput
FuzzySet *photoresistor_low = new FuzzySet(0, 0, 0, 100);
FuzzySet *photoresistor_mid = new FuzzySet(0, 100, 100, 200);
FuzzySet *photoresistor_high = new FuzzySet(100, 200, 1023, 1023);

// FuzzyOutput
FuzzySet *led_off = new FuzzySet(0, 0, 0, 0);
FuzzySet *led_on = new FuzzySet(1, 1, 1, 1);

void setup(void)
{
  // put your setup code here, to run once:
  pinMode(ultrasonic_sensor_HC_SR04_Echo_PIN_D3, INPUT);
  pinMode(Photoresistor_PIN_A0, INPUT);

  pinMode(LED_LEDRGB_Blue_PIN_D6, OUTPUT);
  pinMode(ultrasonic_sensor_HC_SR04_Trigger_PIN_D2, OUTPUT);

  // Add FuzzyInput and FuzzyOutput objects to the fuzzy logic system
  FuzzyInput *photoresistor = new FuzzyInput(1);
  photoresistor->addFuzzySet(photoresistor_low);
  photoresistor->addFuzzySet(photoresistor_mid);
  photoresistor->addFuzzySet(photoresistor_high);
  fuzzy->addFuzzyInput(photoresistor);

  FuzzyOutput *ledState = new FuzzyOutput(1);
  ledState->addFuzzySet(led_off);
  ledState->addFuzzySet(led_on);
  fuzzy->addFuzzyOutput(ledState);

  // Define fuzzy rules here
  FuzzyRuleAntecedent *motionDetected = new FuzzyRuleAntecedent();
  motionDetected->joinSingle(photoresistor_high);

  FuzzyRuleConsequent *outputLedOn = new FuzzyRuleConsequent();
  outputLedOn->addOutput(led_on);

  FuzzyRule *fuzzyRule = new FuzzyRule(1, motionDetected, outputLedOn);
  fuzzy->addFuzzyRule(fuzzyRule);

  // Set initial input values for the fuzzy logic system
  fuzzy->setInput(1, analogRead(Photoresistor_PIN_A0));

  // Set initial output values for the physical outputs
  LED_LEDRGB_Blue_PIN_D6_rawData = false;
  ultrasonic_sensor_HC_SR04_Trigger_PIN_D2_rawData = false;

  // Start serial communication
  Serial.begin(9600);
}

void loop(void)
{
  // put your main code here, to run repeatedly:
  // Perform ultrasonic sensor measurements
  float distance = getUltrasonicDistance();

  // Set input values for the fuzzy logic system
  fuzzy->setInput(1, analogRead(Photoresistor_PIN_A0));

  // Perform fuzzy logic calculations
  fuzzy->fuzzify();

  // Obtain output value from fuzzy logic system
  float ledState = fuzzy->defuzzify(1);

  // Update physical outputs based on fuzzy logic outputs
  updateOutputs(ledState);
  delay(1000);
}

float getUltrasonicDistance()
{
  unsigned int distance = ultrasonic_sensor_HC_SR04.read(CM);
  if (distance == 0) {
    return 100; // If no object detected, set distance to maximum value
  } else {
    return distance;
  }
}

void updateOutputs(float ledState)
{
  if (ledState > 0.5) {
    LED_LEDRGB_Blue_PIN_D6_rawData = true;
  } else {
    LED_LEDRGB_Blue_PIN_D6_rawData = false;
  }

  // Update physical output states
  digitalWrite(LED_LEDRGB_Blue_PIN_D6, LED_LEDRGB_Blue_PIN_D6_rawData);
  digitalWrite(ultrasonic_sensor_HC_SR04_Trigger_PIN_D2, ultrasonic_sensor_HC_SR04_Trigger_PIN_D2_rawData);

  // Print the output state
  Serial.print("LED State: ");
  Serial.println(LED_LEDRGB_Blue_PIN_D6_rawData);
}
