DIY 3kW Arduino MPPT Solar Charge Controller ESP32

Diskuze na téma solárních, větrných a ostatních regulátorů, datové komunikace mezi regulátory a PC, instalace software, zapojení regulátorů, chování a zkušenosti s různými typy regulátorů.
Uživatelský avatar
rottenkiwi
Příspěvky: 5451
Registrován: pát úno 13, 2015 2:24 pm
Lokalita: SO, SK
Bydliště: SO, SK

Re: DIY 3kW Arduino MPPT Solar Charge Controller ESP32

Příspěvek od rottenkiwi »

Ked si chcete niekto vyskusat urobit dvojfazovy MPPT s ESP32
tak odporucam precitat:

https://www.instructables.com/DIY-1kW-M ... ontroller/
schemu najdete tu:

https://www.youtube.com/watch?v=R-_ATHYgcBQ

parametre BUCK tu:

https://www.youtube.com/watch?v=bJVInQO7r_A

Tu je moj kod na par riadkov:

Kód: Vybrat vše

#include <Arduino.h>
#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
//#include <AsyncMqttClient.h>
#include "SPIFFS.h"
#include <Arduino_JSON.h>
#include <EEPROM.h>
#include <driver/ledc.h>
#include <driver/gpio.h>
#include <driver/mcpwm.h>
#include <esp_intr_alloc.h>
#include <soc/soc.h>
#include <soc/soc_caps.h>
#include <soc/mcpwm_reg.h>
#include <soc/mcpwm_struct.h>
#include <esp_err.h>
#include <hal/mcpwm_types.h>
#include <Adafruit_ADS1X15.h>
#include <LiquidCrystal_I2C.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <DS1307ESP.h>

const int oneWireBus = 27;  
OneWire oneWire(oneWireBus);
DallasTemperature sensors(&oneWire);
int numberOfDevices;
DeviceAddress tempDeviceAddress; 

Adafruit_ADS1115 ads0, ads1;
uint8_t address = 0x27;uint8_t cols = 20;uint8_t rows = 4;
LiquidCrystal_I2C lcd( address, cols, rows );
DS1307ESP rtc;

#define EEPROM_MAX 1024
#define FAN_PIN_0 33
#define FAN_PIN_1 35

// setting PWM properties
const int freq = 5000;const int ledChannel_0 = 0;const int ledChannel_1 = 1;const int resolution = 8;

#define SD_PIN  2  // ESP32 for SD at IR2104 IR2184 .. etc. first phase
#define SD_PIN2  4  // ESP32 for second phase 

#define MIN_AMPS 0.49
#define REBULK_VOLTS 12.95
#define MIN_PANEL_VOLTS 13.00
#define CRITICAL_VOLTS 15.15

#define MAX_VOLTS_PB 14.95
#define MAX_VOLTS_SLOW_PB 13.60
#define MAX_VOLTS_FLOAT_PB 13.50
#define REBULK_VOLTS_PB 13.45

#define MAX_V_OUT 14.90
#define MAX_V_IN 119.00

#define MAX_VOLTS_LFP 14.20
#define MAX_VOLTS_SLOW_LFP 13.60
#define MAX_VOLTS_FLOAT_LFP 13.50
#define REBULK_VOLTS_LFP 13.40

#define MAX_V_OUT_12V 14.95
#define MIN_V_OUT_12V 11.10
#define MIN_PANEL_VOLTS_12V 19.00

#define MAX_V_OUT_24V 29.80
#define MIN_V_OUT_24V 22.20
#define MIN_PANEL_VOLTS_24V 32.00

#define MAX_V_OUT_48V 59.40
#define MIN_V_OUT_48V 44.40
#define MIN_PANEL_VOLTS_48V 51.20

#define A_OFFSET 1825.0

#define PWM_1 2300
#define PWM_10 23000
#define PWM_2 2000
#define PWM_20 20000
#define PWM_3 2400
#define PWM_30 24000
#define PWM_4 2500
#define PWM_40 25000

#define GPIO_PWM0A_OUT 19
#define GPIO_PWM0B_OUT 23
#define GPIO_PWM1A_OUT 17
#define GPIO_PWM1B_OUT 18
#define GPIO_PWM2A_OUT 16
#define GPIO_PWM2B_OUT 5

const char* ssid = "guest";
const char* password = "password";
AsyncWebServer server(80);
AsyncWebSocket ws("/ws");
AsyncEventSource events("/events");

JSONVar readings;

const int ledPin1 = 2;
const int ledPin2 = 4;
const int ledPin3 = 12;
const int ledPin4 = 13;

String message = "";
String buffer_1 = "                  ";
String sliderValue1 = "0";
String sliderValue2 = "0";
String sliderValue3 = "0";
String sliderValue4 = "0";

int dutyCycle1;
int dutyCycle2;
int dutyCycle3;
int dutyCycle4;
int deltaPWM = 0;

const int ledChannel1 = 0;
const int ledChannel2 = 1;
const int ledChannel3 = 2;
const int ledChannel4 = 3;

unsigned long previous = 0;   // Stores last time temperature was published
const long interval = 992;        // Interval at which to publish sensor readings
const long setup_interval = 333;        // Interval at which to publish sensor readings
long int num_of_intervals, duty_high, duty_low, max_volts_high; 
unsigned long previousTime = 0; 
unsigned long now, currentTime, loop_time, loop_interval, now_m;

long wh_all;
int wh_day;
int Addr_0 = 0, Addr_1 = 4;
const unsigned long timeoutTime = 19990;

char sF_BULK[7] = {'F','_','B','U','L','K','\0'} ;
char sS_BULK[7] = {'S','_','B','U','L','K','\0'} ;
char sS_ABS[7] = {'S','_','A','B','S',' ','\0'} ;
char sS_FLOAT[7] = {'_','F','L','O','A','T','\0'} ;
char sS_ST_BY[7] = {'_','S','T','_','B','Y','\0'} ;
char sS_CRIT [7] = {'C','R','I','T','_','V','\0'} ;

char sS_A_IN [3] = {'I','\0'} ; char sS_A_OUT [3] = {'O','\0'} ;char sS_V_IN  [3] = {'O','\0'} ;char sS_V_OUT [3] = {'O','\0'} ;

float duty_0 [325] = { 11.0,11.2,11.4,11.6,11.8, 12.0,12.2,12.4,12.6,12.8, 13.0,13.2,13.4,13.6,13.8, 14.0,14.2,14.4,14.6,14.8, 
                       15.0,15.2,15.4,15.6,15.8, 16.0,16.2,16.4,16.6,16.8, 17.0,17.2,17.4,17.6,17.8, 18.0,18.2,18.4,18.6,18.8, 
                       19.0,19.2,19.4,19.6,19.8, 20.0,20.2,20.4,20.6,20.8,
                       21.0,21.2,21.4,21.6,21.8, 22.0,22.2,22.4,22.6,22.8, 23.0,23.2,23.4,23.6,23.8, 24.0,24.2,24.4,24.6,24.8, 
                       25.0,25.2,25.4,25.6,25.8, 26.0,26.2,26.4,26.6,26.8, 27.0,27.2,27.4,27.6,27.8, 28.0,28.2,28.4,28.6,28.8, 
                       29.0,29.2,29.4,29.6,29.8, 30.0,30.2,30.4,30.6,30.8,
                       31.0,31.2,31.4,31.6,31.8, 32.0,32.2,32.4,32.6,32.8, 33.0,33.2,33.4,33.6,33.8, 34.0,34.2,34.4,34.6,34.8, 
                       35.0,35.2,35.4,35.6,35.8, 36.0,36.2,36.4,36.6,36.8, 37.0,37.2,37.4,37.6,37.8, 38.0,38.2,38.4,38.6,38.8, 
                       39.0,39.2,39.4,39.6,39.8, 40.0,40.2,40.4,40.6,40.8, 41.0,41.2,41.4,41.6,41.8, 42.0,42.2,42.4,42.6,42.8,
                       43.0,43.2,43.4,43.6,43.8, 44.0,44.2,44.4,44.6,44.8, 45.0,45.2,45.4,45.6,45.8, 46.0,46.2,46.4,46.6,46.8,
                       47.0,47.2,47.4,47.6,47.8, 48.0,48.2,48.4,48.6,48.8, 49.0,49.2,49.4,49.6,49.8, 50.0,50.1,50.2,50.3,50.4,
                       50.5,50.6,50.7,50.8,50.9, 51.0,51.1,51.2,51.3,51.4, 51.5,51.6,51.7,51.8,51.9, 52.0,52.1,52.2,52.3,52.4,
                       52.5,52.6,52.7,52.8,52.9, 53.0,53.1,53.2,53.3,53.4, 53.5,53.6,53.7,53.8,53.9, 54.0,54.2,54.4,54.6,54.8,
                       55.0,55.2,55.4,55.6,55.8, 56.0,56.2,56.4,56.6,56.8, 57.0,57.2,57.4,57.6,57.8, 58.0,58.2,58.4,58.6,58.8,
                       59.0,59.2,59.4,59.6,59.8 ,60.0,60.2,60.4,60.6,60.8, 61.0,61.2,61.4,61.6,61.8 ,62.0,62.2,62.4,62.6,62.8,
                       63.0,63.2,63.4,63.6,63.8, 64.0,64.2,64.4,64.6,64.8, 65.0,65.2,65.4,65.6,65.8, 66.0,66.2,66.4,66.6,66.8,
                       67.0,67.2,67.4,67.6,67.8, 68.0,68.2,68.4,68.6,68.8, 69.0,69.2,69.4,69.6,69.8, 70.0,70.2,70.4,70.6,70.8,
                       71.0,71.2,71.4,71.6,71.8  };

