Ana içeriğe git

Haberler

Konu: HAL lib ADC  (735 Kez okunmuş) önceki konu - sonraki konu

0 Üyeler ve 1 Ziyaretçi konuyu incelemekte.
Ynt: HAL lib ADC
Yanıt #10
şimdilik sondurum bu şekilde. şimdilik ara verdim F4 için keile kazma kürek işlemi uygulayacağım

Kod: [Seç]
/* USER CODE BEGIN 0 */
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
if (__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_EOC))
{

ADCRaw = HAL_ADC_GetValue(hadc);
Vin = 3.3 * (ADCRaw/4095); //VRef * (ADC Data/2^ADCbit)
  }
}
/* USER CODE END 0 */


Kod: [Seç]
/* USER CODE BEGIN 3 */

HAL_ADC_Start_IT(&hadc);

float X[100], ToplamX=0;
int j;
X[0] = Vin;    //okudugumuz degeri dizinin ilk elemanina
for (int i=0;i<99;i++) //9 kere döngü döner
{
j = 98 - i; //8 den 0 e dogru geriye saydiralim
X[j+1] = X[j] ; // Her seferinde eski X[j] degerini bir eskisinin yerine tasiyalim
}
for (int y=0;y<99;y++)
{
ToplamX += X[y]; // tüm X degerlerini toplayip 10 a bölüyoruz.
}
OrtalamaX = ToplamX/100;

sprintf(lcd_buff,"MC_Skywalker");
ssd1306_SetCursor(0,0);
ssd1306_WriteString(lcd_buff,Font_7x10,White);

sprintf(lcd_buff,"Volt:%.2f", OrtalamaX );
ssd1306_SetCursor(0,15);
ssd1306_WriteString(lcd_buff,Font_11x18,White);

ssd1306_UpdateScreen();
HAL_Delay(100);

  }
  /* USER CODE END 3 */

Ynt: HAL lib ADC
Yanıt #11
Sanırım çalıştığım MCU da birşeyler sıkıntılı. ADC IN0 kullanarak yaptığım çalışmayı ADC IN1 ile yaptığımda 3.2V okuyorum. IN0 da 3.0V okuduğum oluyordu.

Ynt: HAL lib ADC
Yanıt #12
ADC'de aldığım veriyi UART üzerinden PC'ye atayum dedim. Öncelikli olarak bir deneme yapayım sonra ADC'yi de eklerindedim amma demez olayıdım. bulduğum basit örnekte bile PC ye veri alamadım.

STM32F030F4 ün bir tek UART'ı var onu HAL ile init ettim. 38400, 8bit, 1bit stop, no party

10 elemanlı bir dizi tanımladım
Kod: [Seç]
uint8_t tampon[10] = {10,9,8,7,6,5,4,3,2,1};

sonra  DMA veya INT kullanmadan
Kod: [Seç]
	HAL_UART_Transmit(&huart1, tampon, 10, 100);
HAL_Delay(100);

gönderdim. MCU pinlerine program atmak içinde kullandığım Serial to USB dönüştürücü takıp PC ye bağladım ve terra termi açtığımda ses soluk yok.  Dönüştürücüde sıkıntı yok zira ULINk2'yi çıkartıp bu dönüştürücüyle MCU programlaya biliyorum.

Nedir bunun sıkıntısı anlamadım?!!?

Ynt: HAL lib ADC
Yanıt #13
Terraterm i bende calistiramadim hocam. Problem olabilir.
Adc ye gelince kullandiginiz tum kanallari bir olcjm noktasina baglayiniz. Eger kullanmayacaksaniz gnd ye cekiniz

Ynt: HAL lib ADC
Yanıt #14
Realterm diye bir uygulama buldum. onunla sorunsuz.
 https://realterm.sourceforge.io/

Ynt: HAL lib ADC
Yanıt #15
Yok çıkmadım bu ADC işi içinde bulamadım bu gezinme sorununu.

  • klein
  • [*]
