#include <stdio.h>
#include <stdint.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "driver/adc.h"
#include "esp_timer.h"
#include <time.h>
#include "esp_log.h"
#include <math.h>
#include "esp_adc_cal.h"
#define DC_RELAY_CONTACTOR 33
#define ADC_WIDTH ADC_WIDTH_BIT_12
#define ADC_ATTENUATION ADC_ATTEN_DB_11
#define CP_CHANNEL ADC2_CHANNEL_0
#define VOLTAGE_CHANNEL ADC2_CHANNEL_2
#define CURRENT_CHANNEL ADC2_CHANNEL_3
static const char *TAG = "AC_VOLTAGE_SENSOR";
bool state = false;
float Volts_TRMS;
float intercept = 0; // to be adjusted based on calibration testin
float slope = 2.515;
int val[100]; // Array to store sensor values
int max_v = 0;
double VmaxD = 0; // Max voltage
double VeffD = 0; // Effective voltage
double Veff = 0; // Resulting voltage
float read_volt(adc2_channel_t channel) {
int raw_out;
esp_err_t adc_result = adc2_get_raw(channel, ADC_WIDTH_BIT_12, &raw_out);
if (adc_result == ESP_OK)
{
for (int i = 0; i < 100; i++) {
if (raw_out > 2050) {
val[i] = (raw_out * 3.3 / 4095 )*2; // Store sensor value in the array if it's greater than 511
} else {
val[i] = 0; // Otherwise, set the value to 0
}
}
// Find the maximum sensor value in the array
max_v = 0;
for (int i = 0; i < 100; i++) {
if (val[i] > max_v) {
max_v = val[i]; // Update max_v if a higher value is found
}
val[i] = 0; // Reset the array element to 0
}
// Calculate effective voltage based on the maximum sensor value
if (max_v != 0) {
VmaxD = max_v*2; // Set VmaxD to the maximum sensor value
VeffD = VmaxD / sqrt(2); // Calculate effective voltage (RMS) from VmaxD
Veff = (((VeffD - 420.76) / -90.24) * -210.2) + 210.2; // Apply calibration and scaling to Veff
} else {
Veff = 0; // If no maximum value, set Veff to 0
}
VmaxD = 0; // Reset VmaxD for the next iteration
return Veff;
}
else
{
printf("Error reading ADC channel %d\n", channel);
return 0.0;
}
}
float read_cp(adc2_channel_t channel)
{
int raw_out;
esp_err_t adc_result = adc2_get_raw(channel, ADC_WIDTH_BIT_12, &raw_out);
if (adc_result == ESP_OK)
{
float voltage = raw_out * 3.3 / 4095;
//printf("Voltage1 (Channel %d): %.2fV\n", channel, voltage);
return voltage;
}
else
{
printf("Error reading ADC channel %d\n", channel);
return 0.0;
}
}
float read_current(adc2_channel_t channel)
{
int raw_out;
esp_err_t adc_result = adc2_get_raw(channel, ADC_WIDTH_BIT_12, &raw_out);
if (adc_result == ESP_OK)
{
float input = raw_out * (3.3 / 4095)* 2;
float current = (input - 2.5)/ 0.066;
return current ;
}
else
{
printf("Error reading ADC channel %d\n", channel);
return 0.0;
}
}
float energy_consumed(float voltage, float current, time_t time_seconds)
{
printf(" Current : %.2fA\n", current);
printf(" voltage : %.2fV\n", voltage);
printf(" time_seconds %lld\n", time_seconds);
float energy_kwh =(voltage * current * time_seconds) / (1000.0 * 3600.0);
printf(" Energy Consumed: %.2f kWh\n", energy_kwh);
return energy_kwh;
}
void app_main(void)
{
printf("Initializing...\n");
// Set up GPIO and ADC channels
gpio_set_direction(DC_RELAY_CONTACTOR, GPIO_MODE_OUTPUT);
adc2_config_channel_atten(CP_CHANNEL, ADC_ATTENUATION);
adc2_config_channel_atten(VOLTAGE_CHANNEL, ADC_ATTENUATION);
adc2_config_channel_atten(CURRENT_CHANNEL, ADC_ATTENUATION);
vTaskDelay(2000 / portTICK_PERIOD_MS);
int balance = 20;
int initialized = 0;
time_t start_time;
while (balance > 0)
{
float n = read_cp(CP_CHANNEL); // Control Pilot voltage
printf("CP value: %.2fV\n", n);
if (n >= 1.242 && n <= 1.863 )
{
if(!initialized){
time(&start_time);
initialized = 1;
}
gpio_set_level(DC_RELAY_CONTACTOR, 1);
time_t now;
time(&now);
printf(" start charging time %lld\n", start_time);
printf(" current time : %lld\n", now);
time_t time_passed = now - start_time;
printf(" time_passed : %lld\n", time_passed);
float voltage = read_volt(VOLTAGE_CHANNEL); // Replace with the correct channel for voltage
float current = read_current(CURRENT_CHANNEL); // Replace with the correct channel for current
//printf(" Current : %.2fA\n", current); // Channel 3
float energy = energy_consumed(voltage, current, time_passed);
// Deduct the balance based on energy consumption and a predefined rate
float charging_rate = 0.2; // Example rate
balance -= energy * charging_rate;
if (balance <0){
balance = 0;
}
printf("Remaining balance: %d\n", balance);
}
else if (n >= 1.863 )
{
printf("Car NOT plugged\n");
gpio_set_level(DC_RELAY_CONTACTOR, 0);
initialized = 0;
}else
{
printf("error\n");
gpio_set_level(DC_RELAY_CONTACTOR, 0);
initialized = 0;
printf("Charging session ended\n");
}
vTaskDelay(1000 / portTICK_PERIOD_MS); // Delay for stability
}
}