float duty_1 [325] = { 11.0,11.2,11.4,11.6,11.8, 12.0,12.2,12.4,12.6,12.8, 13.0,13.2,13.4,13.6,13.8, 14.0,14.2,14.4,14.6,14.8, 
                       15.0,15.2,15.4,15.6,15.8, 16.0,16.2,16.4,16.6,16.8, 17.0,17.2,17.4,17.6,17.8, 18.0,18.2,18.4,18.6,18.8, 
                       19.0,19.2,19.4,19.6,19.8, 20.0,20.2,20.4,20.6,20.8,
                       21.0,21.2,21.4,21.6,21.8, 22.0,22.2,22.4,22.6,22.8, 23.0,23.2,23.4,23.6,23.8, 24.0,24.2,24.4,24.6,24.8, 
                       25.0,25.2,25.4,25.6,25.8, 26.0,26.2,26.4,26.6,26.8, 27.0,27.2,27.4,27.6,27.8, 28.0,28.2,28.4,28.6,28.8, 
                       29.0,29.2,29.4,29.6,29.8, 30.0,30.2,30.4,30.6,30.8,
                       31.0,31.2,31.4,31.6,31.8, 32.0,32.2,32.4,32.6,32.8, 33.0,33.2,33.4,33.6,33.8, 34.0,34.2,34.4,34.6,34.8, 
                       35.0,35.2,35.4,35.6,35.8, 36.0,36.2,36.4,36.6,36.8, 37.0,37.2,37.4,37.6,37.8, 38.0,38.2,38.4,38.6,38.8, 
                       39.0,39.2,39.4,39.6,39.8, 40.0,40.2,40.4,40.6,40.8, 41.0,41.2,41.4,41.6,41.8, 42.0,42.2,42.4,42.6,42.8,
                       43.0,43.2,43.4,43.6,43.8, 44.0,44.2,44.4,44.6,44.8, 45.0,45.2,45.4,45.6,45.8, 46.0,46.2,46.4,46.6,46.8,
                       47.0,47.2,47.4,47.6,47.8, 48.0,48.2,48.4,48.6,48.8, 49.0,49.2,49.4,49.6,49.8, 50.0,50.1,50.2,50.3,50.4,
                       50.5,50.6,50.7,50.8,50.9, 51.0,51.1,51.2,51.3,51.4, 51.5,51.6,51.7,51.8,51.9, 52.0,52.1,52.2,52.3,52.4,
                       52.5,52.6,52.7,52.8,52.9, 53.0,53.1,53.2,53.3,53.4, 53.5,53.6,53.7,53.8,53.9, 54.0,54.2,54.4,54.6,54.8,
                       55.0,55.2,55.4,55.6,55.8, 56.0,56.2,56.4,56.6,56.8, 57.0,57.2,57.4,57.6,57.8, 58.0,58.2,58.4,58.6,58.8,
                       59.0,59.2,59.4,59.6,59.8 ,60.0,60.2,60.4,60.6,60.8, 61.0,61.2,61.4,61.6,61.8 ,62.0,62.2,62.4,62.6,62.8,
                       63.0,63.2,63.4,63.6,63.8, 64.0,64.2,64.4,64.6,64.8, 65.0,65.2,65.4,65.6,65.8, 66.0,66.2,66.4,66.6,66.8,
                       67.0,67.2,67.4,67.6,67.8, 68.0,68.2,68.4,68.6,68.8, 69.0,69.2,69.4,69.6,69.8, 70.0,70.2,70.4,70.6,70.8,
                       71.0,71.2,71.4,71.6,71.8  };

float duty_2 [325] = { 11.0,11.2,11.4,11.6,11.8, 12.0,12.2,12.4,12.6,12.8, 13.0,13.2,13.4,13.6,13.8, 14.0,14.2,14.4,14.6,14.8, 
                       15.0,15.2,15.4,15.6,15.8, 16.0,16.2,16.4,16.6,16.8, 17.0,17.2,17.4,17.6,17.8, 18.0,18.2,18.4,18.6,18.8, 
                       19.0,19.2,19.4,19.6,19.8, 20.0,20.2,20.4,20.6,20.8,
                       21.0,21.2,21.4,21.6,21.8, 22.0,22.2,22.4,22.6,22.8, 23.0,23.2,23.4,23.6,23.8, 24.0,24.2,24.4,24.6,24.8, 
                       25.0,25.2,25.4,25.6,25.8, 26.0,26.2,26.4,26.6,26.8, 27.0,27.2,27.4,27.6,27.8, 28.0,28.2,28.4,28.6,28.8, 
                       29.0,29.2,29.4,29.6,29.8, 30.0,30.2,30.4,30.6,30.8,
                       31.0,31.2,31.4,31.6,31.8, 32.0,32.2,32.4,32.6,32.8, 33.0,33.2,33.4,33.6,33.8, 34.0,34.2,34.4,34.6,34.8, 
                       35.0,35.2,35.4,35.6,35.8, 36.0,36.2,36.4,36.6,36.8, 37.0,37.2,37.4,37.6,37.8, 38.0,38.2,38.4,38.6,38.8, 
                       39.0,39.2,39.4,39.6,39.8, 40.0,40.2,40.4,40.6,40.8, 41.0,41.2,41.4,41.6,41.8, 42.0,42.2,42.4,42.6,42.8,
                       43.0,43.2,43.4,43.6,43.8, 44.0,44.2,44.4,44.6,44.8, 45.0,45.2,45.4,45.6,45.8, 46.0,46.2,46.4,46.6,46.8,
                       47.0,47.2,47.4,47.6,47.8, 48.0,48.2,48.4,48.6,48.8, 49.0,49.2,49.4,49.6,49.8, 50.0,50.1,50.2,50.3,50.4,
                       50.5,50.6,50.7,50.8,50.9, 51.0,51.1,51.2,51.3,51.4, 51.5,51.6,51.7,51.8,51.9, 52.0,52.1,52.2,52.3,52.4,
                       52.5,52.6,52.7,52.8,52.9, 53.0,53.1,53.2,53.3,53.4, 53.5,53.6,53.7,53.8,53.9, 54.0,54.2,54.4,54.6,54.8,
                       55.0,55.2,55.4,55.6,55.8, 56.0,56.2,56.4,56.6,56.8, 57.0,57.2,57.4,57.6,57.8, 58.0,58.2,58.4,58.6,58.8,
                       59.0,59.2,59.4,59.6,59.8 ,60.0,60.2,60.4,60.6,60.8, 61.0,61.2,61.4,61.6,61.8 ,62.0,62.2,62.4,62.6,62.8,
                       63.0,63.2,63.4,63.6,63.8, 64.0,64.2,64.4,64.6,64.8, 65.0,65.2,65.4,65.6,65.8, 66.0,66.2,66.4,66.6,66.8,
                       67.0,67.2,67.4,67.6,67.8, 68.0,68.2,68.4,68.6,68.8, 69.0,69.2,69.4,69.6,69.8, 70.0,70.2,70.4,70.6,70.8,
                       71.0,71.2,71.4,71.6,71.8  };                                            


float AMPS_MAX [3][6] = { { 19, 19, 19, 19, 19, 19   }, { 12, 12, 12, 12, 12, 12   } ,{ 6, 6, 6, 6, 6, 6  }  };
int duty_modulo = 325;int duty_index = 1;int duty_index_b = 1;int amps_index = 0;int phase = 0;
float A1_awg, A1_sum, A2_awg, A2_sum  = 0;
float max_volts, max_volts_slow, max_volts_float ,rebulk_volts, min_panel_volts  ;
int amps_modulo = 6;
float AMPS [3][6] = { { 17, 17, 17, 17, 17, 17   }, { 10, 10, 10, 10, 10, 10   } ,{ 4, 4, 4, 4, 4, 4   }  };
boolean setup_amps, mppt, lfp, temp_algo;
float   amps_f,   amps_s, amps_step, max_v_in, max_v_out, critical_volts, T_factor;
int duty_begin;
  
float x,y,z,n = 0.0;
char sx[10] = {' '} ;char sy[10] = {' '} ;char sz[10] = {' '} ;
char sa[10] = {' '} ;char sn[10] = {' '} ;char ss[10] = {' '} ;
char x0 [10] = {' '};  char x1 [10] = {' '};  char x2 [10] = {' '}; 
char x3 [10] = {' '};  char x4 [10] = {' '};  char x5 [10] = {' '};
char x6 [10] = {' '};   char x7 [10] = {' '};    char x8 [10] = {' '};  char x9 [10] = {' '};

int16_t adc0, adc1, adc2, adc3, adc1_0;
int32_t adc_avg;

float volts0, volts1, volts2, volts3, volts1_0, V_IN, V_OUT, V_OC;
float amps0, amps1, amps1_0, amps_1, p_in, p_out, eta, p_out_0, p_out_1, wh;
float V_panels, V_panels_last, power, power_last;

const int S_max = 3;
int32_t A_0_a [S_max] = {13300};
int A_0_i = 0;
int32_t A_1_a [S_max] = {13200};
int A_1_i = 0;
int32_t A_2_a [S_max] = {13200};
int A_2_i = 0;
 
const float volts0_off = 2494.0;
const float volts1_off = 2489.0;
const float volts1_0_off = 2482.0;

const float volts2_off = - 0.120;
const float volts3_off = - 0.120;
const float FACTOR_IN = 13.23; // -----------------mV per AMPER
const float FACTOR_OUT_0 = -13.23; // ACS758 sens. mV per AMPER
const float FACTOR_OUT_1 = -13.23; // ------------ mV per AMPER

//String tempA [10] = { "29.12","28.95","14.77","15.05","28.83","56.12","1674.06", "20.36","86.12","1752.94"  };
String tempA [12] = { "29.12","28.95","14.77","15.05","28.83","56.12","1674.06", "93.98", "20.36","86.12","1752.94", "1.02"  };

JSONVar sliderValues;

