|
@@ -29,9 +29,12 @@
|
|
|
|
|
|
#define ADC_REF 3300
|
|
|
#define ADC_DIV 4095
|
|
|
-#define ADC_ODIV 32768
|
|
|
+#define ADC_ODIV 32760
|
|
|
+#define ADC_DIV_H 2048
|
|
|
+#define ADC_ODIV_H 16380
|
|
|
#define ADC_VOLT_K 11
|
|
|
#define ADC_CURR_K 20
|
|
|
+#define ADC_CURR_SH 100
|
|
|
|
|
|
// (Частота МК (16 МHz) / Предделитель таймера (8) * Нужное время в секундах (0.0015625)) - 1
|
|
|
#define TIM_PERIOD ((uint16_t)3128)
|
|
@@ -173,9 +176,27 @@ static void ADC_ConfigTIM2(void)
|
|
|
INTERRUPT_HANDLER(DMA1_CHANNEL0_1_IRQHandler,2)
|
|
|
{
|
|
|
static uint8_t idx = 0;
|
|
|
-
|
|
|
- VoltageFastBuffer[idx] = ADC_Buffer[0];
|
|
|
- CurrentFastBuffer[idx] = ADC_Buffer[1];
|
|
|
+ static uint16_t va1=0, va2=0, ca1=0, ca2=0;
|
|
|
+
|
|
|
+ if (ADC_Buffer[0] < va1 && ADC_Buffer[0] < va2) {
|
|
|
+ VoltageFastBuffer[idx] = va1;
|
|
|
+ } else if (ADC_Buffer[0] > va1 && ADC_Buffer[0] > va2) {
|
|
|
+ VoltageFastBuffer[idx] = va1;
|
|
|
+ } else {
|
|
|
+ VoltageFastBuffer[idx] = ADC_Buffer[0];
|
|
|
+ }
|
|
|
+ va2 = va1;
|
|
|
+ va1 = ADC_Buffer[0];
|
|
|
+
|
|
|
+ if (ADC_Buffer[1] < ca1 && ADC_Buffer[1] < ca2) {
|
|
|
+ CurrentFastBuffer[idx] = ca1;
|
|
|
+ } else if (ADC_Buffer[1] > ca1 && ADC_Buffer[1] > ca2) {
|
|
|
+ CurrentFastBuffer[idx] = ca1;
|
|
|
+ } else {
|
|
|
+ CurrentFastBuffer[idx] = ADC_Buffer[1];
|
|
|
+ }
|
|
|
+ ca2 = ca1;
|
|
|
+ ca1 = ADC_Buffer[1];
|
|
|
|
|
|
idx ++;
|
|
|
if(idx >= FAST_BUFFER_SIZE) {
|
|
@@ -206,53 +227,27 @@ uint16_t * ADC_GetValues(void) {
|
|
|
/* Попытка оверсемплинга, чтобы сделать шаг ~1мВ
|
|
|
делим на 8, умножаем на опорное напряжение, умножаем на входной делитель
|
|
|
и делим на (12 бит АЦП * 8). */
|
|
|
-#ifdef ADC_USE_V_OVERS
|
|
|
- volt >>= 3;
|
|
|
+ volt += 4; // для округления
|
|
|
+ volt /= 8; // усредняем
|
|
|
volt *= ADC_REF;
|
|
|
volt *= ADC_VOLT_K;
|
|
|
+ volt += ADC_ODIV_H;
|
|
|
volt /= ADC_ODIV;
|
|
|
-#else
|
|
|
- volt += 32; // для округления
|
|
|
- volt >>= 6; // делим
|
|
|
- volt *= ADC_REF;
|
|
|
- volt *= ADC_VOLT_K;
|
|
|
- volt /= ADC_DIV;
|
|
|
-#endif // ADC_USE_V_OVERS
|
|
|
-
|
|
|
- /* получаем среднее по току, затем фильтруем */
|
|
|
- curr += 32;
|
|
|
- curr >>= 6;
|
|
|
-#ifdef ADC_USE_C_FILTR
|
|
|
- uint16_t middle;
|
|
|
- middle = curr + 8;
|
|
|
- middle &= 0xFFF0;
|
|
|
- curr = 0;
|
|
|
- uint8_t cnt = 0;
|
|
|
- uint16_t tmp;
|
|
|
- for(i=1; i<FAST_BUFFER_SIZE; i+=2){
|
|
|
- tmp = CurrentFastBuffer[i];
|
|
|
- tmp += 8;
|
|
|
- tmp &= 0xFFF0;
|
|
|
- if(tmp == middle){
|
|
|
- cnt ++;
|
|
|
- curr += CurrentFastBuffer[i];
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /* Усредняем преобразованный результат
|
|
|
- и переводим код АЦП в милиамперы */
|
|
|
- if(cnt > 0){
|
|
|
- curr /= cnt;
|
|
|
- } else {
|
|
|
- curr = middle;
|
|
|
- }
|
|
|
-#endif // ADC_USE_C_FILTR
|
|
|
|
|
|
+ curr += 4;
|
|
|
+ curr /= 8;
|
|
|
curr *= ADC_REF;
|
|
|
- curr /= ADC_DIV;
|
|
|
-
|
|
|
- shunt_volt = curr / ADC_CURR_K;
|
|
|
- volt -= shunt_volt;
|
|
|
+ curr += (ADC_CURR_K/2); // для округления
|
|
|
+ curr /= ADC_CURR_K; // делим на Ку усилителя шунта
|
|
|
+ curr *= ADC_CURR_SH; // делим вольты на омы шунта
|
|
|
+ curr += ADC_ODIV_H; // для округления
|
|
|
+ curr /= ADC_ODIV;// и получили ток в мА
|
|
|
+
|
|
|
+ /* так как шунт стоит в разрве земли до выхода из БП
|
|
|
+ компенсируем падение напряжения на нём. */
|
|
|
+ shunt_volt = curr + (ADC_CURR_K/2);
|
|
|
+ shunt_volt /= ADC_CURR_K; // мВ на входе ОУ
|
|
|
+ volt -= shunt_volt; // получили напряжение на клемах
|
|
|
|
|
|
avgVal[0] = (uint16_t)volt;
|
|
|
avgVal[1] = (uint16_t)curr;
|