Parcourir la source

Переделал буфер АЦП, и быстрый буфер.

Vladimir N. Shilov il y a 9 ans
Parent
commit
9ed0f402ce
6 fichiers modifiés avec 120 ajouts et 43 suppressions
  1. 1 0
      .gitignore
  2. 44 0
      ReadMe.txt
  3. 12 9
      lib/adc.c
  4. 10 7
      lib/adc.h
  5. 38 8
      src/main.c
  6. 15 19
      src/stm8l15x_it.c

+ 1 - 0
.gitignore

@@ -3,3 +3,4 @@ Out
 *.layout
 *.save
 Debug
+Result.log

+ 44 - 0
ReadMe.txt

@@ -127,3 +127,47 @@ Factory_VREFINT у меня == 0x7E, т.е. полное значение 0x067E
 тригером от Т2. Настройка Т2 пока заклинанием -- понимания нету.
 На очереди -- усреднение результатов, вычисление напряжения питания через 
 опорное напряжение.
+
+Пока не сильно нравится -- завышает напругу, скачут показания.
+Мерял аккум - 4.219 В, мой точный показывал 4.207, DT-шка - 4.17-4.18 В.
+Канал внутреннего опорного напряжения показывает 1.219 - 1.223 В
+По каналу тока висит 4 мВ, мой 5-ти разрядный вольтметр показывал 3 мВ на 
+выводе.
+По каналу напряжения постоянно висит 17-26-35 мВ, вольтметр показывет 
+чёткий "0". Замыкание на землю ничего не даёт. Хз, что это такое.
+Если от итогового напряжения вычесть эти миливольты, то результат будет 
+больше похож на правду.
+
+На тему усреднения, такая идея:
+ - в прерывании ПДП данные перекладываются в быстрый кольцевой буфер
+   на 10 значений. Можно мерять чаще, хоть каждую 1 мс.
+ - в основном теле каждые 100 мсек отрабатывает процедура, которая 
+   усредняет данные из быстрого буфера, отбрасывая слишком мелкие/большие,
+   и перекладывает в медленный кольцевой буфер. Тут же делать пересчёты 
+   значений из кода АЦП в реальные значения.
+ - ещё одна процедура раз в секунду усредняет данные из медленного буфера 
+   и сохраняем в текущий секундный результат. Здесь же вычеслять мощности,
+   ёмкости, время и т.д.
+
+---
+2016.03.25
+
+Причесал настройку Т2.
+
+Считаем среднее, зануляем младшие 4 бита, и потом сравниваем каждое 
+значение со сброшенными 4-мя младшими битами:
+  middle &= 0xFFF0;
+  if ((value & 0xFFF0) == middle) { ... }
+таким образом отберём только те значения, которые отличаются от 
+предварительного среднего не более чем на 1/16
+
+---
+2016.03.28
+
+Период измерений 1.25 мсек, быстрый буфер - на 16 значений.
+Фильтра нет, только усреднение.
+Понял, почему скачет опора -- при включеном светодиоде проседает 
+напряжение питания и завышаются показания. Что за хрень в канале напруги 
+всё равно не понятно.
+Нужно срочно увеличивать резисторы в цепи светодиодов.
+Без светодиодов канал внутренней опоры показывает 1.219 В.

+ 12 - 9
lib/adc.c

@@ -19,18 +19,21 @@
 /* Private define ------------------------------------------------------------*/
 /* Private macro -------------------------------------------------------------*/
 /* Private variables ---------------------------------------------------------*/
-uint16_t Buffer[BUFFER_SIZE]  = {0, 0, 0};
-uint16_t Voltage = 0;
-uint16_t Current = 0;
-uint16_t RefVolt = 0;
+uint16_t ADC_Buffer[ADC_BUFFER_SIZE] = {0, 0, 0};
+
+uint16_t VoltageFastBuffer[FAST_BUFFER_SIZE];
+uint16_t CurrentFastBuffer[FAST_BUFFER_SIZE];
+uint16_t RefVoltFastBuffer[FAST_BUFFER_SIZE];
+
+/* Private constants ---------------------------------------------------------*/
+__near __no_init const unsigned char Factory_VREFINT @ 0x4910;
 
 /* Private function prototypes -----------------------------------------------*/
-/* Private functions ---------------------------------------------------------*/
 static void ADC_Config(void);
 static void DMA_Config(void);
 static void TIM2_Config(void);
 
-/* Public functions ----------------------------------------------------------*/
+/* Private functions ---------------------------------------------------------*/
 
 /**
   * @brief  Initialize and start ADC
@@ -100,9 +103,9 @@ static void DMA_Config(void)
     /* Connect ADC to DMA channel 0 */
     SYSCFG_REMAPDMAChannelConfig(REMAP_DMA1Channel_ADC1ToChannel0);
 