String getSliderValues(){
  sliderValues["sliderValue1"] = String(sliderValue1);  sliderValues["sliderValue2"] = String(sliderValue2);
  sliderValues["sliderValue3"] = String(sliderValue3);  sliderValues["sliderValue4"] = String(sliderValue4);
  String jsonString = JSON.stringify(sliderValues);
  return jsonString;
}

void initFS() {
  if (!SPIFFS.begin()) {    Serial.println("An error has occurred while mounting SPIFFS");  }
  else { Serial.println("SPIFFS mounted successfully");  }
}

void initWiFi() {
  WiFi.mode(WIFI_STA);  WiFi.begin(ssid, password);  Serial.print("Connecting to WiFi ..");
  while (WiFi.status() != WL_CONNECTED) {    Serial.print('.');    delay(500);  }
  Serial.println(WiFi.localIP());
}

void notifyClients(String sliderValues) {
  ws.textAll(sliderValues);
}

void handleWebSocketMessage(void *arg, uint8_t *data, size_t len) {
  AwsFrameInfo *info = (AwsFrameInfo*)arg;
  if (info->final && info->index == 0 && info->len == len && info->opcode == WS_TEXT) {
    data[len] = 0;
    message = (char*)data;
    if (message.indexOf("1s") >= 0) {
      sliderValue1 = message.substring(2);
      dutyCycle1 = map(sliderValue1.toInt(), 0, 100, 0, 255);
      Serial.println(dutyCycle1);
      Serial.print(getSliderValues());
      notifyClients(getSliderValues());
    }
    if (message.indexOf("2s") >= 0) {
      sliderValue2 = message.substring(2);
      dutyCycle2 = map(sliderValue2.toInt(), 0, 100, 0, 255);
      Serial.println(dutyCycle2);
      Serial.print(getSliderValues());
      notifyClients(getSliderValues());
    }    
    if (message.indexOf("3s") >= 0) {
      sliderValue3 = message.substring(2);
      dutyCycle3 = map(sliderValue3.toInt(), 0, 100, 0, 255);
      Serial.println(dutyCycle3);
      Serial.print(getSliderValues());
      notifyClients(getSliderValues());
    }
     if (message.indexOf("4s") >= 0) {
      sliderValue4 = message.substring(2);
      dutyCycle4 = map(sliderValue4.toInt(), 0, 100, 0, 255);
      Serial.println(dutyCycle4);
      Serial.print(getSliderValues());
      notifyClients(getSliderValues());
    }
    if (strcmp((char*)data, "getValues") == 0) {
      notifyClients(getSliderValues());
    }
  }
}

void onEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len) {
  switch (type) {
    case WS_EVT_CONNECT:
      Serial.printf("WebSocket client #%u connected from %s\n", client->id(), client->remoteIP().toString().c_str());
      break;
    case WS_EVT_DISCONNECT:
      Serial.printf("WebSocket client #%u disconnected\n", client->id());
      break;
    case WS_EVT_DATA:
      handleWebSocketMessage(arg, data, len);
      break;
    case WS_EVT_PONG:
    case WS_EVT_ERROR:
      break;
  }
}

void initWebSocket() {
  ws.onEvent(onEvent);
  server.addHandler(&ws);
}

String processor(const String& var){

  if(var == "TEMPERATUREA"){
    return tempA[0];
  }
  else if(var == "TEMPERATUREB"){
    return tempA[1];
  }
  else if(var == "TEMPERATUREC"){
    return tempA[2];
  }
  else if(var == "TEMPERATURED"){
    return tempA[3];
  }
   else if(var == "TEMPERATUREE"){
    return tempA[4];
  }
   else if(var == "TEMPERATUREF"){
    return tempA[5];
  }
   else if(var == "TEMPERATUREG"){
    return tempA[6];
  }
   else if(var == "TEMPERATUREH"){
    return tempA[7];
  }
   else if(var == "TEMPERATUREI"){
    return tempA[8];
  }
   else if(var == "TEMPERATUREJ"){
    return tempA[9];
  }
  else if(var == "TEMPERATUREK"){
    return tempA[10];
  }
  else if(var == "TEMPERATUREL"){
    return tempA[11];
  }
  return String();
}

void readTemp_1 () {
  sensors.requestTemperatures();   float temp_1 = sensors.getTempCByIndex(0);
  Serial.print(temp_1);  Serial.print("ºC_1");  tempA [0] = String(temp_1);
  temp_1 = sensors.getTempCByIndex(1);  Serial.print(temp_1);  Serial.println("ºC_2");
  tempA [1] = String(temp_1);
}

void set_lcd (){
  lcd.init();    
  lcd.backlight(); lcd.setCursor(1,0);  lcd.print("MPPT ver.  -07.07-!");
  lcd.setCursor(1,1);  lcd.print("Amps  OUT: ");   lcd.setCursor(1,2);  lcd.print("Volts IN : ");
  lcd.setCursor(1,3);  lcd.print("VOLTS OUT: ");  char x1 [10] = {' '};  char x2 [10] = {' '};  char x3 [10] = {' '};  char x4 [10] = {' '};
  
  sprintf (x2, "%3.2f", amps_f );   x2[7] = {'\0'} ;  sprintf (x3, "%3.2f", volts2 );   x3[7] = {'\0'} ;
  sprintf (x4, "%3.2f", volts3 );   x4[7] = {'\0'} ;  lcd.setCursor(12,1);       lcd.print( x2 );
  lcd.setCursor(12,2);       lcd.print( x3 );  lcd.setCursor(12,3);       lcd.print( x4 );
  delay (550);    lcd.init();     lcd.backlight();
  lcd.setCursor(1,0);  lcd.print("      A           W");
  lcd.setCursor(1,1);  lcd.print("      A           C");
  lcd.setCursor(1,2);  lcd.print("      A           C");
  lcd.setCursor(1,3);  lcd.print("      V           V");
  delay (100);
  sx[9] = {'\0'} ;     sy[9] = {'\0'} ;      sz[9] = {'\0'} ;     sa[9] = {'\0'} ;     
}

void printAddress(DeviceAddress deviceAddress) {
  for (uint8_t i = 0; i < 8; i++){     if (deviceAddress[i] < 16) Serial.print("0");      Serial.print(deviceAddress[i], HEX);  }
}  

void set_sd_HIGH (){ digitalWrite ( SD_PIN, HIGH ); digitalWrite ( SD_PIN2, HIGH ); }

void set_sd_LOW (){ digitalWrite ( SD_PIN, LOW ); digitalWrite ( SD_PIN2, LOW ); }

static void readOutTemp( void * pvParameters )
{
  for(;;)
  {
    if (1)
    {
      String extTemp = "";      sensors.requestTemperatures();
      extTemp = (String)sensors.getTempCByIndex(0);      tempA [0] = String(extTemp );
      extTemp = (String)sensors.getTempCByIndex(1);      tempA [1] = String(extTemp );
      #if DEBUG 
        Serial.print("Temperature: ");        Serial.println(extTemp);
      #endif
      delay(1);  
    }
    delay(1);  
  }
}

