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

[Atmega8][Bascom] Współpraca z AD7731 po SPI

krataja 25 Maj 2008 23:37 2538 2
  • #1 5181293
    krataja
    Poziom 2  
    Witam wszystkich Forumowiczow,
    do tej pory nigdy nie miałem potrzeby pisać postu bo wszystkie problemy rozwiązywałem opcja search ;-) az do tej chwili.

    buduje układ przetwornika AD 24 bitowego, ktory komunikuje sie z Atmega8 po SPI hardware a ta z kolei z moim PC po RS232.
    Docelowo maja byc 2/3 przetworniki, poki co jest jeden i walka trwa ;-)

    Całość pisze w nieszczesnym Bascomie (ver 1.11.8.7) ale rozgrzebałem juz go wiec nie chce zmieniać środowiska (choc na marginesie zaznacze dla tych, ktorzy byc moze kiedys trafia na ten watek- jesli nie macie pojecia czy chcecie sie nauczyc Bascoma to zapewniam ze nie chcecie, funkcje proste sa w nim banalne, a trudne niemozliwe)

    Niemniej wracajac do tematu...
    Problem polega na tym, ze po bolach strasznych przetwornik moj wspolpracuje ze mna w trybie single conversion bardzo dobrze a w trybie continous conversion po kilku/kilkunastu/kilkudziesieciu pomiarach zacina sie i watchdog musi reagować.

    Procesor jest umieszczony na plytce rozruchowej ZL2AVR od pana Wiazani, taktowany kwarcem 14754600 Hz (minimalny blad dla tranmisji RS) , AD7731 zas siedzi na plytce uniwersalnej i taktowany jest domyslnym zegarem 4915200 Hz.

    Bede wdzięczny za wszystkie sugestie co moze być zle.

    Z początku sądziłem że moj błąd tkwi w hardwarze, ale jesli program nie tnie sie w single conversion i działa bezproblemowo to zaczynam sadzić że może błąd jest gdzieś głębiej aniżeli w słabym styku zworki.

    Zasilanie idzie na układ z zasilacza impulsowego 9V a na płytce z Atmega jest stabilizator 5V i z niego pobieram prąd także dla AD7731.
    Uzywam tej samej linii masy i 5V dla toru cyfrowego i analogowego i Atmegi, niemniej do każdego urządzenia ida osobne kabelki. Na wejściach AVCC - AGND i DVCC - DGND wstawiłem pary kondensatorów odsprzęgajacych 4,7uF i 100nF.

    dodatkowo mam pytanie, dla bardziej niz ja obeznanych AVRowców:
    1. dlaczego przy CTC na OC1, które wygląda jak poniżej dostaję częstotliwość 670kHz a nie 737kHz. Jak rozumiem kwarc 14754600 przy preskalerze 1, przy dzielniku 10 [&HA] powinien dac 1475460Hz /2 = 737kHz. czy moj wynik 670 ma jakis sens czy po prostu kwarc mnie oszukuje i nie ma tych swoich 14,7Mhz?

    
    Ddrb.1 = 1
    Tccr1a = &B01000000                                         '&B01001000
    Tccr1b = &B00001001
    Ocr1ah = &H00
    Ocr1al = &HA
    


    2. jak wygląda kwestia obsługi pamięci w Atmedze8?
    czy jest mozliwa w jakis inny sposob niz przez i2c? jesli jest mozliwosc tylko przez i2c to czy wpisanie do pamieci bedzie krotsze czasowo niz wyslanie na rs?

    z góry dziękuję za odpowiedzi,
    pozdrawiam
    krataja


    ps.
    po uruchomieniu programu dostaje na porcie RS np takie dane jak poniżej po czym nastepuje zwis i watchdog resetuje calosc.
    koncowe linijki z wynikiem 1.27999985 to po prostu &H FFFF czyli ciagle stan wysoki na linii ale skad on sie tam bierze?

    no i ciekawym jest fakt, ze kazdy kolejny wynik jest minimalnie wiekszy od poprzednika od dość stała wartość ok 0.0001V. Natomiast w trybie single conversion wynik jest stabilny z szumem na poziomie 0.00001V.
    To, co w tej chwili mierze to bateryjka 9V podlaczona do wejsc Ain1-2 przez dzielnik napięcia R1 ok 80kOhm i R2 ok 340kOhm.




    
    Filter Register: 8004
    po kalibracji skali Ain1-Ain2: 0174
    po kalibracji skali Ain3-Ain4: 0175
    po kalibracji skali Ain5-Ain6: 0176
    po kalibracji zera Ain1-Ain2: 0174
    po kalibracji zera Ain3-Ain4: 0175
    po kalibracji zera Ain5-Ain6: 0176
    po continous conversion mode: 2174
    Wynik Ain1-Ain2: 0.769170818
    Wynik Ain1-Ain2: 0.769291695
    Wynik Ain1-Ain2: 0.769409654
    Wynik Ain1-Ain2: 0.769525583
    Wynik Ain1-Ain2: 0.769641574
    Wynik Ain1-Ain2: 0.76975846
    Wynik Ain1-Ain2: 0.769876537
    Wynik Ain1-Ain2: 0.76999509
    Wynik Ain1-Ain2: 0.770112928
    Wynik Ain1-Ain2: 0.770228561
    Wynik Ain1-Ain2: 0.770341512
    Wynik Ain1-Ain2: 0.770451662
    Wynik Ain1-Ain2: 0.770560737
    Wynik Ain1-Ain2: 0.770670947
    Wynik Ain1-Ain2: 0.770784733
    Wynik Ain1-Ain2: 0.770904237
    Wynik Ain1-Ain2: 0.771030424
    Wynik Ain1-Ain2: 0.771162565
    Wynik Ain1-Ain2: 0.771299118
    Wynik Ain1-Ain2: 0.771436926
    Wynik Ain1-Ain2: 0.771573003
    Wynik Ain1-Ain2: 0.77170473
    Wynik Ain1-Ain2: 0.771830734
    Wynik Ain1-Ain2: 0.771951611
    Wynik Ain1-Ain2: 0.772070167
    Wynik Ain1-Ain2: 1.27999985
    Wynik Ain1-Ain2: 1.27999985
    


    Zamieszczam poniżej kod programu w wersji continous conversion:



    $regfile = "m8def.dat"                                      '
    $crystal = 14745600                                         
    $baud = 115200
    
    
    $hwstack = 32                                               '128
    $swstack = 8                                                '128
    $framesize = 24                                             '128
    
    '------------konfiguracja SPI i COM--------------------
    Config Spi = Hard , Interrupt = Off , Data Order = Msb , Master = Yes , Polarity = High , Phase = 1 , Clockrate = 128 , Noss = 0
    Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 2 , Databits = 8 , Clockpol = 0
    
    
    '------------konfiguracja portu B i C zgodnie z uzyciem--
    Ddrb.0 = 0                                                  'wejscie
    Ddrb.2 = 1                                                  'wyjscie
    Ddrb.3 = 1
    Ddrb.4 = 0
    Ddrb.5 = 1
    Ddrc.3 = 1
    
    Reset Portb.0
    
    
    Rdy Alias Pinb.0
    Rst Alias Portc.3
    
    
    '------------deklaracja zmiennych------------------------
    Dim Wart_ac(3) As Byte                                      
    Dim Communication_reg As Byte
    Dim Io_control_reg As Integer
    Dim Filter_reg(2) As Byte
    Dim Ad_aux_reg As Byte
    Dim Ad_main_reg As Byte
    Dim Mode_reg(2) As Byte
    Dim Dac_reg As Byte
    Dim Test_reg As Long
    Dim Longpomiar As Single
    Dim Longpomiarr As Single
    Dim Longpomiarrr As Single
    Dim Longpomiarrrr As Single
    Dim Singlewynik As Single
    Dim Singlewynik_12 As Single
    Dim Singlewynik_34 As Single
    Dim Singlewynik_56 As Single
    Dim Doublewynik As Double
    
    Dim Zakres As Double
    Zakres = 1.28 * 2
    
    Dim Ile_stanow As Double
    Ile_stanow = 2 ^ 24
    
    Dim Longiloczyn As Single
    Longiloczyn = 256 * 256
    
    Dim Polzakres As Double
    Polzakres = Zakres / 2
    
    Dim Rozdz As Double
    Rozdz = Zakres / Ile_stanow                                 '0.0000000762939453125
    
    Dim Test As Integer
    
    Wart_ac(1) = 0
    Wart_ac(2) = 0
    Wart_ac(3) = 0
    
    '-------------------konfiguracja watchdoga------------
    Config Watchdog = 2048
    
    '-------------------reset AD7731
    Wait 1
    Reset Rst
    Waitms 100
    Set Rst
    Waitms 1000
    
    
    '-------------------poczatek programu-----------------
    Start Watchdog
    
    Print "start"
    Waitms 1000
    
    
    '-------------------test czy dziala status register---
    Spiinit
    Communication_reg = &H10
    Spiout Communication_reg , 1
    Spiin Wart_ac(1) , 1
    
    Print "Communication Register: " ; Hex(wart_ac(1))
    
    
    Do
    
    '------------------ustawienie filtra------------------
    Communication_reg = &H03
    Spiout Communication_reg , 1
    Filter_reg(1) = &H40                                        '13
    Spiout Filter_reg(1) , 1
    Filter_reg(2) = &H04                                        '36
    Spiout Filter_reg(2) , 1
    
    
    Communication_reg = &H13
    Spiout Communication_reg , 1
    Spiin Wart_ac(1) , 2
    
    Print "Filter Register: " ; Hex(wart_ac(1)) ; Hex(wart_ac(2))
    
    
    Test = Makeint(wart_ac(2) , Wart_ac(1))
    Loop Until Test = &H4004                                    '1336
    
    Reset Watchdog
    
    Do
    
    '--------------kalibracja wenwnetrzna skali kanal Ain1-Ain2
    Communication_reg = &H02
    Spiout Communication_reg , 1
    Mode_reg(1) = &HA1
    Spiout Mode_reg(1) , 1
    Mode_reg(2) = &H74
    Spiout Mode_reg(2) , 1
    
    
    Stop Watchdog
    'Waitms 2400
    Bitwait Rdy , Reset
    Start Watchdog
    
    
    Communication_reg = &H12
    Spiout Communication_reg , 1
    Spiin Wart_ac(1) , 2
    
    Print "po kalibracji skali Ain1-Ain2: " ; Hex(wart_ac(1)) ; Hex(wart_ac(2))
    
    
    
    Test = Makeint(wart_ac(2) , Wart_ac(1))
    Loop Until Test = &H0174
    
    
    Do
    
    '---------------kalibracja wenwnetrzna skali kanal Ain3-Ain4
    Communication_reg = &H02
    Spiout Communication_reg , 1
    Mode_reg(1) = &HA1
    Spiout Mode_reg(1) , 1
    Mode_reg(2) = &H75
    Spiout Mode_reg(2) , 1
    
    
    Stop Watchdog
    'Waitms 2400
    Bitwait Rdy , Reset
    Start Watchdog
    
    Communication_reg = &H12
    Spiout Communication_reg , 1
    Spiin Wart_ac(1) , 2
    
    Print "po kalibracji skali Ain3-Ain4: " ; Hex(wart_ac(1)) ; Hex(wart_ac(2))
    'Waitus 100
    
    Reset Watchdog
    Test = Makeint(wart_ac(2) , Wart_ac(1))
    Loop Until Test = &H0175
    
    Do
    
    
    '----------------kalibracja wenwnetrzna skali kanal Ain5-Ain6
    Communication_reg = &H02
    Spiout Communication_reg , 1
    Mode_reg(1) = &HA1
    Spiout Mode_reg(1) , 1
    Mode_reg(2) = &H76
    Spiout Mode_reg(2) , 1
    
    
    Stop Watchdog
    'Waitms 2400
    Bitwait Rdy , Reset
    Start Watchdog
    
    Communication_reg = &H12
    Spiout Communication_reg , 1
    Spiin Wart_ac(1) , 2
    
    Print "po kalibracji skali Ain5-Ain6: " ; Hex(wart_ac(1)) ; Hex(wart_ac(2))
    'Waitus 100
    
    Reset Watchdog
    Test = Makeint(wart_ac(2) , Wart_ac(1))
    Loop Until Test = &H0176
    
    
    
    
    
    Do
    '----------------calibracja wewnetrzna zera kanalu Ain1-Ain2
    Communication_reg = &H02
    Spiout Communication_reg , 1
    Mode_reg(1) = &H81
    Spiout Mode_reg(1) , 1
    Mode_reg(2) = &H74
    Spiout Mode_reg(2) , 1
    
    
    'Waitms 1200
    Bitwait Rdy , Reset
    
    
    Communication_reg = &H12
    Spiout Communication_reg , 1
    Spiin Wart_ac(1) , 2
    
    Print "po kalibracji zera Ain1-Ain2: " ; Hex(wart_ac(1)) ; Hex(wart_ac(2))
    'Waitus 100
    
    Reset Watchdog
    Test = Makeint(wart_ac(2) , Wart_ac(1))
    Loop Until Test = &H0174
    
    
    Do
    '---------------calibracja wewnetrzna zera kanalu Ain3-Ain4
    Communication_reg = &H02
    Spiout Communication_reg , 1
    Mode_reg(1) = &H81
    Spiout Mode_reg(1) , 1
    Mode_reg(2) = &H75
    Spiout Mode_reg(2) , 1
    
    
    'Waitms 1200
    Bitwait Rdy , Reset
    
    Communication_reg = &H12
    Spiout Communication_reg , 1
    Spiin Wart_ac(1) , 2
    
    Print "po kalibracji zera Ain3-Ain4: " ; Hex(wart_ac(1)) ; Hex(wart_ac(2))
    'Waitus 100
    
    Reset Watchdog
    Test = Makeint(wart_ac(2) , Wart_ac(1))
    Loop Until Test = &H0175
    
    Do
    '---------------calibracja wewnetrzna zera kanalu Ain5-Ain6
    Communication_reg = &H02
    Spiout Communication_reg , 1
    Mode_reg(1) = &H81
    Spiout Mode_reg(1) , 1
    Mode_reg(2) = &H76
    Spiout Mode_reg(2) , 1
    
    
    'Waitms 1200
    Bitwait Rdy , Reset
    
    Communication_reg = &H12
    Spiout Communication_reg , 1
    Spiin Wart_ac(1) , 2
    
    Print "po kalibracji zera Ain5-Ain6: " ; Hex(wart_ac(1)) ; Hex(wart_ac(2))
    'Waitus 100
    
    Reset Watchdog
    Test = Makeint(wart_ac(2) , Wart_ac(1))
    Loop Until Test = &H0176
    
    
    
    
    '------------------przygotowanie do odczytu data register
    '------------------do con conversion Ain1-Ain2----------
    Communication_reg = &H02
    Spiout Communication_reg , 1
    Mode_reg(1) = &H21
    Spiout Mode_reg(1) , 1
    Mode_reg(2) = &H74
    Spiout Mode_reg(2) , 1
    
    
    Waitms 600
    
    
    Communication_reg = &H12
    Spiout Communication_reg , 1
    Spiin Wart_ac(1) , 2
    
    Print "po continous conversion mode: " ; Hex(wart_ac(1)) ; Hex(wart_ac(2))
    
    Communication_reg = &H21
    Spiout Communication_reg , 1
    '-----------------------------------------------
    
    
    
    
    Do
    
    
    '--------- cont conversion na 1 kanale-----------
    
    Bitwait Rdy , Reset
    Spiin Wart_ac(1) , 3
    
    
    'Print "pomiar: " ; Hex(wart_ac(1)) ; Hex(wart_ac(2)) ; Hex(wart_ac(3))
    
    Longpomiarrrr = Wart_ac(1) * Longiloczyn
    Longpomiarrr = Wart_ac(2) * 256
    Longpomiarr = Wart_ac(3) + Longpomiarrr
    Longpomiar = Longpomiarr + Longpomiarrrr
    Doublewynik = Longpomiar
    Doublewynik = Doublewynik * Rozdz
    Doublewynik = Doublewynik - Polzakres
    Singlewynik_12 = Doublewynik
    
    
    Print "Wynik Ain1-Ain2: " ; Singlewynik_12
    Reset Watchdog
    
    
    Loop
    End
  • #2 5188853
    rusala
    Poziom 22  
    coz fajny projekt ale jezyk... zreszta juz go komentowales. Wgryzanie sie w kod bascoma niestety nie nalezy do moich ulubionych zajec wiec z tym Ci nie pomoge ale zaciekawilo mnie twoje pytanie o pamiec - chodzi Ci o EEPROM zenetrzny czy o co? Jezeli tak to oczywiscie istnieja tez EEPROMy/DataFLASHe na SPI chocby. ATmegi maja tez troche wlasnego EEPROmu. Natomiast po I2C prawie napewno (Zaleznie od predkosci UARTu) bedzie wolniej niz po RSie
  • #3 5607265
    krataja
    Poziom 2  
    Pisze gdyz byc moze komus kiedys w przyszlosci sie przyda wniosek, choc wiem ze juz trocheczasu minelo od tamtego postu ;-)

    Wklejony kod programu działa prawidłowo, musialem zrobic update Bascoma i poszlo.

    Natomiast jesli chodzi o wnioski z tej konstrukcji to tak:
    1. udalo sie uzyskac dokladny pomiar, ok 18-19 bitow. mysle ze to duzo
    2. AD7731 ma duże opoźnienie pierwszej próbki wyjściowej. dlugo schodzi zanim przetworzy dane. ja wiem ze to wynika z ukladu sigma-delta ale czas oczekiwania jest baaardzo dlugi.
    3. uklad chodzi z predkoscia do 600 sampli na sekunde, wiec mozna jakies pomiary juz zrobic
    4. ad7731 ma bardzo ostro zrobiony filr dolnoprzepustowy, ktorego nei da sie kontrolowac bezpośrednio, tylko pośrednio, zaleznie od np fsample. pasmo 3db dla 600 sampli/sekunde wynosi ok 20Hz. wiec sygnału prostokątnego zmierzyć się tym nie da;-)

    to tyle, temat zamkniety.
REKLAMA