#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 ADC1_CHANNEL_7
#define CURRENT_CHANNEL ADC2_CHANNEL_3
const float MAX_CURRENT = 30.0;
#define NUM_READINGS 10
esp_adc_cal_characteristics_t *adc_chars;
#define DEFAULT_VREF 1100 // Default reference voltage in mV
#define NO_OF_SAMPLES 100 // Number of samples to take for averaging
static const char *TAG = "AC_VOLTAGE_SENSOR";
esp_adc_cal_characteristics_t *adc_chars;
bool state = false;
float read_volt(adc2_channel_t channel) {
int raw_out = 0;
double sensorValue1 = 0;
int val[NO_OF_SAMPLES];
int max_v = 0;
double VmaxD = 0;
double VeffD = 0;
double Veff = 0;
// Initialize ADC
for (int i = 0; i < NO_OF_SAMPLES; i++) {
if (adc1_get_raw(channel, ADC_WIDTH_BIT_12, &raw_out) == ESP_OK) {
sensorValue1 = raw_out;
if (raw_out > 2047) { // equivalent to 511 in 12-bit resolution
val[i] = sensorValue1;
} else {
val[i] = 0;
}
vTaskDelay(pdMS_TO_TICKS(1));
} else {
ESP_LOGE(TAG, "ADC read failed");
return -1; // Return an error value if ADC read fails
}
}
// Find the maximum value in the array
max_v = 0;
for (int i = 0; i < NO_OF_SAMPLES; i++) {
if (val[i] > max_v) {
max_v = val[i];
}
}
// Calculate effective voltage
if (max_v != 0) {
VmaxD = (double) max_v;
VeffD = VmaxD / sqrt(2);
Veff = (((VeffD - 420.76) / -90.24) * -210.2) + 210.2;
} else {
Veff = 0;
}
// Determine state based on voltage
state = (Veff >= 210);
ESP_LOGI(TAG, "Voltage: %.2f V, state: %s", Veff, state ? "HIGH" : "LOW");
return Veff;
}
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 volt = raw_out * 3.3 / 4095;
float current = volt * MAX_CURRENT;
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; // Convert to kWh
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);
adc1_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(ADC2_CHANNEL_2); // Replace with the correct channel for voltage
printf(" Voltage : %.2fV\n", voltage);
float current = read_current(ADC2_CHANNEL_3); // 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 unplugged\n");
gpio_set_level(DC_RELAY_CONTACTOR, 0);
initialized = 0;
printf("Charging session ended\n");
}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
}
printf("Charging session ended\n");
}