void setup(void)
{
  Serial.begin(115200);   rtc.begin();
  pinMode ( SD_PIN, OUTPUT );   pinMode ( SD_PIN2, OUTPUT );
  digitalWrite ( SD_PIN, LOW );   digitalWrite ( SD_PIN2, LOW );
  EEPROM.begin( EEPROM_MAX );    wh_day = 0;    wh_all = 0;
  xTaskCreatePinnedToCore(
      readOutTemp,                       /* Function to implement the task */
      "readOutTemp ",                    /* Name of the task */
      8192,                           /* Stack size in words */
      NULL,                           /* Task input parameter */
      5,                              /* Priority of the task idle ... WTD */
      NULL,                           /* Task handle. */
   0);  
      
   sensors.begin();
   numberOfDevices = sensors.getDeviceCount();  Serial.print("Found ");  Serial.print(numberOfDevices, DEC);  Serial.println(" devices.");
   for(int i=0;i<numberOfDevices; i++){
   if(sensors.getAddress(tempDeviceAddress, i)){
      Serial.print("Found device ");Serial.print(i, DEC);Serial.print(" with address: ");printAddress(tempDeviceAddress);Serial.println();
    } else {
      Serial.print("Found ghost device at ");Serial.print(i, DEC);Serial.print(" but could not detect address. Check power and cabling");
    }
  }
    // configure LED PWM for FAN_0 & FAN_1
  ledcSetup(ledChannel_0, freq, resolution);  ledcSetup(ledChannel_1, freq, resolution);
    
  // attach the channel to the GPIO to be controlled
  ledcAttachPin(FAN_PIN_0, ledChannel_0);  ledcAttachPin(FAN_PIN_1, ledChannel_1);
  dutyCycle1 = 128;  dutyCycle2 = 128;  ledcWrite(ledChannel_0, dutyCycle1);  ledcWrite(ledChannel_1, dutyCycle2);
  
   mcpwm_config_t pwm_config_0;    mcpwm_config_t pwm_config_0_1;    mcpwm_config_t pwm_config_0_2;
   mcpwm_config_t pwm_config_1;    mcpwm_config_t pwm_config_1_1;    mcpwm_config_t pwm_config_1_2;
 
   mcpwm_gpio_init(MCPWM_UNIT_1, MCPWM0A, GPIO_PWM0A_OUT);
   mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM0B, GPIO_PWM0B_OUT);
   mcpwm_gpio_init(MCPWM_UNIT_1, MCPWM1A, GPIO_PWM1A_OUT);
   mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM1B, GPIO_PWM1B_OUT);
   mcpwm_gpio_init(MCPWM_UNIT_1, MCPWM2A, GPIO_PWM2A_OUT);
   mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM2B, GPIO_PWM2B_OUT);

   mcpwm_sync_config_t  sync_ttt_0 ;
   sync_ttt_0.sync_sig = MCPWM_SELECT_TIMER0_SYNC;
   sync_ttt_0.timer_val = 600;
   sync_ttt_0.count_direction   = MCPWM_TIMER_DIRECTION_UP;

   mcpwm_sync_config_t  sync_ttt_1 ;
   sync_ttt_1.sync_sig = MCPWM_SELECT_TIMER0_SYNC;
   sync_ttt_1.timer_val = 0;
   sync_ttt_1.count_direction   = MCPWM_TIMER_DIRECTION_UP;

  
  ads0.setGain(GAIN_ONE);        // 1x gain   +/- 4.096V  1 bit = 2mV      0.125mV
  ads1.setGain(GAIN_ONE);  
  // ads.setGain(GAIN_TWO);     0.0625mV
  // ads.setGain(GAIN_FOUR);    0.03125mV
  // ads.setGain(GAIN_EIGHT);   0.015625mV
  // ads.setGain(GAIN_SIXTEEN); 0.0078125mV
  lcd.init();       lcd.backlight();    lcd.setCursor(1,0);     rtc.DSread(); 
   lcd.print( rtc.getTime() );   lcd.setCursor(1,1);   lcd.print( rtc.getDate() ); 
   delay (1111);      
  
  if (!ads0.begin(0x49)) {
    Serial.println("Failed to initialize ADS.");   lcd.init();       lcd.backlight();    lcd.setCursor(1,0);   lcd.print("1115_x49_NOTOK");
    while (1);
  }
  if (!ads1.begin(0x48)) {
    Serial.println("Failed to initialize ADS.");   lcd.init();       lcd.backlight();    lcd.setCursor(2,0);   lcd.print("1115_x48_NOTOK");
    while (1);
  }
  
  previous = millis();  now = millis();  currentTime = millis();  previousTime = millis();
  sx[8] = {'\0'} ;    sy[8] = {'\0'} ;      sz[8] = {'\0'} ;
  setup_amps = true;   mppt = false;   amps_step = 0.5;
  duty_index = 20;   amps_f = 10;   amps_s = 8;   phase = 0;
  V_panels_last = 0;   power_last = 0;   duty_high = 0;   duty_low = 0;
  max_volts_high = 0;   wh = 0;
  lcd.init();       lcd.backlight();    lcd.setCursor(1,0);   lcd.print("MPPT_______________");
  if ( setup_amps  ) 
  {
     amps_f = get_amps ();
     for (int i=0; i< amps_modulo; i++) { 
       AMPS_MAX [phase][i] = amps_f;
       AMPS [phase][i] = amps_f - 1.5;
     }
     get_mppt ();     get_batt ();     get_temp_algo ();     print_temps ();
     delay (199);     setup_amps = false;
  }

  uint32_t PWM = PWM_1;    uint32_t PWM_0 = PWM_10;
    if ( amps_f < 30.0  )    {       PWM = PWM_2; PWM_0 = PWM_20;    }
    if ( amps_f > 60.0  )    {       PWM = PWM_3; PWM_0 = PWM_30;    } 
    if ( amps_f > 80.0  )    {       PWM = PWM_4; PWM_0 = PWM_40;    } 
    pwm_config_0.frequency = PWM;    //frequency 
    pwm_config_0.cmpr_a = 50.0;       // Duty em porcentagem
    pwm_config_0.cmpr_b = 50.0;       
    pwm_config_0.counter_mode = MCPWM_UP_COUNTER;
    pwm_config_0.duty_mode = MCPWM_DUTY_MODE_0;
    
    pwm_config_0_1.frequency = PWM;    //frequency 
    pwm_config_0_1.cmpr_a = 50.0;       // Duty em porcentagem
    pwm_config_0_1.cmpr_b = 50.0;       
    pwm_config_0_1.counter_mode = MCPWM_UP_COUNTER;
    pwm_config_0_1.duty_mode = MCPWM_DUTY_MODE_0;

    pwm_config_0_2.frequency = PWM;    //frequency 
    pwm_config_0_2.cmpr_a = 50.0;       // Duty em porcentagem
    pwm_config_0_2.cmpr_b = 50.0;       
    pwm_config_0_2.counter_mode = MCPWM_UP_COUNTER;
    pwm_config_0_2.duty_mode = MCPWM_DUTY_MODE_0;

    pwm_config_1.frequency = PWM_0;    //frequency 
    pwm_config_1.cmpr_a = 0.0;       // Duty em porcentagem
    pwm_config_1.cmpr_b = 50.0;       
    pwm_config_1.counter_mode = MCPWM_UP_COUNTER;
    pwm_config_1.duty_mode = MCPWM_DUTY_MODE_1;

    pwm_config_1_2.frequency = PWM_0;    //fr equency 
    pwm_config_1_2.cmpr_a = 0.0;       // Duty em porcentagem
    pwm_config_1_2.cmpr_b = 50.0;       
    pwm_config_1_2.counter_mode = MCPWM_UP_COUNTER;
    pwm_config_1_2.duty_mode = MCPWM_DUTY_MODE_1;

    mcpwm_init(MCPWM_UNIT_0, MCPWM_TIMER_0, &pwm_config_0);   //Configure PWM0A & PWM0B with above settings
    mcpwm_init(MCPWM_UNIT_0, MCPWM_TIMER_1, &pwm_config_0_1);   //Configure PWM1A & PWM1B with above settings
    mcpwm_init(MCPWM_UNIT_0, MCPWM_TIMER_2, &pwm_config_0_2);   //Configure PWM2A & PWM2B with above settings   

    mcpwm_init(MCPWM_UNIT_1, MCPWM_TIMER_0, &pwm_config_0_2);   //Configure PWM0A & PWM0B with above settings
    mcpwm_init(MCPWM_UNIT_1, MCPWM_TIMER_1, &pwm_config_0_2);   //Configure PWM1A & PWM1B with above settings
    mcpwm_init(MCPWM_UNIT_1, MCPWM_TIMER_2, &pwm_config_0_2);   //Configure PWM2A & PWM2B with above settings   

    mcpwm_group_set_resolution( MCPWM_UNIT_0, 80000000) ;
    mcpwm_timer_set_resolution( MCPWM_UNIT_0, MCPWM_TIMER_0, 8000000);
    mcpwm_timer_set_resolution( MCPWM_UNIT_0, MCPWM_TIMER_1, 8000000);
    mcpwm_timer_set_resolution( MCPWM_UNIT_0, MCPWM_TIMER_2, 8000000);
    mcpwm_group_set_resolution( MCPWM_UNIT_1, 80000000) ;
    mcpwm_timer_set_resolution( MCPWM_UNIT_1, MCPWM_TIMER_0, 8000000);
    mcpwm_timer_set_resolution( MCPWM_UNIT_1, MCPWM_TIMER_1, 8000000);
    mcpwm_timer_set_resolution( MCPWM_UNIT_1, MCPWM_TIMER_2, 8000000);

    mcpwm_sync_configure(MCPWM_UNIT_0, MCPWM_TIMER_1, &sync_ttt_0);
    mcpwm_sync_configure(MCPWM_UNIT_0, MCPWM_TIMER_2,  &sync_ttt_1);
    mcpwm_sync_configure(MCPWM_UNIT_1, MCPWM_TIMER_1, &sync_ttt_0);
    mcpwm_sync_configure(MCPWM_UNIT_1, MCPWM_TIMER_2,  &sync_ttt_1);
   
    adc2 = ads0.readADC_SingleEnded(2); // consider median
    adc3 = ads0.readADC_SingleEnded(3); // consider median
    volts2 = ads0.computeVolts(adc2);
    volts3 = ads0.computeVolts(adc3);
    volts2 = volts2 * 18.0 / 1.037;
    volts3 = volts3 * 36.0 / 1.067;

    char x3 [10] = {' '};  char x4 [10] = {' '};    sprintf (x3, "%3.2f", volts2 );   x3[7] = {'\0'} ;    sprintf (x4, "%3.2f", volts3 );   x4[7] = {'\0'} ;
    lcd.setCursor(2,3);       lcd.print( x3 );       lcd.setCursor(12,3);      lcd.print( x4 );
    V_IN = volts3; V_OC = V_IN;
    V_OUT = volts2;

    if ((  V_OUT > MIN_V_OUT_12V) &&  ( V_OUT < MAX_V_OUT_12V )) {
       max_v_out = MAX_V_OUT_12V;
       critical_volts = CRITICAL_VOLTS;
       min_panel_volts = MIN_PANEL_VOLTS_12V;
       get_wh ();
       if (  lfp ) {
         max_volts = MAX_VOLTS_LFP; max_volts_slow = MAX_VOLTS_SLOW_LFP;max_volts_float = MAX_VOLTS_FLOAT_LFP;rebulk_volts = REBULK_VOLTS_LFP; }
       else  { max_volts = MAX_VOLTS_PB; max_volts_slow = MAX_VOLTS_SLOW_PB; max_volts_float = MAX_VOLTS_FLOAT_PB; rebulk_volts = REBULK_VOLTS_PB;         }
    }
    if ((  V_OUT > MIN_V_OUT_24V) &&  ( V_OUT < MAX_V_OUT_24V )) {
       max_v_out = MAX_V_OUT_24V;
       critical_volts = 2 * CRITICAL_VOLTS;
       min_panel_volts = MIN_PANEL_VOLTS_24V;
       get_wh ();
       if (  lfp ) { max_volts = 2 * MAX_VOLTS_LFP; max_volts_slow = 2 * MAX_VOLTS_SLOW_LFP; max_volts_float = 2 * MAX_VOLTS_FLOAT_LFP; rebulk_volts = 2 * REBULK_VOLTS_LFP;         }
       else  { max_volts = 2 * MAX_VOLTS_PB; max_volts_slow = 2 * MAX_VOLTS_SLOW_PB; max_volts_float = 2 * MAX_VOLTS_FLOAT_PB; rebulk_volts = 2 * REBULK_VOLTS_PB;    }
    }
    if ((  V_OUT > MIN_V_OUT_48V) &&  ( V_OUT < MAX_V_OUT_48V )) {
       max_v_out = MAX_V_OUT_48V;
       critical_volts = 4 * CRITICAL_VOLTS;
       min_panel_volts = MIN_PANEL_VOLTS_48V;
       get_wh ();
       if (  lfp ) { max_volts = 4 * MAX_VOLTS_LFP; max_volts_slow = 4 * MAX_VOLTS_SLOW_LFP; max_volts_float = 4 * MAX_VOLTS_FLOAT_LFP; rebulk_volts = 4 * REBULK_VOLTS_LFP;  }
       else { max_volts = 4 * MAX_VOLTS_PB; max_volts_slow = 4 * MAX_VOLTS_SLOW_PB; max_volts_float = 4 * MAX_VOLTS_FLOAT_PB; rebulk_volts = 4 * REBULK_VOLTS_PB;  }
    }
      
    if ( V_OUT < MIN_V_OUT_12V ) {  Serial.println("Failed to init MPPT.");  lcd.init();    
      lcd.backlight();  lcd.setCursor(1,0); lcd.print("V_OUT_LOW !");
      while (1);
    }
     
    if ( V_IN > MAX_V_IN ) {  Serial.println("Failed to init MPPT.");      lcd.init();    
      lcd.backlight();    lcd.setCursor(1,0);   lcd.print("V_IN_HIGH !");
      while (1);
    }
    
    if ( V_OUT > max_v_out ) {   Serial.println("Failed to init MPPT.");    lcd.init();    
      lcd.backlight();      lcd.setCursor(1,0);     lcd.print("V_OUT_HIGH !");
      while (1);
    }
    
    if ( V_IN < V_OUT ) {   Serial.println("Failed to init MPPT.");   lcd.init();    
      lcd.backlight();     lcd.setCursor(1,0);     lcd.print("V_IN_LOW !");
      while (1);
    }
    
    for (int i=0; i < duty_modulo ; i++) {   
       if ( duty_0 [i] <  (float )(V_OUT / V_IN * 96.0 )) duty_index = i;
    }     duty_index--;duty_index--;    duty_begin = duty_index;
        
    if (  duty_0 [duty_index] / 100 * V_IN > max_v_out ) {    Serial.println("Failed to init MPPT.");
      lcd.init();    lcd.backlight();   lcd.setCursor(1,0);  lcd.print("DUTY_HIGH !");
      while (1);
    } 
    
    set_lcd ();    delay (300);    read_amps (); 
    initFS();    initWiFi();    initWebSocket();
    server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(SPIFFS, "/index.html", "text/html");
  });
 
  server.serveStatic("/", SPIFFS, "/");
 // Request for the latest sensor readings
  server.on("/readings", HTTP_GET, [](AsyncWebServerRequest *request){
    String json = getSensorReadings();
    request->send(200, "application/json", json);
    json = String();
  });
  events.onConnect([](AsyncEventSourceClient *client){
    if(client->lastId()){
      Serial.printf("Client reconnected! Last message ID that it got is: %u\n", client->lastId());
    }
    client->send("hello!", NULL, millis(), 10000);
  });
  
  server.addHandler(&events);  server.begin();
  set_sd_HIGH ();    loop_interval = millis();    T_factor = 1.0000;
  
}

