Index: ctrl/firmware/Main/CubeMX/Core/Inc/adc.h
===================================================================
--- ctrl/firmware/Main/CubeMX/Core/Inc/adc.h	(revision 108)
+++ ctrl/firmware/Main/CubeMX/Core/Inc/adc.h	(revision 109)
@@ -41,11 +41,11 @@
 /* USER CODE BEGIN Private defines */
 
-#define ADC2_CHANNELS	(2U)
-#define ADC3_CHANNELS	(4U)
-#define VREF			(3000U)
+#define ADC2_CHANNELS_NUM	(2U)
+#define ADC3_CHANNELS_NUM	(4U)
+#define VREF				(3000U)
 
 typedef union ADC2_data_t
 {
-	uint16_t Raw[ADC2_CHANNELS];
+	uint16_t Raw[ADC2_CHANNELS_NUM];
 	struct
 	{
@@ -57,5 +57,5 @@
 typedef union ADC3_data_t
 {
-	uint16_t Raw[ADC3_CHANNELS];
+	uint16_t Raw[ADC3_CHANNELS_NUM];
 	struct
 	{
Index: ctrl/firmware/Main/CubeMX/Core/Src/adc.c
===================================================================
--- ctrl/firmware/Main/CubeMX/Core/Src/adc.c	(revision 108)
+++ ctrl/firmware/Main/CubeMX/Core/Src/adc.c	(revision 109)
@@ -23,4 +23,6 @@
 /* USER CODE BEGIN 0 */
 
+#include <string.h>
+
 volatile ADC2_data_t ADC2Data __attribute__((section(".AXI_RAM_4_DMA")));
 volatile ADC3_data_t ADC3Data __attribute__((section(".BKP_RAM_4_DMA")));
@@ -52,5 +54,5 @@
   */
   hadc2.Instance = ADC2;
-  hadc2.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV256;
+  hadc2.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV2;
   hadc2.Init.Resolution = ADC_RESOLUTION_16B;
   hadc2.Init.ScanConvMode = ADC_SCAN_ENABLE;
@@ -66,6 +68,6 @@
   hadc2.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;
   hadc2.Init.OversamplingMode = ENABLE;
-  hadc2.Init.Oversampling.Ratio = 1024;
-  hadc2.Init.Oversampling.RightBitShift = ADC_RIGHTBITSHIFT_10;
+  hadc2.Init.Oversampling.Ratio = 64;
+  hadc2.Init.Oversampling.RightBitShift = ADC_RIGHTBITSHIFT_6;
   hadc2.Init.Oversampling.TriggeredMode = ADC_TRIGGEREDMODE_SINGLE_TRIGGER;
   hadc2.Init.Oversampling.OversamplingStopReset = ADC_REGOVERSAMPLING_CONTINUED_MODE;
@@ -93,4 +95,5 @@
   sConfig.Channel = ADC_CHANNEL_4;
   sConfig.Rank = ADC_REGULAR_RANK_2;
+  sConfig.Offset = 0;
   if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)
   {
@@ -104,13 +107,29 @@
   HAL_Delay(100U);
 
-  //if (HAL_OK != HAL_ADC_Start(&hadc3)) Error_Handler();
-  if (HAL_OK != HAL_ADC_Start_DMA(&hadc2, (uint32_t*)&ADC2Data, ADC2_CHANNELS)) Error_Handler();
-  __HAL_DMA_DISABLE_IT(&hdma_adc2, DMA_IT_HT);
-
-  uint16_t offset = 0;
-  for (int i = 0; i < 100; i++)
-  {
-
-  }
+  uint32_t offset[2] = { 0U };
+  const uint32_t max_samples = 16U;
+  // Starting DMA converstion
+  if (HAL_OK != HAL_ADC_Start_DMA(&hadc2, (uint32_t*)&ADC2Data, ADC2_CHANNELS_NUM)) Error_Handler();
+   // Disabling interrupts, because we don't need it during offset calculation
+  __HAL_DMA_DISABLE_IT(&hdma_adc2, DMA_IT_HT | DMA_IT_TC);
+  for (uint32_t i = 0U; i < max_samples; i++)
+  {	  // Waiting for conversion to finish
+	  while(!__HAL_DMA_GET_FLAG(&hdma_adc2, DMA_FLAG_TCIF1_5));
+	  // Reading ADC2 value
+	  offset[0] += ADC2Data.Raw[0];
+	  offset[1] += ADC2Data.Raw[1];
+	  __HAL_DMA_CLEAR_FLAG(&hdma_adc2, DMA_FLAG_TCIF1_5);
+  }
+
+  printf("ADC2 offset[0] = %u, offset[1] = %u\n", offset[0] / max_samples, offset[1] / max_samples);
+
+  if (HAL_OK == HAL_ADC_Stop_DMA(&hadc2))
+  {
+	  LL_ADC_SetOffset(hadc2.Instance, LL_ADC_OFFSET_1, LL_ADC_CHANNEL_3, (offset[0]/max_samples) << 6U);
+	  LL_ADC_SetOffset(hadc2.Instance, LL_ADC_OFFSET_2, LL_ADC_CHANNEL_4, (offset[1]/max_samples) << 6U);
+  }
+
+  if (HAL_OK != HAL_ADC_Start_DMA(&hadc2, (uint32_t*)&ADC2Data, ADC2_CHANNELS_NUM)) Error_Handler();
+  __HAL_DMA_DISABLE_IT(&hdma_adc2, DMA_IT_HT /*| DMA_IT_TC*/); // Disabling interrupts, because we don't need it
 
 
@@ -209,5 +228,5 @@
 
   //if (HAL_OK != HAL_ADC_Start(&hadc3)) Error_Handler();
-  if (HAL_OK != HAL_ADC_Start_DMA(&hadc3, (uint32_t*)&ADC3Data, ADC3_CHANNELS)) Error_Handler();
+  if (HAL_OK != HAL_ADC_Start_DMA(&hadc3, (uint32_t*)&ADC3Data, ADC3_CHANNELS_NUM)) Error_Handler();
   __HAL_DMA_DISABLE_IT(&hdma_adc3, DMA_IT_HT);
 
Index: ctrl/firmware/Main/CubeMX/Core/Src/freertos.c
===================================================================
--- ctrl/firmware/Main/CubeMX/Core/Src/freertos.c	(revision 108)
+++ ctrl/firmware/Main/CubeMX/Core/Src/freertos.c	(revision 109)
@@ -58,5 +58,5 @@
 #define BME_TASK_STACK_DEPTH_WORDS					(256U)
 #define GUI_TASK_STACK_DEPTH_WORDS					(2048U)
-#define FAN_TASK_STACK_DEPTH_WORDS					(128U)
+#define FAN_TASK_STACK_DEPTH_WORDS					(256U)
 
 /* USER CODE END PD */
Index: ctrl/firmware/Main/CubeMX/Core/Src/main.c
===================================================================
--- ctrl/firmware/Main/CubeMX/Core/Src/main.c	(revision 108)
+++ ctrl/firmware/Main/CubeMX/Core/Src/main.c	(revision 109)
@@ -374,4 +374,5 @@
 {
   /* USER CODE BEGIN Error_Handler_Debug */
+  printf("ERROR!!!\n");
   /* User can add his own implementation to report the HAL error return state */
   __disable_irq();
Index: ctrl/firmware/Main/CubeMX/Core/Src/stm32h7xx_it.c
===================================================================
--- ctrl/firmware/Main/CubeMX/Core/Src/stm32h7xx_it.c	(revision 108)
+++ ctrl/firmware/Main/CubeMX/Core/Src/stm32h7xx_it.c	(revision 109)
@@ -24,7 +24,9 @@
 /* USER CODE BEGIN Includes */
 
+#include <stdio.h>
+
 #include "FreeRTOS.h"
 #include "modbus.h"
-//#include "semphr.h"
+#include "adc.h"
 
 /* USER CODE END Includes */
@@ -468,4 +470,26 @@
 
 //------------------------------------------------------------------------------
+
+static volatile int64_t charge_tmp;
+static volatile int64_t load_tmp;
+static volatile float charge_i;
+static volatile float load_i;
+
+void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
+{
+	//extern ADC2_data_t ADC2Data;
+
+	if (hadc->Instance == ADC2)
+	{
+		HAL_GPIO_WritePin(RX1_LED_GPIO_Port, RX1_LED_Pin, GPIO_PIN_SET);
+		charge_tmp = (((int64_t)ADC2Data.Name.charge_strom * ((int64_t)VREF) * 1000LL) / ((int64_t)0xFFFF)) / 50LL;
+		load_tmp = (((int64_t)ADC2Data.Name.eload_strom * ((int64_t)VREF) * 1000LL) / ((int64_t)0xFFFF)) / 50LL;
+		charge_i = (float)charge_tmp / 500LL;
+		load_i = (float)load_tmp / 500LL;
+		//printf("\t\t\t%5.2fA, %5.2fA\n", charge_i, load_i);
+		HAL_GPIO_WritePin(RX1_LED_GPIO_Port, RX1_LED_Pin, GPIO_PIN_RESET);
+	}
+}
+
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
Index: ctrl/firmware/Main/CubeMX/charger.ioc
===================================================================
--- ctrl/firmware/Main/CubeMX/charger.ioc	(revision 108)
+++ ctrl/firmware/Main/CubeMX/charger.ioc	(revision 109)
@@ -6,7 +6,8 @@
 ADC2.ConversionDataManagement=ADC_CONVERSIONDATA_DMA_CIRCULAR
 ADC2.EOCSelection=ADC_EOC_SEQ_CONV
-ADC2.IPParameters=Rank-0\#ChannelRegularConversion,Channel-0\#ChannelRegularConversion,SingleDiff-0\#ChannelRegularConversion,SamplingTime-0\#ChannelRegularConversion,OffsetNumber-0\#ChannelRegularConversion,OffsetSignedSaturation-0\#ChannelRegularConversion,NbrOfConversionFlag,NbrOfConversion,Rank-2\#ChannelRegularConversion,Channel-2\#ChannelRegularConversion,SingleDiff-2\#ChannelRegularConversion,SamplingTime-2\#ChannelRegularConversion,OffsetNumber-2\#ChannelRegularConversion,OffsetSignedSaturation-2\#ChannelRegularConversion,ContinuousConvMode,EOCSelection,Overrun,ConversionDataManagement,OversamplingMode,RightBitShift,Ratio,ClockPrescaler
+ADC2.IPParameters=Rank-0\#ChannelRegularConversion,Channel-0\#ChannelRegularConversion,SingleDiff-0\#ChannelRegularConversion,SamplingTime-0\#ChannelRegularConversion,OffsetNumber-0\#ChannelRegularConversion,OffsetSignedSaturation-0\#ChannelRegularConversion,NbrOfConversionFlag,NbrOfConversion,Rank-2\#ChannelRegularConversion,Channel-2\#ChannelRegularConversion,SingleDiff-2\#ChannelRegularConversion,SamplingTime-2\#ChannelRegularConversion,OffsetNumber-2\#ChannelRegularConversion,OffsetSignedSaturation-2\#ChannelRegularConversion,ContinuousConvMode,EOCSelection,Overrun,ConversionDataManagement,OversamplingMode,RightBitShift,Ratio,ClockPrescaler,Offset-0\#ChannelRegularConversion
 ADC2.NbrOfConversion=2
 ADC2.NbrOfConversionFlag=1
+ADC2.Offset-0\#ChannelRegularConversion=32767
 ADC2.OffsetNumber-0\#ChannelRegularConversion=ADC_OFFSET_NONE
 ADC2.OffsetNumber-2\#ChannelRegularConversion=ADC_OFFSET_NONE
@@ -437,6 +438,6 @@
 Mcu.UserConstants=
 Mcu.UserName=STM32H723ZETx
-MxCube.Version=6.13.0
-MxDb.Version=DB.6.0.130
+MxCube.Version=6.14.0
+MxDb.Version=DB.6.0.140
 NVIC.BDMA_Channel0_IRQn=true\:5\:0\:false\:false\:true\:true\:false\:true\:true
 NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
@@ -720,4 +721,5 @@
 ProjectManager.AskForMigrate=true
 ProjectManager.BackupPrevious=false
+ProjectManager.CompilerLinker=GCC
 ProjectManager.CompilerOptimize=6
 ProjectManager.ComputerToolchain=false
@@ -792,5 +794,5 @@
 RCC.I2C123Freq_Value=64000000
 RCC.I2C4Freq_Value=100000000
-RCC.IPParameters=ADCCLockSelection,ADCFreq_Value,AHB12Freq_Value,AHB4Freq_Value,APB1Freq_Value,APB2Freq_Value,APB3Freq_Value,APB4Freq_Value,AXIClockFreq_Value,CECFreq_Value,CKPERFreq_Value,CortexFreq_Value,CpuClockFreq_Value,D1CPREFreq_Value,DFSDMACLkFreq_Value,DFSDMFreq_Value,DIVM1,DIVM2,DIVM3,DIVN1,DIVN2,DIVN3,DIVP1Freq_Value,DIVP2Freq_Value,DIVP3Freq_Value,DIVQ1Freq_Value,DIVQ2,DIVQ2Freq_Value,DIVQ3,DIVQ3Freq_Value,DIVR1Freq_Value,DIVR2,DIVR2Freq_Value,DIVR3,DIVR3Freq_Value,FDCANFreq_Value,FMCFreq_Value,FamilyName,HCLK3ClockFreq_Value,HCLKFreq_Value,I2C123CLockSelection,I2C123Freq_Value,I2C4Freq_Value,LPTIM1Freq_Value,LPTIM2Freq_Value,LPTIM345Freq_Value,LPUART1Freq_Value,LTDCFreq_Value,MCO1PinFreq_Value,MCO2PinFreq_Value,PLL2FRACN,PLL2_VCI_Range-AdvancedSettings,PLLFRACN,PLLSourceVirtual,QSPIFreq_Value,RNGFreq_Value,RTCClockSelection,RTCFreq_Value,SAI1Freq_Value,SAI4AFreq_Value,SAI4BFreq_Value,SDMMC1CLockSelection,SDMMCFreq_Value,SPDIFRXFreq_Value,SPI123CLockSelection,SPI123Freq_Value,SPI45Freq_Value,SPI6Freq_Value,SWPMI1Freq_Value,SYSCLKFreq_VALUE,SYSCLKSource,Spi45ClockSelection,Tim1OutputFreq_Value,Tim2OutputFreq_Value,TraceFreq_Value,USART16CLockSelection,USART16Freq_Value,USART234578CLockSelection,USART234578Freq_Value,USBFreq_Value,VCO1OutputFreq_Value,VCO2OutputFreq_Value,VCO3OutputFreq_Value,VCOInput1Freq_Value,VCOInput2Freq_Value,VCOInput3Freq_Value
+RCC.IPParameters=ADCCLockSelection,ADCFreq_Value,AHB12Freq_Value,AHB4Freq_Value,APB1Freq_Value,APB2Freq_Value,APB3Freq_Value,APB4Freq_Value,AXIClockFreq_Value,CECFreq_Value,CKPERFreq_Value,CortexFreq_Value,CpuClockFreq_Value,D1CPREFreq_Value,DFSDMACLkFreq_Value,DFSDMFreq_Value,DIVM1,DIVM2,DIVM3,DIVN1,DIVN2,DIVN3,DIVP1Freq_Value,DIVP2Freq_Value,DIVP3Freq_Value,DIVQ1Freq_Value,DIVQ2,DIVQ2Freq_Value,DIVQ3,DIVQ3Freq_Value,DIVR1Freq_Value,DIVR2,DIVR2Freq_Value,DIVR3,DIVR3Freq_Value,FDCANFreq_Value,FMCFreq_Value,FamilyName,HCLK3ClockFreq_Value,HCLKFreq_Value,I2C123CLockSelection,I2C123Freq_Value,I2C4Freq_Value,LPTIM1Freq_Value,LPTIM2Freq_Value,LPTIM345Freq_Value,LPUART1Freq_Value,LTDCFreq_Value,MCO1PinFreq_Value,MCO2PinFreq_Value,PLL2FRACN,PLL2_VCI_Range-AdvancedSettings,PLLFRACN,PLLSourceVirtual,PWR_Regulator_Voltage_Scale,QSPIFreq_Value,RNGFreq_Value,RTCClockSelection,RTCFreq_Value,SAI1Freq_Value,SAI4AFreq_Value,SAI4BFreq_Value,SDMMC1CLockSelection,SDMMCFreq_Value,SPDIFRXFreq_Value,SPI123CLockSelection,SPI123Freq_Value,SPI45Freq_Value,SPI6Freq_Value,SWPMI1Freq_Value,SYSCLKFreq_VALUE,SYSCLKSource,Spi45ClockSelection,Tim1OutputFreq_Value,Tim2OutputFreq_Value,TraceFreq_Value,USART16CLockSelection,USART16Freq_Value,USART234578CLockSelection,USART234578Freq_Value,USBFreq_Value,VCO1OutputFreq_Value,VCO2OutputFreq_Value,VCO3OutputFreq_Value,VCOInput1Freq_Value,VCOInput2Freq_Value,VCOInput3Freq_Value
 RCC.LPTIM1Freq_Value=100000000
 RCC.LPTIM2Freq_Value=100000000
@@ -804,4 +806,5 @@
 RCC.PLLFRACN=0
 RCC.PLLSourceVirtual=RCC_PLLSOURCE_HSE
+RCC.PWR_Regulator_Voltage_Scale=PWR_REGULATOR_VOLTAGE_SCALE0
 RCC.QSPIFreq_Value=100000000
 RCC.RNGFreq_Value=48000000