Ynt: HAL lib ADC
Yanıt #16
Değerlerin biraz oynak olması normal. Fakat sizinkiler biraz fazla oynak gibi geldi bana.
Kayar ortalama algoritması pek hoşuma gitmedi. Aşağıdaki gibi yaparsanız daha hızlı olacaktır. Her seferinde tün diziyi kaydırmaya gerek yok. Filtre dizisi uzunluğunu 2 nin katı yaparsanız bölme hızlanır. VDDA ile VDD yi birbirinden ayırmak çok ciddi bir düzelme sağlayacaktır. VDDA pinini direk VCC ye vermek yerine 100-200R gibi bir dirençle vermeyi bi deneyin. Hatta 5Volttan TL431 gibi bir referans regülatörü üzerinden verseniz daha iyi. Eğer referans çipiniz yoksa herhangi bir 3V3 LDO da olur.

Kod: [Seç]
#define ANFILTERSIZE 128
uint32_t Sum;
uint16_t Count;
uint16_t AnFilterVal;
uint16_t Buf[ANFILTERSIZE];

uint16_t AnMovingAverage(uint16_t AVal)
{
    Sum -=  Buf[Count];
    Sum += AVal;
    Buf[Count]= AVal;

    if(++Count == ANFILTERSIZE)
            Count = 0;
    return(Sum / ANFILTERSIZE);
}

AnFilterVal = AnMovingAverage(AnRawVal);


  • klein
  • [*]
Ynt: HAL lib ADC
Yanıt #17
Eğer bu düzeltmekleri yaptıktan sonra halen filtreleme ihtiyacı olursa aşağıdaki gibi floating point filtre uygulayabilirsiniz.
Kayan ortalama filtresinde Floating Point kullanmanıza gerek yok. Bu filtre yeter.

Kod: [Seç]
float AnFVal;

float AnFilterFloat(uint16_t AVal)
{
static float f = 0f;
    f = (float) (f * 0.99f)+(AVal * 0.01f);
    return(f);
}

AnFVal = AnFilterFloat(AnMovingaverage(AnRawVal));


  • klein
  • [*]
Ynt: HAL lib ADC
Yanıt #18
Voltmetrede gördüğünüz değeri ADC de Volt cinsinden görebilmek için basit çarpma bölme çok işe yaramayacaktır. Kalibrasyon yapmanız gerekecek.
ADC girişinde gerilim yokken okuduğunuz değeri InOffset değişkenine yazın.
ADC girişi MAX (örn 3.00V) iken Okuduğunuz değeri InSpan değişkenine yazın.
ADC girişi 0 iken göstergede ne görmek istiyorsanız o değeri OutOffset değişkenine yazın ( örn : 0f)
ADC girişi MAX iken göstergede görmek istediğiniz değeri OutGain değişkenine yazın (örn: 3.00f)

Kod: [Seç]

float InOffset;
float InSpan;
float OutOffset;
float OutGain;

float GetAnResult(float AVal)
{
    float f =(( AVal - (float)InOffset) / (((float)InSpan- (float)InOffset) / ((float)OutGain - (float)OutOffset)) + (float)OutOffset);
    return(f);
}



Ynt: HAL lib ADC
Yanıt #19
@klein değerli yardımlarınız için teşekürler.  NTC okumak için ADC'yi kullanmayı öğrenmeye çalışıyordum. Vermiş olduğunuz örnekleri bugün müsait olur olmaz deneyeceğim.

ST App Notunda 1LSB gezme olabilir demiş. benim bu çalışamamda ise 0x64f  sapma oluyor. 
F4 sersinde ADC girşilerini tarama işlemini iptal edebiliyorsunuz (CubeMX'te ayar mevcut) ama F0'da bunu göremedim. Yani AN0 dışındaki kullanılmayan girşileride tarıyor. 
Burda verdiğiniz filtreleme yöntemi işe yarayacak.