String getSensorReadings(){
  readings["temperature_1"] = String(tempA[0]);
  readings["temperature_2"] = String(tempA[1]);
  readings["phase_1"] =  String(tempA [2]);
  readings["phase_2"] =  String(tempA [3]);
  readings["vin_1"] =  String(tempA [9]);
  readings["vout_1"] =  String(tempA [5]);
  readings["aout_1"] =  String(tempA [4]);
  readings["wout_1"] =  String(tempA [6]);
  String jsonString = JSON.stringify(readings);
  return jsonString;
}

float read_amps (){
  for (int i=0; i < S_max ; i++) {   
    adc_avg = (int32_t )ads0.readADC_SingleEnded(0);
    A_0_a [A_0_i] = adc_avg;    A_0_i = ( A_0_i + 1 ) % S_max;      isort ( A_0_a, S_max );
    adc_avg = ( A_0_a [S_max / 2] + A_0_a [S_max / 2 + 1] ) / 2;

    adc_avg = (int32_t )ads0.readADC_SingleEnded(1);
    A_1_a [A_1_i] = adc_avg;    A_1_i = ( A_1_i + 1 ) % S_max;    isort ( A_1_a, S_max );
    adc_avg = ( A_1_a [S_max / 2] + A_1_a [S_max / 2 + 1] ) / 2;

    adc_avg = (int32_t )ads1.readADC_SingleEnded(0);
    A_2_a [A_2_i] = adc_avg;    A_2_i = ( A_2_i + 1 ) % S_max;      isort ( A_2_a, S_max );
    adc_avg = ( A_2_a [S_max / 2] + A_2_a [S_max / 2 + 1] ) / 2;     
  }
  return( 0.0 );
}

void isort (int32_t * a, int n)
{
 for (int i = 1; i < n; ++i) {
   int32_t j = a[i];   int k;
   for (k = i - 1; (k >= 0) && (j < a[k]); k--)
   {     a[k + 1] = a[k];   }
   a[k + 1] = j;
 }
}

void print_temps (){
         lcd.setCursor(1,1); lcd.print("FET_1 :");  lcd.setCursor(9,1); lcd.print( tempA [0]);
         lcd.setCursor(1,2); lcd.print("FET_2 :"); lcd.setCursor(9,2); lcd.print( tempA [1]);
}

void write_wh (){
        wh_day = floor( wh );        wh_all = wh_day;        EEPROM.writeInt(Addr_0, wh_day );
        EEPROM.commit();          EEPROM.writeLong(Addr_1, wh_all );        EEPROM.commit();          //lcd.noBacklight();
}

void get_wh (){
        wh_day = EEPROM.readInt(Addr_0 );  wh_all = EEPROM.readLong(Addr_1 );  wh = floor( wh_day );      
}

void get_batt (){
     lcd.setCursor(1,0);         lcd.print("BATT : LiFePO4___"); max_volts = MAX_VOLTS_LFP;     lfp = true;         delay (333);
     while ( setup_amps  ) 
     { int touch_up = touchRead(T6);    int touch_down = touchRead(T5);    int touch_enter = touchRead(T4);
       now = millis();       currentTime = millis();
       if (now - previous > setup_interval ) {
         previous = now;
         Serial.print(" T6 up = "); Serial.println(touch_up);  Serial.print(" T5 down = ");  Serial.println(touch_down);
         Serial.print(" T4 enter = "); Serial.println(touch_enter);   Serial.print(" amsp_f = "); Serial.println( amps_f );
       }
       if ( touch_up < 20  ) 
       {
         lcd.setCursor(1,0);  lcd.print("BATT: LiFePO_13.9 V"); max_volts = MAX_VOLTS_LFP;   lfp = true;   delay (399);
       }
       touch_up = touchRead(T6);       touch_down = touchRead(T5);
       if ( touch_up < 20  )  {  lcd.setCursor(1,0);   lcd.print("BATT: AGM_Pb_14.4 V"); max_volts = MAX_VOLTS_PB;  lfp = false;   delay (399);
       }
       delay (222);
       if ( touch_down < 20  )  break ; 
     }
}

void get_mppt (){
     lcd.setCursor(1,0);  lcd.print("ALGO : CHARGER_____"); mppt = false;    delay (333);
     while ( setup_amps  ) 
     { int touch_up = touchRead(T6);      int touch_down = touchRead(T5);      int touch_enter = touchRead(T4);
       now = millis();       currentTime = millis();
       if (now - previous > setup_interval ) {
         previous = now;
         Serial.print(" T6 up = ");  Serial.println(touch_up);  Serial.print(" T5 down = "); Serial.println(touch_down);
         Serial.print(" T4 enter = ");  Serial.println(touch_enter);  Serial.print(" amsp_f = ");  Serial.println( amps_f );
       }
       if ( touch_up < 20  ) 
       {
         lcd.setCursor(1,0);      lcd.print("ALGO : MPPT________"); mppt = true;      delay (399);
       }
       touch_up = touchRead(T6);       touch_down = touchRead(T5);
       if ( touch_up < 20  )  {  lcd.setCursor(1,0);  lcd.print("ALGO : CHARGER_____"); mppt = false;  delay (399);
       }
       delay (322);
       if ( touch_down < 20  )  break ; 
     }
}

void get_temp_algo (){
     lcd.setCursor(1,0);
     lcd.print("ALGO : OPTIMAL____"); temp_algo = false;         delay (333);
     while ( setup_amps  ) 
     { int touch_up = touchRead(T6); int touch_down = touchRead(T5);  int touch_enter = touchRead(T4);
       now = millis();   currentTime = millis();
       if (now - previous > setup_interval ) {
         previous = now;
         Serial.print(" T6 up = "); Serial.println(touch_up);   Serial.print(" T5 down = ");   Serial.println(touch_down);
         Serial.print(" T4 enter = ");  Serial.println(touch_enter);  Serial.print(" amsp_f = ");   Serial.println( amps_f );
       }
       if ( touch_up < 20  ) 
       {
         lcd.setCursor(1,0);   lcd.print("ALGO : MIN_TEMP____"); temp_algo = true;     delay (399);
       }
       touch_up = touchRead(T6);       touch_down = touchRead(T5);
       if ( touch_up < 20  ) 
       {
         lcd.setCursor(1,0);    lcd.print("ALGO : OPTIMAL____"); temp_algo = false;     delay (399);
       }
       delay (322);
       if ( touch_down < 20  )  break ; 
     }
}

