Parcourir la source

Подправил под новые условия.

Vladimir N. Shilov il y a 8 ans
Parent
commit
1153666a01
3 fichiers modifiés avec 98 ajouts et 52 suppressions
  1. 10 6
      Makefile
  2. 47 0
      ReadMe.txt
  3. 41 46
      lib/adc.c

+ 10 - 6
Makefile

@@ -44,6 +44,12 @@ LIST_DIR = $(OUT_DIR)/List
 CODE_MODEL = small
 DATA_MODEL = medium
 
+STACK_SIZE = 0x100
+HEAP_SIZE = 0x000
+
+DEFINES = -D USE_STDPERIPH_DRIVER
+DEFINES+ = -D USE_RTOS
+
 # Application object files
 APP_OBJECTS = $(notdir $(patsubst %.c,%.o,$(wildcard $(APP_SRC)/*.c)))
 
@@ -96,10 +102,9 @@ vpath %.elf .\$(OUT_DIR)
 vpath %.hex .\$(OUT_DIR)
 
 # Compiler/Assembler flags
-CFLAGS = -e -Oh -D USE_STDPERIPH_DRIVER -D USE_RTOS
+CFLAGS = -e -Oh $(DEFINES) -D NDEBUG -D $(PART)
 CFLAGS += --code_model $(CODE_MODEL) --data_model $(DATA_MODEL)
 CFLAGS += --dlib_config "$(EWSTM8_DIR)\lib\$(LIB_MODEL)"
-CFLAGS += -D NDEBUG -D $(PART)
 CFLAGS += -lCN $(LIST_DIR) -lBN $(LIST_DIR)
 CFLAGS += --diag_suppress Pa050
 
@@ -118,8 +123,7 @@ DBG_ASMFLAGS += --code_model $(CODE_MODEL) --data_model $(DATA_MODEL)
 LINKFLAGS = --redirect _Printf=_PrintfTinyNoMb
 LINKFLAGS += --redirect _Scanf=_ScanfSmallNoMb
 LINKFLAGS += --config "$(EWSTM8_DIR)\config\$(ICF)"
-LINKFLAGS += --config_def _CSTACK_SIZE=0x100
-LINKFLAGS += --config_def _HEAP_SIZE=0x000
+LINKFLAGS += --config_def _CSTACK_SIZE=$(STACK_SIZE) --config_def _HEAP_SIZE=$(HEAP_SIZE)
 LINKFLAGS += --map $(OUT_DIR)
 LINKFLAGS += --entry __iar_program_start
 LINKFLAGS += --merge_duplicate_sections
@@ -127,8 +131,8 @@ LINKFLAGS += --strip
 LINKFLAGS += -f "$(EWSTM8_DIR)\config\math_small.xcl"
 
 DBG_LINKFLAGS = --redirect _Printf=_PrintfTinyNoMb --redirect _Scanf=_ScanfSmallNoMb
-DBG_LINKFLAGS += --config "$(EWSTM8_DIR)\config\$(ICF)" --config_def
-DBG_LINKFLAGS += _CSTACK_SIZE=0x100 --config_def _HEAP_SIZE=0x000
+DBG_LINKFLAGS += --config "$(EWSTM8_DIR)\config\$(ICF)"
+DBG_LINKFLAGS += --config_def _CSTACK_SIZE=$(STACK_SIZE) --config_def _HEAP_SIZE=$(HEAP_SIZE)
 DBG_LINKFLAGS += --entry __iar_program_start
 
 

+ 47 - 0
ReadMe.txt

@@ -281,3 +281,50 @@ Factory_VREFINT у меня == 0x7E, т.е. полное значение 0x067E
 
 Сделал чтобы напряжение и ток показывало не среднее за секунду, а последнее за 100 мсек.
 Если будет сильно быстро, можно будет брать последние 2-4 результата.
+
+---
+2016.12.02
+
+Что-то я вообще забыл, для чего я это всё начинал.
+Если у меня получится переделать FSP235 в БП 30В 10А, то можно будет из этого
+*-метра сделать что-то более полезное. Но для этого нужно прикрутить энкодер и
+два ШИМ-выхода для управления БП. Плюс ещё рэле, или два. Попробуем.
+ - есть два выхода Т2 -- 1 и 2. на них однозначно шим.
+ - есть два входа АЦП, если смогу к ним припаяться -- туда можно прицепить
+   переменные резисторы для регулировки напряжения и тока. это будет удобнее и
+   проще, чем через энкодер.
+ - реле можно вместо светодиодов, но сначала придумать зачем они нужны.
+ - энкодер, программно, можно на ПА2, ПА3 а кнопку на ПД0.
+
+По регулировке
+ - если выбрать шаг регулирования в 10 мВ и 10 мА, то для тока нужно 10 бит, а
+для напряжения -- 12 бит.
+ - если ставить энкодер, то переменники не нужны.
+
+По измерениям
+ - для экономии ОЗУ, можно в прерывании от ПДП суммировать в 32-бит
+аккумуляторы, а в конце цикла доводить до 16-бит и скидывать в медленный
+буфер.
+
+По функционалу:
+ - для контролируемого разряда нужно ставить реле от клемм на нагрузку.
+   вольтметр тогда нужно подключать на клемы. бп тогда нужно или выключать,
+   или ставить ещё реле. можно поставить реле средними на выход, одни контакты
+   к бп, другие контакты на внешнюю нагрузку. но как-то всё это мутно.
+ - по уму, нужно отображать уставку и факт, но нет столько индикаторов.
+ - вообще что-то не вижу особого смысла во всех этих заморочках.
+
+---
+2016.12.09
+
+Итак, БП почти работает.
+Входной делитель по напряжению -- оставляем 10 и 1 кОм 0.1% -- 36.3В/8.9мВ
+Амперметр -- шунт с БП 0.01 Ом, при 10А даст 0.1В, в усилителе шунта меняем
+резисторы 20кОм 0.1% на 33кОм 1%, получаем Ку=33. Если не менять -- получим
+максимальный предел по току в 16.5А, шаг измерения ~4 мА -- пока можно и
+оставить. С резистором 38.3 кОм получим ток 8.6А с шагом в ~2 мА, с резистором
+на 30 кОм -- 11А и ~2.7 мА.
+
+Добавил простенькую фильтрацию сразу после DMA.
+Вернул "оверсемплинг". Не уверен, правильно ли я насчитал коэфф...
+Нужно будет добавить коррекцию "0" с выхода ОУ.

+ 41 - 46
lib/adc.c

@@ -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;