-    DMA_Init(DMA1_Channel0, BUFFER_ADDRESS,
+    DMA_Init(DMA1_Channel0, ADC_BUFFER_ADDRESS,
            ADC1_DR_ADDRESS,
-           BUFFER_SIZE,
+           ADC_BUFFER_SIZE,
            DMA_DIR_PeripheralToMemory,
            DMA_Mode_Circular,
            DMA_MemoryIncMode_Inc,
@@ -130,7 +133,7 @@ static void TIM2_Config(void)
     CLK_PeripheralClockConfig(CLK_Peripheral_TIM2, ENABLE);
 
     /* Initializes the TIM2 Time Base Unit */
-    TIM2_TimeBaseInit(TIM2_Prescaler_128, TIM2_CounterMode_Up, TIM_PERIOD);
+    TIM2_TimeBaseInit(TIM_PRESCALER, TIM2_CounterMode_Up, TIM_PERIOD);
 
     /* Selects the TIM2 Update Request Interrupt source */
     TIM2_UpdateRequestConfig(TIM2_UpdateSource_Regular);

+ 10 - 7
lib/adc.h

@@ -21,17 +21,20 @@
 #define VOLTAGE_CHANNEL     ADC_Channel_17
 #define CURRENT_CHANNEL     ADC_Channel_18
 #define ADC1_DR_ADDRESS     ((uint16_t)0x5344)
-#define BUFFER_SIZE         ((uint8_t) 0x03)
-#define BUFFER_ADDRESS      ((uint16_t)(&Buffer))
+#define ADC_BUFFER_SIZE     ((uint8_t) 3)
+#define ADC_BUFFER_ADDRESS  ((uint16_t)(&ADC_Buffer))
 
-// (×àñòîòà ÌÊ (16 ÌHz) / Ïðåääåëèòåëü òàéìåðà (128) * Íóæíîå âðåìÿ â ñåêóíäàõ (0.01)) - 1
-#define TIM_PERIOD          ((uint16_t)1249)
+#define FAST_BUFFER_SIZE    ((uint8_t) 16)
+/* ADC_RATIO = (( 3.3 * 1000 * 1000 ) + 2048 ) / 4095 */
+#define ADC_RATIO       806UL
+#define ADC_VOLT_RATIO  8864UL
 
-/* Exported constants --------------------------------------------------------*/
-__near __no_init const unsigned char Factory_VREFINT @ 0x4910;
+// (×àñòîòà ÌÊ (16 ÌHz) / Ïðåääåëèòåëü òàéìåðà (32) * Íóæíîå âðåìÿ â ñåêóíäàõ (0.00125)) - 1
+#define TIM_PERIOD          ((uint16_t)624)
+#define TIM_PRESCALER       TIM2_Prescaler_32
 
+/* Exported constants --------------------------------------------------------*/
 /* Exported macro ------------------------------------------------------------*/
-/* Exported variables --------------------------------------------------------*/
 /* Exported functions ------------------------------------------------------- */
 void Init_ADC(void);
 

+ 38 - 8
src/main.c

@@ -75,10 +75,13 @@ static const max7219_sym_t num[16] = {
 };
 
 /* Private variables ---------------------------------------------------------*/
-extern uint16_t Voltage;
-extern uint16_t Current;
-extern uint16_t RefVolt;
-//extern uint16_t Buffer[];
+uint16_t Voltage = 0;
+uint16_t Current = 0;
+uint16_t RefVolt = 0;
+
+extern uint16_t VoltageFastBuffer[];
+extern uint16_t CurrentFastBuffer[];
+extern uint16_t RefVoltFastBuffer[];
 
 /* Private function prototypes -----------------------------------------------*/
 static void GPIO_Config(void);
@@ -88,6 +91,7 @@ static void CLK_Config(void);
 static void ShowTopLineV(void);
 static void ShowTopLineC(void);
 static void ShowBotLine(void);
+static void ProcessFastBuffer(void);
 
 /* Private functions ---------------------------------------------------------*/
 
@@ -114,8 +118,9 @@ void main(void)
   MAX7219_Init();
 
   /* ROTS tasks */
-  RTOS_SetTask(ShowTopLineV,100,4000);
-  RTOS_SetTask(ShowTopLineC,2100,4000);
+  RTOS_SetTask(ProcessFastBuffer,0,100);
+  RTOS_SetTask(ShowTopLineV,101,4000);
+  RTOS_SetTask(ShowTopLineC,2101,4000);
   RTOS_SetTask(ShowBotLine,101,100);
 
   /* Infinite loop */
@@ -126,6 +131,31 @@ void main(void)
   }
 }
 