float get_amps (){
     while ( setup_amps  ) 
     { int touch_up = touchRead(T6);   int touch_down = touchRead(T5);   int touch_enter = touchRead(T4);
       now = millis();       currentTime = millis();
       if (now - previous > setup_interval ) {
         previous = now;
         Serial.print(" T6 up = ");   Serial.println(touch_up);    Serial.print(" T5 down = ");    Serial.println(touch_down);
          Serial.print(" T4 enter = ");  Serial.println(touch_enter);   Serial.print(" amsp_f = ");    Serial.println( amps_f );
       }
       if ( touch_up < 20  ) 
       {
         amps_f = ( amps_f + amps_step ) ; 
       }   
       delay (99);       lcd.setCursor(1,0);       lcd.print("AMPS :_____________");       n = amps_f;
       sprintf (sn, "%f.1", n );        sn[7] = {'\0'} ;       lcd.setCursor(12,0);       lcd.print( sn );
       if ( touch_down < 20  )  break ; 
     }
    return( amps_f );               // divide sum by AVG_NUM to get average and return it
}

void loop(void)
{
  now = millis();  currentTime = millis();  now_m = micros();
  loop_interval = now_m - loop_time;  loop_time = now_m;
  adc2 = ads0.readADC_SingleEnded(2);  volts2 = ads0.computeVolts(adc2);
  volts2 = volts2 * 17.35775;
  if  (  volts2 > critical_volts   )  
  {
     set_sd_LOW (); lcd.setCursor(10,3);  lcd.print( sS_CRIT );  num_of_intervals = 0;
  }
  adc_avg = ads0.readADC_SingleEnded(0);
  A_0_a [A_0_i] = adc_avg;  A_0_i = ( A_0_i + 1 ) % S_max;  isort ( A_0_a, S_max ); adc_avg = ( A_0_a [S_max / 2] + A_0_a [S_max / 2 + 1] ) / 2;
  adc0 =  (int16_t )adc_avg;
  adc_avg = ads0.readADC_SingleEnded(1);
  A_1_a [A_1_i] = adc_avg; A_1_i = ( A_1_i + 1 ) % S_max; isort ( A_1_a, S_max ); adc_avg = ( A_1_a [S_max / 2] + A_1_a [S_max / 2 + 1] ) / 2;
  adc1 = (int16_t ) adc_avg;
  adc_avg = ads1.readADC_SingleEnded(0);
  A_2_a [A_2_i] = adc_avg; A_2_i = ( A_2_i + 1 ) % S_max;  isort ( A_2_a, S_max ); adc_avg = ( A_2_a [S_max / 2] + A_2_a [S_max / 2 + 1] ) / 2;     
  adc1_0 = (int16_t )adc_avg;
  adc3 = ads0.readADC_SingleEnded(3);
  volts0 = ads0.computeVolts(adc0)*1000.0 -volts0_off;
  volts1 = ads0.computeVolts(adc1)*1000.0 -volts1_off;
  volts1_0 = ads1.computeVolts(adc1_0)*1000.0 -volts1_0_off;
  volts2 = ads0.computeVolts(adc2);
  volts3 = ads0.computeVolts(adc3);
  volts2 = volts2 * 17.35775;  volts3 = volts3 * 33.73951;
  amps0 = T_factor * volts0 / FACTOR_IN;  amps1 = T_factor * volts1 / FACTOR_OUT_0;
  amps1_0 = T_factor * volts1_0 / FACTOR_OUT_1;  amps_1 =  amps1 +  amps1_0;
  p_in = amps0 *  volts3;  p_out_0 = amps1 *  volts2;  p_out_1 = amps1_0 *  volts2;  p_out  = p_out_0 + p_out_1;
  if ( mppt  ) 
  {
     V_panels  = volts3;     power = p_out;
     if ( power  < 1.0  ) duty_index++;
     if ( power  > power_last  ) 
     { if ( V_panels  > V_panels_last  )  {     duty_index--;  }
       else  {    duty_index++;     }    
     }
     else  
     { if ( V_panels  > V_panels_last  )  {     duty_index++;  }
       else
       {    duty_index--;       }    
     }
     V_panels_last = V_panels;     power_last =  power;
   }
   else
   {
      if ( amps_1 > AMPS [phase][amps_index]  ) { duty_index --;   }
      if ( amps_1 < AMPS [phase][amps_index]  ) { duty_index ++;   }
   }
   if ( amps_1 > AMPS_MAX [phase][amps_index]  )   {     duty_index--;  duty_index--;  }

   if ( duty_index <= 2  ) {   duty_index = 2;  }
   if ( duty_index >= duty_modulo  ) { duty_index = duty_modulo - 2; }
   
   mcpwm_set_duty(MCPWM_UNIT_1, MCPWM_TIMER_0, MCPWM_OPR_A, duty_0 [ duty_index % duty_modulo] );
   mcpwm_set_duty(MCPWM_UNIT_0, MCPWM_TIMER_0, MCPWM_OPR_B,  duty_0 [ duty_index % duty_modulo] );
   mcpwm_set_duty(MCPWM_UNIT_1, MCPWM_TIMER_1, MCPWM_OPR_A,  duty_1 [ duty_index % duty_modulo] );
   mcpwm_set_duty(MCPWM_UNIT_0, MCPWM_TIMER_1, MCPWM_OPR_B,  duty_1 [ duty_index % duty_modulo] );
   mcpwm_set_duty(MCPWM_UNIT_1, MCPWM_TIMER_2, MCPWM_OPR_A,  duty_2 [ duty_index % duty_modulo] );
   mcpwm_set_duty(MCPWM_UNIT_0, MCPWM_TIMER_2, MCPWM_OPR_B,  duty_2 [ duty_index % duty_modulo] );
   now = millis();
   if (now - previous > interval ) {
     previous = now;     num_of_intervals++;      wh = wh + p_in / 3600.0;    
     float max_temp = tempA [0].toFloat  ();     float max_temp_1 = tempA [1].toFloat  ();  
     if ( max_temp_1 > max_temp ) 
     {
       max_temp = max_temp_1;
     }     
     if  ( max_temp > 49.99 )    {     set_sd_LOW ();   }
     if  ( max_temp > 39.99 )    {     T_factor = 1.011;  }  
     if  ( ( max_temp < 39.99 ) &&  ( max_temp > 24.99 ) )    {    T_factor = 1.005;   }  
     if  ( max_temp < 24.99 )    {    T_factor = 0.985;  }
     if ( temp_algo  ) 
     {
       if ( max_temp > 26.0  ) { deltaPWM = deltaPWM + 3;  if ( deltaPWM > 220.0  )  deltaPWM = 220;      }
       dutyCycle1 = 32 + deltaPWM ;       dutyCycle2 = 32 + deltaPWM ;
       if (( max_temp < 24.0 ) &&  (max_temp > 22.0 )) 
       {
         deltaPWM = deltaPWM - 2;   if ( deltaPWM < 2  )  deltaPWM = 2;
       }
       ledcWrite(ledChannel_0, dutyCycle1);       ledcWrite(ledChannel_1, dutyCycle2);
     }
     if  ( mppt  ) 
     {
       if ( volts3 < V_OC * 0.77 )   {   duty_high ++;   }
       if ( duty_high > 10  )  { duty_index = duty_begin ;   duty_high = 0;   }
       if ( volts3 > V_OC * 0.966   )   {     duty_low ++;    }
       if ( duty_low > 10  )    {     duty_index = duty_begin;      duty_low = 0;     }
     } 
     if  (  (   num_of_intervals % 2  ) == 1 )
     {
        sprintf (x0, "%4.2f", amps0 );   x0[7] = {'\0'} ;   tempA [8] = String (amps0,2);
        sprintf (x1, "%4.2f", amps1 );   x1[7] = {'\0'} ;   tempA [2] = String (amps1,2);
        sprintf (x2, "%4.2f", amps1_0 );  x2[7] = {'\0'} ;  tempA [3] = String (amps1_0,2);
        sprintf (x3, "%3.2f", volts2 );   x3[7] = {'\0'} ;  tempA [5] = String (volts2,2);
        eta = p_out / (p_in+0.001 ) * 100.0;                tempA [7] = String (eta,2);
        lcd.setCursor(0,0);       lcd.print( x0 );       lcd.setCursor(0,1);       lcd.print( x1 );
        lcd.setCursor(0,2);       lcd.print( x2 );       lcd.setCursor(0,3);       lcd.print( x3 );
                                                            tempA [4] = String (amps_1,2);
        sprintf (x4, "%3.4f", volts3 );   x4[8] = {'\0'} ;  tempA [9] = String (volts3,2);
        sprintf (x5, "%3.1f", p_in );   x5[7] = {'\0'} ;    tempA [10] = String (p_in,2);
                                                            tempA [6] = String (p_out,2);  
                                                            tempA [11] = String ( wh,2);   
        lcd.setCursor(9,3);  lcd.print( x4 );    lcd.setCursor(18,3);   lcd.print( " V" ); lcd.setCursor(9,0);  lcd.print( x5 );
     }
     if  (  (   num_of_intervals % 4  ) == 1 )
     {   
        lcd.setCursor(9,1);      lcd.print( tempA [0]);        lcd.setCursor(9,2);      lcd.print( tempA [1]);
        lcd.setCursor(18,1);      lcd.print( " C" );
     }
     else if (  (   num_of_intervals % 4  ) == 3 )
     {
        sprintf (x8, "%3.1f", wh );   x8[8] = {'\0'} ;        sprintf (x9, "%3.3f", ( float )loop_interval/1000.0  );   x9[6] = {'\0'} ;
        lcd.setCursor(9,1);     lcd.print( x9 );        lcd.setCursor(9,3);      lcd.print( x8 ); 
        lcd.setCursor(18,3);      lcd.print( "Wh" );    lcd.setCursor(18,1);      lcd.print( "ms" );
     }
     events.send(getSensorReadings().c_str(),"new_readings" ,millis());
     if  (   num_of_intervals > 30  ) 
     { 
       if  (  (   num_of_intervals % 600  ) == 1 )   {     write_wh ();     }
       if  ( (   amps_1 < MIN_AMPS   ) &&  (   volts3 < min_panel_volts   ) )   
       {
          set_sd_LOW ();
       }
       if  ( (   !mppt   ) &&  (   volts3 < 50.11   ) )   
       {
         set_sd_LOW (); 
       }
       if  (  volts2 > max_volts   )  
       {
         max_volts_high++;
         if ( max_volts_high > 5  ) 
         {            
           max_volts_high = 0;    phase = 1;      num_of_intervals = 0;
         }
       }
       if ( (  volts2 > max_volts_slow )  && (  phase == 1 ) && (   num_of_intervals > 10  ) ) 
       {
          phase = 2;   num_of_intervals = 0;  
       }
       if ( (  volts2 > max_volts_float )  && (  phase == 2 )  && (   num_of_intervals > 10  ) )  
       {
          phase = 0;    lcd.setCursor(10,3);   lcd.print( sS_ST_BY );   set_sd_LOW ();    write_wh ();
       }
       if  ( (   amps_1 < MIN_AMPS   ) && ( volts2 < rebulk_volts ) &&  (  volts3 > min_panel_volts   ) ) 
         {
           phase = 0;           lcd.setCursor(10,3);           lcd.print( sF_BULK ); 
           V_IN = volts3; V_OC = V_IN;    V_OUT = volts2;
           for (int i=0; i < duty_modulo ; i++) {   
             if ( duty_0 [i] <  (float )(V_OUT / V_IN * 96.0 )) duty_index = i;
             }
             duty_index--;duty_index--;
             mcpwm_set_duty(MCPWM_UNIT_1, MCPWM_TIMER_0, MCPWM_OPR_A, duty_0 [ duty_index % duty_modulo] );
             mcpwm_set_duty(MCPWM_UNIT_0, MCPWM_TIMER_0, MCPWM_OPR_B,  duty_0 [ duty_index % duty_modulo] );
             mcpwm_set_duty(MCPWM_UNIT_1, MCPWM_TIMER_1, MCPWM_OPR_A,  duty_1 [ duty_index % duty_modulo] );
             mcpwm_set_duty(MCPWM_UNIT_0, MCPWM_TIMER_1, MCPWM_OPR_B,  duty_1 [ duty_index % duty_modulo] );
             mcpwm_set_duty(MCPWM_UNIT_1, MCPWM_TIMER_2, MCPWM_OPR_A,  duty_2 [ duty_index % duty_modulo] );
             mcpwm_set_duty(MCPWM_UNIT_0, MCPWM_TIMER_2, MCPWM_OPR_B,  duty_2 [ duty_index % duty_modulo] );
             digitalWrite ( SD_PIN, HIGH  );          digitalWrite ( SD_PIN2, HIGH  );
             num_of_intervals = 0;  
         }
     }
     if  (  currentTime - previousTime  > timeoutTime  ) 
     { 
        amps_index++; amps_index = amps_index % amps_modulo;        previousTime = currentTime;        currentTime = millis();
     }       
   }
   ws.cleanupClients();
}

