Sfoglia il codice sorgente

Added ADC zero current correction and store in EEPROM.

Vladimir N. Shilov 8 anni fa
parent
commit
5533503dab
3 ha cambiato i file con 87 aggiunte e 14 eliminazioni
  1. 1 1
      Makefile
  2. 8 0
      ReadMe.txt
  3. 78 13
      src/main.c

+ 1 - 1
Makefile

@@ -59,7 +59,7 @@ PERIPH_OBJECTS = stm8s_adc1.o
 #PERIPH_OBJECTS += stm8s_beep.o
 PERIPH_OBJECTS += stm8s_clk.o
 PERIPH_OBJECTS += stm8s_exti.o
-#PERIPH_OBJECTS += stm8s_flash.o
+PERIPH_OBJECTS += stm8s_flash.o
 PERIPH_OBJECTS += stm8s_gpio.o
 #PERIPH_OBJECTS += stm8s_i2c.o
 PERIPH_OBJECTS += stm8s_itc.o

+ 8 - 0
ReadMe.txt

@@ -115,3 +115,11 @@ Vin	    Vout	    R1	    R2	    Error
 2016.11.14
 
 RTOS выкинул. на очереди SPL? :-)
+
+---
+2016.11.22
+
+Если при включении питания на выводе кнопки (PA2) будет "0", то сработает
+автокоррекция смещения "0" на входе АЦП -- будет получено и сохранено в EEPROM
+значение АЦП при нулевом токе на входе, которое затем будет использовано при
+расчётах.

+ 78 - 13
src/main.c

@@ -24,6 +24,11 @@
 //#include "rtos.h"
 
 /* Private defines -----------------------------------------------------------*/
+union u_word {
+    uint16_t  Word;
+    uint8_t   Bytes[2];
+};
+
 // for 1 msek ticks
 #define TIM4_PERIOD  (uint8_t)124
 
@@ -91,7 +96,10 @@ E   C
 #define SUB_SECOND_CNT  5
 #define LED_ONE_PERIOD  5
 
+#define ADC_ZERO_EEADDR   FLASH_DATA_START_PHYSICAL_ADDRESS
+
 /* Private function prototypes -----------------------------------------------*/
+static void ADC_CorrectZero(void);
 static void ADC_Config(void);
 static void GPIO_Config(void);
 static void TIM1_Config(void);
@@ -112,6 +120,7 @@ static uint8_t LedDigits[3] = {0, 0, 0};
 static uint8_t LedPoint = 3;
 static uint16_t SubSecondBfr = 0;
 static uint8_t SubSecondCnt = SUB_SECOND_CNT;