+/*
+ * Фильтрация и усреднение данных из быстрого буфера,
+ * вычесление значений, перенос в медленный буфер.
+ */
+static void ProcessFastBuffer(void){
+    uint16_t volt=0, curr=0, ref=0;
+
+    /* Summarize buffers values */
+    uint8_t i;
+    for(i=0;i<FAST_BUFFER_SIZE;i++){
+        volt += VoltageFastBuffer[i];
+        curr += CurrentFastBuffer[i];
+        ref += RefVoltFastBuffer[i];
+    }
+
+    /* Calculate voltage value*/
+    Voltage = ((volt / FAST_BUFFER_SIZE) * ADC_VOLT_RATIO) / 1000;
+
+    /* Calculate current value*/
+    Current = ((curr / FAST_BUFFER_SIZE) * ADC_RATIO) / 1000;
+
+    /* Calculate reference voltage value*/
+    RefVolt = ((ref / FAST_BUFFER_SIZE) * ADC_RATIO) / 1000;
+}
+
 /*
  * Output to top indicator line
  */
@@ -144,7 +174,7 @@ static void ShowTopLineV(void){
     /* Ones voltage value */
     voltage1 = (uint8_t)(Voltage % 10);
 
-    LED_GREEN_ON;
+    LED_RED_ON;
 
     MAX7219_WriteData(dig[0], num[voltage1000]);
     MAX7219_WriteData(dig[1], num[voltage100]);
@@ -153,7 +183,7 @@ static void ShowTopLineV(void){
 }
 
 static void ShowTopLineC(void){
-    LED_GREEN_OFF;
+    LED_RED_OFF;
     uint8_t tmp = Current / 1000;
     MAX7219_WriteData(dig[0], num[tmp]);
     tmp = (Current % 1000) / 100;

+ 15 - 19
src/stm8l15x_it.c

@@ -28,6 +28,7 @@
 
 /* Includes ------------------------------------------------------------------*/
 #include "stm8l15x_it.h"
+#include "adc.h"
 
 /** @addtogroup STM8L15x_StdPeriph_Template
   * @{
@@ -35,16 +36,12 @@
 
 /* Private typedef -----------------------------------------------------------*/
 /* Private define ------------------------------------------------------------*/
-/* ADC_RATIO = (( 3.3 * 1000 * 1000 ) + 2048 ) / 4095 */
-#define ADC_RATIO       806UL
-#define ADC_VOLT_RATIO  8864UL
-
 /* Private macro -------------------------------------------------------------*/
 /* Private variables ---------------------------------------------------------*/
-extern uint16_t Voltage;
-extern uint16_t Current;
-extern uint16_t RefVolt;
-extern uint16_t Buffer[];
+extern uint16_t VoltageFastBuffer[];
+extern uint16_t CurrentFastBuffer[];
+extern uint16_t RefVoltFastBuffer[];
+extern uint16_t ADC_Buffer[];
 
 /* Private function prototypes -----------------------------------------------*/
 /* Private functions ---------------------------------------------------------*/
@@ -97,20 +94,19 @@ INTERRUPT_HANDLER(FLASH_IRQHandler,1)
   */
 INTERRUPT_HANDLER(DMA1_CHANNEL0_1_IRQHandler,2)
 {
-    /* In order to detect unexpected events during development,
-       it is recommended to set a breakpoint on the following instruction.
-    */
-
-  /* Calculate voltage value*/
-  Voltage = (Buffer[0] * ADC_VOLT_RATIO) / 1000;
+    static uint8_t i = 0;
 
-  /* Calculate current value*/
-  Current = (Buffer[1] * ADC_RATIO) / 1000;
+    VoltageFastBuffer[i] = ADC_Buffer[0];
+    CurrentFastBuffer[i] = ADC_Buffer[1];
+    RefVoltFastBuffer[i] = ADC_Buffer[2];
 
-  RefVolt = (Buffer[2] * ADC_RATIO) / 1000;
+    i ++;
+    if(i >= FAST_BUFFER_SIZE) {
+        i = 0;
+    }
 
-  /* Clear IT Pending Bit */
-  DMA1_Channel0->CSPR &= (uint8_t)~(uint8_t)(DMA1_IT_TC0 & (uint8_t)0x06);
+    /* Clear IT Pending Bit */
+    DMA1_Channel0->CSPR &= (uint8_t)~(uint8_t)(DMA1_IT_TC0 & (uint8_t)0x06);
 }
 /**
   * @brief DMA1 channel2 and channel3 Interrupt routine.