/// made by Pavol Filek /*--*/
Este k tomu treba HTML kod na SPIFFS, ale ten sa tu vlozit neda.
DC-AC inverter REC Lion DC-AC ESP32 DIY inv. 15 GB za sekundu DIY MPPT Holder
Zjedz vsetko, co si kupil, v obchode a netreba ti tasku, auto ci chladnicku.
Uživatelský avatar
rottenkiwi
Příspěvky: 5451
Registrován: pát úno 13, 2015 2:24 pm
Lokalita: SO, SK
Bydliště: SO, SK

Re: DIY 3kW Arduino MPPT Solar Charge Controller ESP32

Příspěvek od rottenkiwi »

Viete niekto posudit, co je na tom dizajne DIY menicov dobre a co zle urobene ?

.
MPPT_DIY_01_06_23.jpg

.
DIY_INVERTER_01_06_2023.jpg
DC-AC inverter REC Lion DC-AC ESP32 DIY inv. 15 GB za sekundu DIY MPPT Holder
Zjedz vsetko, co si kupil, v obchode a netreba ti tasku, auto ci chladnicku.
lzahradil
Site Admin
Příspěvky: 921
Registrován: ned srp 12, 2012 1:18 am
Lokalita: blízko Plzně
Systémové napětí: 48V
Výkon panelů [Wp]: 5840
Kapacita baterie [kWh]: 28
Bydliště: CZ

Re: DIY 3kW Arduino MPPT Solar Charge Controller ESP32

Příspěvek od lzahradil »

Kondy u chladiče?
To jim moc na životnosti svědčit nebude
FVE 5,84kWp [Axpert 5048MK - LiFePO4 580Ah@48V (zatím) | 3x Axpert MSXE 2400W - NiCd 800Ah@24V]
Uživatelský avatar
rottenkiwi
Příspěvky: 5451
Registrován: pát úno 13, 2015 2:24 pm
Lokalita: SO, SK
Bydliště: SO, SK

Re: DIY 3kW Arduino MPPT Solar Charge Controller ESP32

Příspěvek od rottenkiwi »

Cim budu kondy dalej od BJT, FET-ov, alebo IGBT, tym viac roboty budu
musiet robit + este bude treba dalsie mensie keramiky.
A tym bude vacsie EMI a neprejde to testom a nedostane sa to k zakaznikovi.

Potom aj VIctron to ma zle, kde to ma natrieskane v strede blizko chladicov
a s tym ventilatorikom 0.22 A / 12 V toho vela neuchladi.

https://www.youtube.com/watch?v=ISMpcy-wm44

V Quattrach to maju na druhej strane dosky.
DC-AC inverter REC Lion DC-AC ESP32 DIY inv. 15 GB za sekundu DIY MPPT Holder
Zjedz vsetko, co si kupil, v obchode a netreba ti tasku, auto ci chladnicku.
FRSO
Příspěvky: 2254
Registrován: ned srp 14, 2011 10:13 pm
Lokalita: poblíž Hodonína
Systémové napětí: >48V
Výkon panelů [Wp]: 7200
Kapacita baterie [kWh]: 9

Re: DIY 3kW Arduino MPPT Solar Charge Controller ESP32

Příspěvek od FRSO »

rottenkiwi píše:Cim budu kondy dalej od BJT, FET-ov, alebo IGBT, tym viac roboty budu
musiet robit + este bude treba dalsie mensie keramiky.
A tym bude vacsie EMI a neprejde to testom a nedostane sa to k zakaznikovi.

Potom aj VIctron to ma zle, kde to ma natrieskane v strede blizko chladicov
a s tym ventilatorikom 0.22 A / 12 V toho vela neuchladi.

https://www.youtube.com/watch?v=ISMpcy-wm44

V Quattrach to maju na druhej strane dosky.
Tak dát taky ty kondíky z druhé strany :) V nových modelech victronů ofukuje ventilátor fetty, jinak by asi nevydržely trvalý výkon když nejsou na chladiči.
5,4 kWp JJZ 4deg,1,8kWp JV 24deg, do 13.8.2022 bylo 3,6 kWp, MPII 5k, Victron MPPT 250/85-TR, aku 9,45 kWh Lion 15S, BMS 200A, Smart Shunt 500A.
k 28.3.2024 8500kWh
Uživatelský avatar
rottenkiwi
Příspěvky: 5451
Registrován: pát úno 13, 2015 2:24 pm
Lokalita: SO, SK
Bydliště: SO, SK

Re: DIY 3kW Arduino MPPT Solar Charge Controller ESP32

Příspěvek od rottenkiwi »

Prace na ESP32 DIY BOOST MPPT - 2-phase pokracuju dalej
skontrolovane IN, SD , COM pre obidva IR2184.

https://youtu.be/Oq4dqsNd0P0
DC-AC inverter REC Lion DC-AC ESP32 DIY inv. 15 GB za sekundu DIY MPPT Holder
Zjedz vsetko, co si kupil, v obchode a netreba ti tasku, auto ci chladnicku.
Uživatelský avatar
rottenkiwi
Příspěvky: 5451
Registrován: pát úno 13, 2015 2:24 pm
Lokalita: SO, SK
Bydliště: SO, SK

Re: DIY 3kW Arduino MPPT Solar Charge Controller ESP32

Příspěvek od rottenkiwi »

Prva faza ESP32 DIY BOOST MPPT otestovana, idem pridat druhu.

https://youtu.be/_MS4t6KTnJQ
DC-AC inverter REC Lion DC-AC ESP32 DIY inv. 15 GB za sekundu DIY MPPT Holder
Zjedz vsetko, co si kupil, v obchode a netreba ti tasku, auto ci chladnicku.
Uživatelský avatar
rottenkiwi
Příspěvky: 5451
Registrován: pát úno 13, 2015 2:24 pm
Lokalita: SO, SK
Bydliště: SO, SK

Re: DIY 3kW Arduino MPPT Solar Charge Controller ESP32

Příspěvek od rottenkiwi »

AKo z tychto hodnot Vin a Vout a delta I in pre BOOST DC-DC spocitat DUTY_CYCLE pre PWM pre jednu fazu ?

.
boost_tab_02062023.png
.
graph_boost_02062023.png
DC-AC inverter REC Lion DC-AC ESP32 DIY inv. 15 GB za sekundu DIY MPPT Holder
Zjedz vsetko, co si kupil, v obchode a netreba ti tasku, auto ci chladnicku.
Uživatelský avatar
rottenkiwi
Příspěvky: 5451
Registrován: pát úno 13, 2015 2:24 pm
Lokalita: SO, SK
Bydliště: SO, SK

Re: DIY 3kW Arduino MPPT Solar Charge Controller ESP32

Příspěvek od rottenkiwi »

Meranie ucinnosti jednofazoveho BOOST MPPT, priblizne / UNI-T / , lebo nie su ACS758.

