logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

atmega8 program w c pomiar napięcia, źle wyświetla

jaskiniazla 11 Sty 2012 12:31 2475 15
REKLAMA
  • #1 10380755
    jaskiniazla
    Poziom 10  
    Witam
    Mam problem z programem do pomiaru napięcia i wyświetleniu na lcd. Program niby działa ale wyświetlane wartości są przypadkowe 0-150(jednak jak kręcę potencjometrem to coś się zwiększa wchodząc na wyższe wartości 200-455) program jest w fazie początkowej. Jestem początkującym w programowaniu procesorów.

    
    #include <avr/io.h>
    #include "HD44780.h"
    #include <stdlib.h>
    #include <stdio.h>
    #include <avr/pgmspace.h>	
    	#include <avr/signal.h>
    #include <avr/delay.h>
    #include <string.h>
    #include <avr/interrupt.h>
    
    uint16_t pomiar(uint8_t kanal);//deklaracja funkcji pomioaru
    
    int main(void)
    {
    	int f=0;
    	char buffer [17];
    	
      LCD_Initalize();
      //wybor napiecia odniesnienia
        ADMUX |= (1<<REFS0) | (1<<REFS1);
    	//właczenie modułu ADC oraz ustawienie preskalera na 64
      ADCSR |= (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0);
      while(1) //nieskonczona petla w której dokonujemy pomiaru i wyswietlamy na lcd
        {
    		
    	  LCD_Clear();
    	  
    	  f=pomiar(0);
    	  itoa (f,buffer,10);         //zmiana z ASCII
    	  LCD_WriteText("pomiar  ");
    	 // LCD_WriteData(pomiar(0));
    	 LCD_WriteText(buffer); //pomiar i wyswietlenie
    	  _delay_ms(1000);	  
      }
    }
    // DEFINICJA FUNKCJI KTÓRA DOKONUJE POMIARU NA WYBRANYM KANALE, WEJSCIU
    uint16_t pomiar(uint8_t kanal)
    {
    	
    //usatwienie wybranego kanału ADC w rejestrze ADMUX
    ADMUX |= (ADMUX & 0xF8) | kanal;
    //start pomiaru przez ustawienie bitu ADSC w rejestrze ADSC
    ADCSR |=(1<<ADSC);
    //oczekiwanie na koniec pomiaru dopuku bit jest=1
    while ( !ADIF );
    //po zakonczeniu pomiaru gdy bit ADSC=0 zwrocenie wyniku w postaci
    // 16-to bitowej wartości z rejestrów ADCH oraz ADCL
    
    return ADCW;
    }
    
  • REKLAMA
  • #2 10380910
    otapi
    Poziom 25  
    Wyświetlasz wartość odczytaną bezpośrednio z przetwornika ADC, to nie jest wartość zmierzonego napięcia, musisz ją przeliczyć w zależności od zastosowanego napięcia odniesienia.
    napięcie = pomiar_z_ADC*(napięcie_odniesienia/rozdzielczość_ADC)

    w Twoim wypadku

    f=pomiar(0)*(napięcie_odniesienia/1024)
  • #3 10380951
    jaskiniazla
    Poziom 10  
    dzieki :)

    zmieniłem przedostatnią linijke na

    while (!ADIF & (1<<ADSC));

    i teraz pokazuje cały czas 0
  • #4 10380999
    otapi
    Poziom 25  
    BTW. powi nieneś jeszcze zmienić typ zmiennej f na float.
  • REKLAMA
  • #5 10381039
    jaskiniazla
    Poziom 10  
    a czy te rejestry są poprawne? Bo niby sprawdzałem z notą katalogową ale tak jak mówie dopiero zaczynam programować procesory
  • REKLAMA
  • #6 10381063
    dir3ctor
    Poziom 27  
    Witam,

    Nie słuchaj, zmienna f powinna pozostać integerem, jako że funkcja pomiar() zwraca integera. Dopiero jej wartość należy przeliczyć na napięcie, a jak to zrobić to już zależy od tego jakie jest napięcie referencyjne. Zmienna f przyjmuje wartości od 0 do 1023 (10 bitowy ADC), więc aby otrzymać wynik w woltach, przy napięciu referencyjnym 5V masz:

    float wynik;
    wynik = f / 1023 * 5;


    ---edit---
    widzę że kolega otapi był szybszy ;-)
  • REKLAMA
  • #7 10381094
    otapi
    Poziom 25  
    buahahah .... dir3ctor przeczytałeś co napisałem zanim odpowiedziałeś?

    f=pomiar(0)*(napięcie_odniesienia/1024)

    dla przykładu:

    f=200*(5/1024)
    f=0,9765625 - tak to na pewno jest integer ;]
  • #8 10389263
    jaskiniazla
    Poziom 10  
    tylko ze ja mam cały czas problem ze skokami wyniku bo mam rozbierznosc 200 ( np skacze 0-250)
  • #9 10389375
    gaskoin
    Poziom 38  
    jaskiniazla napisał:
    dzieki :)

    zmieniłem przedostatnią linijke na

    while (!ADIF & (1<<ADSC));

    i teraz pokazuje cały czas 0


    Bo to jest bez sensu, poczytaj notę.

    Twoje wyrażenie po kompilacji wygląda tak:

    while (0);

    poza tym co to jest ADCW ?
  • #10 10389782
    jaskiniazla
    Poziom 10  
    adcw jest to rejest 16 bitowy
    ale właśnie będę musiał zmienić program żeby odczytać te 2 rejestry 8 bitowe. Czytałem że trzeba zrobić 2 tablice i to im przypisać i później odczytać całość. Tylko nie do końca jeszcze wiem jak przypisać te rejestry do tablic
  • #11 10389967
    gaskoin
    Poziom 38  
    jak napisałem wyżej - nie to jest Twoim problemem bo można ten rejestr odczytać "na raz"
  • #12 10389978
    tmf
    VIP Zasłużony dla elektroda
    jaskiniazla napisał:
    adcw jest to rejest 16 bitowy
    ale właśnie będę musiał zmienić program żeby odczytać te 2 rejestry 8 bitowe. Czytałem że trzeba zrobić 2 tablice i to im przypisać i później odczytać całość. Tylko nie do końca jeszcze wiem jak przypisać te rejestry do tablic


    Czytaj takie bzdury to daleko zajdziesz. Oczywiście odczyt ADCW jest ok (podobnie jak po prostu odczyt ADC), gaskoin już ci napisał w czym rzecz.
  • #13 10390290
    jaskiniazla
    Poziom 10  
    dzięki za informacje że to źle. Wróciłem do tego programu co na początku. Tylko mam pytanie jak ustabilizować te wyniki wyświetlane na wyświetlaczu. Mam zasilacz(12V) z potencjometrem. i jaką wartość bym nie podał to cały czas skacze, a jak dodam
    f=pomiar(0)*(napięcie_odniesienia/1024)
    to pokazuje 0

    I mam pytanie czy to:
    while (!ADIF );
    jest dobrze
  • Pomocny post
    #14 10390629
    tmf
    VIP Zasłużony dla elektroda
    Nie jest. Do sprawdzania końca konwersji stosuje się bit ADSC. To że masz zero wynika z przeprowadzania operacji na zmiennych całkowitych. Prostym rozwiązaniem jest przejście na float lub zastosowanie arytmetyki stałopozycyjnej. Jeśli sam pomiar skacze to przyczyny mogą być różne:
    - niewłaściwe napięcie referencyjne (np. Vcc),
    - brak kondensatora na wejściu VRef,
    - brak filtracji AVCC i rozdzielenia masy analogowej od cyfrowej,
    - ogólnie kiepskie rozprowadzenie i filtracja napięć,
    - nędzny potencjometr, szumiący jak diabli,
    - zbyt wysoka częstotliwość pracy ADC.
  • Pomocny post
    #15 10391430
    gaskoin
    Poziom 38  
    jaskiniazla napisał:

    I mam pytanie czy to:
    while (!ADIF );
    jest dobrze


    a zastanawiałeś się kiedyś co oznacza zapis np (1 << ADSC) ?

    to co napisałeś to jakaś stała będąca numerem bitu. Jaki to numer to można sprawdzić w dokumentacji albo w pliku nagłówkowym. Jak napisałem wyżej taki kod kompiluje się do

    while(0) więc nigdy ta pętla się nie wykona. Pływanie może brać się stąd że czytasz pomiar nim poprawnie się wykona konwersja
  • #16 10403930
    jaskiniazla
    Poziom 10  
    zmieniłem na
    while (ADCSR & (1<<ADSC) )
    Myślę że pływanie wyniku jest spowodowane winą programu ponieważ płytka była sprawdzana przez kilka osób (co nie znaczy że nie mogą sie mylić :))
REKLAMA