+static u_word ADC_ZeroFix;
 
 void main(void)
 {
@@ -148,6 +157,17 @@ void main(void)
   /* enable interrupts */
   enableInterrupts();
 
+  /** If btn pin == 0 -- auto fix adc zero level
+      else -- read zero value from eeprom
+      Value stored in MSB:LSB
+  */
+  if((BTN_PORT->IDR & BTN_PINS) == 0){
+    ADC_CorrectZero();
+  } else {
+    ADC_ZeroFix.Bytes[1] = FLASH_ReadByte(ADC_ZERO_EEADDR);
+    ADC_ZeroFix.Bytes[0] = FLASH_ReadByte((ADC_ZERO_EEADDR+1));
+  }
+
   /* Infinite loop */
   while (1)
   {
@@ -159,8 +179,6 @@ void main(void)
     if (BufferIndex >= ADC_SMPLS) {
         BufferIndex = 0;
 
-        /* èëè îáðàáàòûâàåì ñðàçó, èëè çàäà÷ó ñ 0-îé çàäåðæêîé? */
-
         /* Oversampling */
         uint32_t tbuf = 0;
         uint8_t i = 0;
@@ -177,16 +195,25 @@ void main(void)
          ïîäåëèëè íà ìíîæèòåëü ÎÓ -- 250 ìÂ
          è ïîäåëèëè íà ñîïðîòèâëåíèå øóíòà -- 5000 ìÀ
         */
-        tbuf >>= 3; // pre div
-        tbuf *= 3300; // Vref = Vcc
-        tbuf = (tbuf + 4096) / 8191; // get ADC input voltage in mV
-        tbuf *= 1000; // -- for OU divider //get voltage in uV
-        tbuf = (tbuf + 3147) / 6294; // get voltage from shunt
-        /* â Current òîê â ìèëèàìïåðàõ */
-        tbuf *= 1000; // get voltage in uV
-        Current = (tbuf + 25) / 50; // shunt resistance in mOhms
-
-        SubSecondBfr += Current;
+        if(tbuf > ADC_ZeroFix.Word){
+          tbuf -= ADC_ZeroFix.Word;
+
+          tbuf >>= 3; // pre div
+          tbuf *= 3300; // Vref = Vcc
+          tbuf = (tbuf + 4096) / 8191; // get ADC input voltage in mV
+          tbuf *= 1000; // -- for OU divider //get voltage in uV
+          tbuf = (tbuf + 3147) / 6294; // get voltage from shunt
+          /* â Current òîê â ìèëèàìïåðàõ */
+          tbuf *= 1000; // get voltage in uV
+          Current = (tbuf + 25) / 50; // shunt resistance in mOhms
+
+          SubSecondBfr += Current;
+
+        } else {
+          tbuf = 0;
+          Current = 0;
+        }
+
         SubSecondCnt --;
 
         if(SubSecondCnt == 0){
@@ -206,6 +233,41 @@ void main(void)
 } // End of main()
 
 
+/** Êîððåêòèðóåì íàïðÿæåíèå ñìåùåíèÿ íóëÿ ÎÓ íà âõîäå ÀÖÏ */
+static void ADC_CorrectZero(void) {
+  u_word abuf;
+
+  /* æä¸ì îêîí÷àíèÿ öèêëà èçìåðåíèé */
+  do {
+  } while (BufferIndex < ADC_SMPLS);
+
+  BufferIndex = 0;
+
+  /* Ïîëó÷àåì 16-òè áèòíîå çíà÷åíèå îò ÀÖÏ */
+  uint8_t i = 0;
+  for(i=0; i<ADC_SMPLS; i++){
+    abuf.Word += ConversionBuffer[i];
+  }
+  ADC_ZeroFix.Word = abuf.Word;
+
+  /* Ñîõðàíÿåì ïîëó÷åííîå çíà÷åíèå â EEPROM */
+
+  /*Define FLASH programming time*/
+  FLASH_SetProgrammingTime(FLASH_PROGRAMTIME_STANDARD);
+
+  /* Unlock Data memory */
+  FLASH_Unlock(FLASH_MEMTYPE_DATA);
+
+  /* MSB */
+  FLASH_ProgramByte(ADC_ZERO_EEADDR, abuf.Bytes[1]);
+  /* LSB */
+  FLASH_ProgramByte((ADC_ZERO_EEADDR+1), abuf.Bytes[0]);
+
+  /* Lock Data memory */
+  FLASH_Lock(FLASH_MEMTYPE_DATA);
+
+}
+
 /** Prepare current value for output ot led */
 static void PrepareForLed(void) {
   uint16_t value;
@@ -217,19 +279,22 @@ static void PrepareForLed(void) {
   }
 
   if(value > 9999){
+    /* XX.X Amper */
     LedPoint = 1;
     LedDigits[0] = value / 10000;
     value = value % 10000;
     LedDigits[1] = value / 1000;
     LedDigits[2] = (value % 1000) / 100;
   } else if(value > 999){
+    /* X.XX Amper */
     LedPoint = 0;
     LedDigits[0] = value / 1000;
     value = value % 1000;
     LedDigits[1] = value / 100;
     LedDigits[2] = (value % 100) / 10;
   } else {
-    LedPoint = 2;
+    /* XXX mili Amper */
+    LedPoint = 3;
     LedDigits[0] = value / 100;
     value = value % 100;
     LedDigits[1] = value / 10;