https://youtu.be/RCbVICU1k_E
DC-AC inverter REC Lion DC-AC ESP32 DIY inv. 15 GB za sekundu DIY MPPT Holder
Zjedz vsetko, co si kupil, v obchode a netreba ti tasku, auto ci chladnicku.
Uživatelský avatar
rottenkiwi
Příspěvky: 5451
Registrován: pát úno 13, 2015 2:24 pm
Lokalita: SO, SK
Bydliště: SO, SK

Re: DIY 3kW Arduino MPPT Solar Charge Controller ESP32

Příspěvek od rottenkiwi »

Snazim sa dostat k ucinnosti, ale neviem kde je problem, podla grafu A OUT, V IN, V OUT
je merane +- 0.003 A / V, A IN +- 0.01 A.
ale ucinnost poskakuje velmi nepresne od 97.5 do 99.5 %.

.
BOOST_eff_measure_I.png
.
BOOST_ETA_I.png
DC-AC inverter REC Lion DC-AC ESP32 DIY inv. 15 GB za sekundu DIY MPPT Holder
Zjedz vsetko, co si kupil, v obchode a netreba ti tasku, auto ci chladnicku.
Uživatelský avatar
rottenkiwi
Příspěvky: 5451
Registrován: pát úno 13, 2015 2:24 pm
Lokalita: SO, SK
Bydliště: SO, SK

Re: DIY 3kW Arduino MPPT Solar Charge Controller ESP32

Příspěvek od rottenkiwi »

6 hodin zbytocneho pajkovania pre 2 pochybne suciastky, po vymene to slapalo
OK, len este treba vycizelovat ten druhy ACS senzor.

Efficiency at LCD:

https://youtu.be/YZF76qklNRI
DC-AC inverter REC Lion DC-AC ESP32 DIY inv. 15 GB za sekundu DIY MPPT Holder
Zjedz vsetko, co si kupil, v obchode a netreba ti tasku, auto ci chladnicku.
Uživatelský avatar
rottenkiwi
Příspěvky: 5451
Registrován: pát úno 13, 2015 2:24 pm
Lokalita: SO, SK
Bydliště: SO, SK

Re: DIY 3kW Arduino MPPT Solar Charge Controller ESP32

Příspěvek od rottenkiwi »

Merania efficiencie su konzistentne, teraz len zistit, ktora z hodnot
A IN, A OUT, V IN, V OUT je najmenej presna a ci eta nedriftuje
s teplotou ADS1115 ACS758 a ACS712.

Efficiency I:

https://youtu.be/R2v3eIuC4hc

Efficiency II:

https://youtu.be/aR1ifdrt1LM

.
BOOST_efficiency_04062023.jpg
DC-AC inverter REC Lion DC-AC ESP32 DIY inv. 15 GB za sekundu DIY MPPT Holder
Zjedz vsetko, co si kupil, v obchode a netreba ti tasku, auto ci chladnicku.
Uživatelský avatar
rottenkiwi
Příspěvky: 5451
Registrován: pát úno 13, 2015 2:24 pm
Lokalita: SO, SK
Bydliště: SO, SK

Re: DIY 3kW Arduino MPPT Solar Charge Controller ESP32

Příspěvek od rottenkiwi »

Uz su tie merania ucinnosti presnejsie:


.
BOOST_efficiency_04062023_II.png
DC-AC inverter REC Lion DC-AC ESP32 DIY inv. 15 GB za sekundu DIY MPPT Holder
Zjedz vsetko, co si kupil, v obchode a netreba ti tasku, auto ci chladnicku.
Uživatelský avatar
rottenkiwi
Příspěvky: 5451
Registrován: pát úno 13, 2015 2:24 pm
Lokalita: SO, SK
Bydliště: SO, SK

Re: DIY 3kW Arduino MPPT Solar Charge Controller ESP32

Příspěvek od rottenkiwi »

BOOST MPPT / CHARGER
CONSTANT CURRENT ALGO 3.000 AMPS:

https://youtu.be/SarqM8d6rZc
DC-AC inverter REC Lion DC-AC ESP32 DIY inv. 15 GB za sekundu DIY MPPT Holder
Zjedz vsetko, co si kupil, v obchode a netreba ti tasku, auto ci chladnicku.
kodl69
Příspěvky: 7379
Registrován: sob črc 19, 2014 8:56 pm
Lokalita: severně od Brna
Systémové napětí: 48V
Výkon panelů [Wp]: 8kWp
Kapacita baterie [kWh]: 12kWh
Chci prodávat energii: NE
Chci/Mám dotaci: NE

Re: DIY 3kW Arduino MPPT Solar Charge Controller ESP32

Příspěvek od kodl69 »

nějak nevím, co tam zobrazuješ, nějak chybí popis osy x a té druhé y...
Tím, že účinnost je (U1*I1)/(U2/I2) tak se ti násobí nepřesnosti, tj pokud bys dokáazl měřit s přesností 1% proudy i napětí, tak na výkonu to bude 1.01*1.01=1.02 tj 2% a když tyhle hodnoty podělíš, tak může být nepřesnost zrovna ty 4% o který ti to skákalo. Tj nějak extra bych se s tím nezalamoval, když vlastně ani nevíš, jak ti přesnost měření ovlivNuje např vf rušení nebo nelineární průběhy napětí a proudu...
ostrov skoro 8kWp neustále ve stádiu zrodu: smartshunt(ex WBJR), MPPT150/45, MPPT 250/100(ex midnitesolar 150 clasic lite), 16S a různě P cca 340Ah Winston, MP II 5000,( ex Powerjack 8kW, ex samodomo cca 4kW). 48V DC rozvody a spotřebiče.
Uživatelský avatar
rottenkiwi
Příspěvky: 5451
Registrován: pát úno 13, 2015 2:24 pm
Lokalita: SO, SK
Bydliště: SO, SK

Re: DIY 3kW Arduino MPPT Solar Charge Controller ESP32

Příspěvek od rottenkiwi »

Vlavo je osa pre ucinnost, eta I a eta II, ta druha je korigovana na zmeny teploty.
Osa X nema popis, lebo tam nie je ziadna hodnota.

Vpravo su AMPERE IN pre BOOST DC-DC merane ACS712, lebo som tam vcera
dal ACS758 a bol chybny, tak som stravil 6 hodin hladanim chyby, akurat, ze
ACS712 nevydrzia narazove prudy 1200 A, co pri 25 *C ACS758 vydrzi.

Nemam cim skontrolovat linearitu napati a prudov, to uz treba na 0.0005 A / V.

Nemam suciastky, tak dalsiu fazu dorobim az o mesiac.
Len si musim este dostudovat BOOST converter a potom
ked to pojde, tak skusim FLYBACK.

U BOOST je moznost COUPLED a INVERSE COUPLED inductor.
Ale to by som si musel navinut sam.

TEST CC 4.000 A.

https://youtu.be/HeHPKhHYapY
DC-AC inverter REC Lion DC-AC ESP32 DIY inv. 15 GB za sekundu DIY MPPT Holder
Zjedz vsetko, co si kupil, v obchode a netreba ti tasku, auto ci chladnicku.
Uživatelský avatar
rottenkiwi
Příspěvky: 5451
Registrován: pát úno 13, 2015 2:24 pm
Lokalita: SO, SK
Bydliště: SO, SK

Re: DIY 3kW Arduino MPPT Solar Charge Controller ESP32

Příspěvek od rottenkiwi »

Otestoval som BOOST na 4.4 - 4.5 A / 41 V OUT
a dalej sa neviem dostat, lebo mam len STPS3045CW, na 45 V max.

https://youtu.be/ph0lEemPAAM
DC-AC inverter REC Lion DC-AC ESP32 DIY inv. 15 GB za sekundu DIY MPPT Holder
Zjedz vsetko, co si kupil, v obchode a netreba ti tasku, auto ci chladnicku.
Uživatelský avatar
gupa
Příspěvky: 2176
Registrován: sob pro 29, 2012 10:22 pm
Lokalita: pod Brnem
Systémové napětí: 24V

Re: DIY 3kW Arduino MPPT Solar Charge Controller ESP32

Příspěvek od gupa »

rottenkiwi píše:
Dnes sa robia GaN menice 60 A na 3 MHz to spina a ma to plochu 25 x 18 mm.
Strasna hustota energie na palec.
Myslíš modulární přelévačku něco jako toto?

https://www.youtube.com/watch?v=dAgw88cUD6c
3x2000VA-VMP-par, NiCd 24V, 22x210-320Wp, 2x85A-VMPPT
Uživatelský avatar
gupa
Příspěvky: 2176
Registrován: sob pro 29, 2012 10:22 pm
Lokalita: pod Brnem
Systémové napětí: 24V

Re: DIY 3kW Arduino MPPT Solar Charge Controller ESP32

Příspěvek od gupa »

rottenkiwi píše:Otestoval som BOOST na 4.4 - 4.5 A / 41 V OUT
a dalej sa neviem dostat, lebo mam len STPS3045CW, na 45 V max.
Na deskách v plazmové televizi jsou RF2001 na 200V 20A.
3x2000VA-VMP-par, NiCd 24V, 22x210-320Wp, 2x85A-VMPPT
Uživatelský avatar
rottenkiwi
Příspěvky: 5451
Registrován: pát úno 13, 2015 2:24 pm
Lokalita: SO, SK
Bydliště: SO, SK

Re: DIY 3kW Arduino MPPT Solar Charge Controller ESP32

Příspěvek od rottenkiwi »

CO vsetko potrebujem na takyto Double Pulse Test , ak mam FET-y 0 - 600 V
a frekvenciu 10 kHz - 150 kHz ?

.
double_pulser_I.png
.
double_pulse_II.png
DC-AC inverter REC Lion DC-AC ESP32 DIY inv. 15 GB za sekundu DIY MPPT Holder
Zjedz vsetko, co si kupil, v obchode a netreba ti tasku, auto ci chladnicku.

  • Podobná témata
    Odpovědi
    Zobrazení
    Poslední příspěvek