Odpowiedz 
 
Ocena wątku:
  • 0 Głosów - 0 Średnio
  • 1
  • 2
  • 3
  • 4
  • 5
Sterowanie syntezą LM7001 z Arduino
SP7EZG Offline
Artur
***

Liczba postów: 194
Dołączył: 06-12-2015
Post: #1
Sterowanie syntezą LM7001 z Arduino
Witajcie.

Cały czas walczę z syntezą do odbiornika na Airband.

Pozostawiając niesnaski związane z nieodpowiednim krokiem postanowiłem wykonać nawet najprostszą syntezę, która później może przydać mi się do innych konstrukcji. (Kiedy już opracuję syntezę z krokiem 8.33 kHz)

http://labkit.ru/userfiles/file/document...LM7001.pdf

Analizuję cały czas projekt zaprezentowany przez SQ1FTB.

http://sq1ftb.n12.pl/projekty/lm7001/Synteza.pdf

Program jest napisany pod Atmegę, jednak ja chciałbym napisać coś swojego w Arudino. Po pierwsze dlatego że mam kilka takich modułów do wykorzystania, po drugie dlatego, że chciałbym pobawić się w sterowanie po USB, po trzecie dlatego że nie przepadam za Bascomem.

Jasnym jest, że wysyłamy do syntezy bity w określonej kolejności.

Linią CE włączamy transmisję. Pozostaje ona włączona przez cały okres trwania przesyłu danych.
Linią CL taktujemy szynę.
Mamy również szynę Data, którą wysyłamy poszczególne bity, z częstotliwością zadaną przez na CL.

Teraz

Analizując kod SQ1FTB straciłem cały wieczór. Wiem, że wysyłamy bit po bicie, natomiast nie doszukałem się 'zgrania' linii CL z liniami Data. Nie wiem w jakiej postaci należy wysyłać te bity. Ponadto ciekawostką byłoby sprawdzenie tego jak ta komunikacja działa. Czy diody na liniach wystarczą?

Proszę o pomoc, bo z Arduino bawię się już jakiś czas, a mam problem z podstawowymi czynnościami.

Pozdrawiam

Pozdrawiam, Artur
22-02-2017 9:08
Znajdź wszystkie posty użytkownika Odpowiedz cytując ten post
SQ8MVY Offline
Paweł
****

Liczba postów: 724
Dołączył: 30-07-2011
Post: #2
RE: Sterowanie syntezą LM7001 z Arduino
Witaj,

Arturze, najpierw zaglądnij do tego dokumentu, strona 5. Strona 6 mówi co powinna zawierać wysyłana ramka danych oraz jak liczyć częstotliwość wyjściową.

Cytat:...Wiem, że wysyłamy bit po bicie, natomiast nie doszukałem się 'zgrania' linii CL z liniami Data...

Tak, wysyłamy bit po bicie. W tym programie generowanie impulsu na linii CL robione jest w funkcji Zegarek.
Cała ramka sterująca układ wysyłana jest w podprogramie Synteza. Analizując więc pętlę tego podprogramu wysyłającą 13 bitów słowa z freq:

- pętla for, której wartością iteracyjną jest zmienna A,
- sprawdzamy A-ty bit w słowie z freq
- jeżeli jest 1 to ustawiamy Data=1, jeśli 0 to linia Data=0
- skok do podprogramu Zegarek, w którym:
> czekamy 10us,
> ustawiamy linię CL=1,
> czekamy 10us,
> ustawiamy linię CL=0,
> czekamy 10us,
> wychodzimy z podprogramu Zegarek.
- kolejny obieg pętli, ze zmienną A zwiększoną o wartość 1

Takim oto sposobem wysyłamy 13 bitów słowa z freq. W dalszej części podprogramu Synteza wysyłane są pozostałe bity słowa sterującego syntezę.

Jak już piszesz swoją wersję sterowania syntezą, to możesz użyć sprzętowego SPI do wysyłania.
Całe słowo sterujące syntezy ma długość 24 bitów, więc pełne 3 bajty. Sprzętowe SPI zapewni prawidłowe timmingi przebiegów. Nie trzeba się będzie bawić w programowe opóźnienia, a i program powinien być bardziej czytelny.

73 Paweł
(Ten post był ostatnio modyfikowany: 22-02-2017 11:41 przez SQ8MVY.)
22-02-2017 10:17
Znajdź wszystkie posty użytkownika Odpowiedz cytując ten post
SP7EZG Offline
Artur
***

Liczba postów: 194
Dołączył: 06-12-2015
Post: #3
RE: Sterowanie syntezą LM7001 z Arduino
Jak obliczona jest postać binarna częstotliwości którą wysyłamy na port?
Jak zrealizować zwiększanie lub zmniejszanie częstotliwości na enkoderze?
Rozumiem, że w zmiennej 'sterowanie' są przechowywane bity konfiguracyjne krok syntezy, i po przesłaniu D13 bitu częstotliwości jest on 'doklejany' do transmisji?

Oczywiście mówię o programie.
Da się zmusić LM7001 do pracy z krokiem 8.33?

Pozdrawiam, Artur
(Ten post był ostatnio modyfikowany: 24-02-2017 21:14 przez SP7EZG.)
24-02-2017 21:10
Znajdź wszystkie posty użytkownika Odpowiedz cytując ten post
SQ8MVY Offline
Paweł
****

Liczba postów: 724
Dołączył: 30-07-2011
Post: #4
RE: Sterowanie syntezą LM7001 z Arduino
(24-02-2017 21:10)SP7EZG napisał(a):  Jak obliczona jest postać binarna częstotliwości którą wysyłamy na port?

Masz to opisane w komentarzu w pdf-ie z programem.

dzielnik = Fvco / krok

(24-02-2017 21:10)SP7EZG napisał(a):  Jak zrealizować zwiększanie lub zmniejszanie częstotliwości na enkoderze?

To już zależy od Ciebie. Jest na to tyle sposobów, ilu jest programistów....

(24-02-2017 21:10)SP7EZG napisał(a):  Rozumiem, że w zmiennej 'sterowanie' są przechowywane bity konfiguracyjne krok syntezy, i po przesłaniu D13 bitu częstotliwości jest on 'doklejany' do transmisji?

Po wysłaniu 14 bitów częstotliwości, wysyłane są bity T0 oraz T1, a następnie zmienna Sterowanie

(24-02-2017 21:10)SP7EZG napisał(a):  Da się zmusić LM7001 do pracy z krokiem 8.33?

Powinno się dać poprzez zmianę częstotliwości kwarcu taktującego LM7001.

Arturze, czy jesteś pewien swoich sił, aby napisać ten program po swojemu ?
Wszystko o co pytasz, masz podane jak na tacy w listingu programu z PDF-a oraz w dokumentacji LM7001.

73 Paweł
(Ten post był ostatnio modyfikowany: 25-02-2017 10:44 przez SQ8MVY.)
24-02-2017 23:33
Znajdź wszystkie posty użytkownika Odpowiedz cytując ten post
SP7EZG Offline
Artur
***

Liczba postów: 194
Dołączył: 06-12-2015
Post: #5
RE: Sterowanie syntezą LM7001 z Arduino
Cytat:Arturze, czy jesteś pewien swoich sił, aby napisać ten program po swojemu ?

Oczywiście że nie, dlatego założyłem ten temat, żeby rozwiązać wszelkie problemy i niesnaski.

Cytat: dzielnik = Fvco / krok

Nie chodziło mi o to.
Miałem na myśli podprogram Synteza. Tam jest zmienna Fpom opisana:

Kod:
Fpom = Freq + Pcz

Następnie
Kod:
For A = 0 To 13             ' wysyłanie bitów częstotliwości D0-D13
      If Fpom.a = 1 Then      ' bit po bicie
         Set Portd.0
      Else
         Reset Portd.0

Wynikałoby z tego, że w zmiennej Fpom.a już jest zapisana postać binarna tej zmiennej. Tutaj jest pytanie jak to rozwiązać w C/Arduino.

I dlaczego funkcja Zegarek jest wywoływana za każdym razem, kiedy wysyłamy cokolwiek? Logika wskazywałaby, że taktowanie szyny CL należałoby ustawić "globalnie" po rozpoczęciu transmisji. Na zasadzie - funkcja Zegarek jest wykonywana przez cały czas trwania przesyłu. Jeśli włączamy CE, włączamy Zegarek. Tutaj Zegarek jest wywoływany co sekwencję.


Całe słowo ma rzecz jasna 24 bity. Szacunkowo - biorąc pod uwagę, że mamy 14 bitów częstotliwości (D0-D13) możemy wysłać maksymalną częstotliwość 16383 razy krok.

Pozdrawiam, Artur
25-02-2017 11:03
Znajdź wszystkie posty użytkownika Odpowiedz cytując ten post
SQ8MVY Offline
Paweł
****

Liczba postów: 724
Dołączył: 30-07-2011
Post: #6
RE: Sterowanie syntezą LM7001 z Arduino
Witaj,

Ok.
Zaglądnij więc na stronę 5 PDF-a ze żródłami.
Kod:
Freq = 5394      ' fodb=(145550-10700)/25=5394
Pcz = 428         ' dodanie pcz do freq nadawczej
Masz tam przypisanie wartości 5394 do zmiennej Fpom, która została na stronie 4 w/w dokumentu zadeklarowana jako WORD.
Zmiennej Pcz natomiast przypisana została wartość 428 (storna 5).

Zmiennej Fpom jest przypisywana wartość w podprogramie Synteza. W tym miejscu:
Kod:
If Portb.2 = 1 Then
  Fpom = Freq + Pcz
  If Rpt = 1 Then
     Fpom = Fpom – 24
  End If
Else
   Fpom = Freq
End If

Wartość ta jest zależna od poziomu sygnału na pinie 2 portu B oraz wartości w zmiennej Rpt

W Bascomie poprzez zapis:
Kod:
Fpom.a
dobieramy się do bitu na pozycji a w zmiennej Fpom. Inaczej mówiąc, jeżeli a będzie miało wartość np. 3, to poprzez ten zapis sprawdzimy jaką wartość ma bit 3 w zmiennej Fpom.

W tym programie sterownika, wysyłanie słowa sterującego do LM7001 zrealizowane jest w sposób czysto programowy. W takim przypadku trzeba zadbać programowo o ustawienie na linii DATA poziomu odpowiadającemu wartości wysyłanego bitu, następnie trzeba programowo wygenerować na linii CL impuls zegarowy - i dba o to podprogram Zegarek.

Czyli w pętli sprawdzany jest stan a-tego bitu zmiennej Fpom i jeżeli jest 0 to na linii DATA ustawiamy 0, jeżeli jest 1 to DATA ustawiamy na 1. Następnie generujemy impuls na linii CL - robi to właśnie podprogram Zegarek.
Ta pętla wykona się 14 razy wysyłając wszystkie bity zmiennej Fpom

Taki sposób wysyłania danych wynika z dokumentacji producenta układu. Rozrysowane jest to na stronie 5 PDF-a układu.

Jeżeli do transmisji danych użyty będzie sprzętowy SPI, to całą transmisję oraz generowanie sygnału zegarowego przejmie sprzęt. Zadaniem programu będzie wtedy dostarczyć gotową daną do rejestru peryferium SPI.


Zanim zaczniesz "męczyć" się z pisaniem swojej wersji programu na Arduino, polecam na początek zapoznać się z kursem Arduino. Jest napisany bardzo prosto, dla całkowicie początkujących. Wiele niewiadomych Ci się rozjaśni.

73 Paweł
(Ten post był ostatnio modyfikowany: 25-02-2017 12:22 przez SQ8MVY.)
25-02-2017 11:51
Znajdź wszystkie posty użytkownika Odpowiedz cytując ten post
SP7EZG Offline
Artur
***

Liczba postów: 194
Dołączył: 06-12-2015
Post: #7
RE: Sterowanie syntezą LM7001 z Arduino
Tutaj jest wszystko jasne Pawle. Rozumiem całą istotę obliczania częstotliwości, w porozumieniu z komentarzami i pdf z LM7001 to jest czytelne.

Nawiązując do strony 6 noty LM7001 mamy rozrysowane przebiegi i sekwencje pojawiające się na liniach.

Rozpoczynamy transmisję - włączamy stan wysoki na CE, oraz funkcję Zegarek na CL - zrozumiałe. Po linii CL synteza wie gdzie leży jaki bit - i to jest w pełni czytelne.
Nie rozumiem jednak dlaczego w programie SQ1FTB po każdej sekwencji bitów jest wywoływana funkcja Zegarek.
No i wracając do Fpom.a

Pozycja bitu - okej, ale czy w Bascomie zmienne zawsze mają postać dwójkową? Nie znalazłem w programie żadnej funkcji zamieniającej wartość Freq czy Fpom na binarną.
Jeśli Fpom.a zwraca wartość bitu na danej pozycji to czy dla C można to zastąpić:

Kod:
unsigned char i;  
    unsigned char a = 00000001;  
      
    for(i = 0; i<9; i++){    
          a<<=1;  
    }

?

Czytałem gdzieś, że zamianę zmiennej w C można zrealizować maską. Mnożąc zmienną np. 4 przez maskę np. 0001 możemy określić wartość bitu.

Pozdrawiam, Artur
25-02-2017 12:19
Znajdź wszystkie posty użytkownika Odpowiedz cytując ten post
SQ8MVY Offline
Paweł
****

Liczba postów: 724
Dołączył: 30-07-2011
Post: #8
RE: Sterowanie syntezą LM7001 z Arduino
(25-02-2017 12:19)SP7EZG napisał(a):  Nie rozumiem jednak dlaczego w programie SQ1FTB po każdej sekwencji bitów jest wywoływana funkcja Zegarek.

Ponieważ Zegarek odpowiada za generowanie impulsu na linii CL. Ten impuls MUSI być wygenerowany po każdym wystawionym bicie na linii DATA

(25-02-2017 12:19)SP7EZG napisał(a):  .... ale czy w Bascomie zmienne zawsze mają postać dwójkową? Nie znalazłem w programie żadnej funkcji zamieniającej wartość Freq czy Fpom na binarną.....

A co robi pętla wysyłająca 14 bitów ze zmiennej Fpom ?????
Każdy procesor, cyfrowy układ logiczny, FPGA i co tam jeszcze jest w cyfrówce widzi tylko dane binarne. Po to są edytory, środowiska programistyczne, żeby kod wyglądał zjadliwie dla człowieka !!!! Ciężko jest w dzisiejszych czasach pisać za pomocą 0 i 1 przy tak złożonych mikroprocesorach i programach.

(25-02-2017 12:19)SP7EZG napisał(a):  Jeśli Fpom.a zwraca wartość bitu na danej pozycji to czy dla C można to zastąpić.....


Np. tak można wysłać 14 bitów zmiennej Fpom w kolejności nałożonej przez producenta LM7001:
Kod:
for( uint8_t idx=0; idx<14; idx++ )
{
   if ( ( Fpom >> idx ) & 0x0001 )
   {
      SET_PIN_DATA ;         // Pin DATA ustawiamy na 1
   } else
   {
      CLEAR_PIN_DATA ;     // Pin DATA ustawiamy na 0
   }
   Zegarek();                    // Generujemy impuls na linii CL
}

Za pomocą tej pętli można również za jednym zamachem wysłać wszystkie 24 bity do LM7001 - czyli kompletne słowo sterujące. Wymaga to jednak, bardzo drobnej modyfikacji powyższej pętli.

73 Paweł
(Ten post był ostatnio modyfikowany: 25-02-2017 14:33 przez SQ8MVY.)
25-02-2017 14:32
Znajdź wszystkie posty użytkownika Odpowiedz cytując ten post
SP7EZG Offline
Artur
***

Liczba postów: 194
Dołączył: 06-12-2015
Post: #9
RE: Sterowanie syntezą LM7001 z Arduino
Kod:
for( uint8_t idx=0; idx<24; idx++ )
{
   if ( ( Fpom >> idx ) & 0x00001 )
   {
      SET_PIN_DATA ;         // Pin DATA ustawiamy na 1
   } else
   {
      CLEAR_PIN_DATA ;     // Pin DATA ustawiamy na 0
   }
   Zegarek();                    // Generujemy impuls na linii CL
}

Zakładając oczywiście, że w Fpom będzie zapisana cała wartość.
Warunkiem w if jest mnożenie logiczne. Czym jest wartość 0x0001? Jedynką reprezentującą ilość bitów?
Pętla sprawdza pozycję bitu, jeśli 1 wysyła, jeśli 0 czeka.
Przecież to jasne jak słońce!

Tylko czy uint8_t przechowa tą wartość? Synteza przyjmuje słowo 14 bitowe.

Cytat:A co robi pętla wysyłająca 14 bitów ze zmiennej Fpom ?????
Każdy procesor, cyfrowy układ logiczny, FPGA i co tam jeszcze jest w cyfrówce widzi tylko dane binarne. Po to są edytory, środowiska programistyczne, żeby kod wyglądał zjadliwie dla człowieka !!!! Ciężko jest w dzisiejszych czasach pisać za pomocą 0 i 1 przy tak złożonych mikroprocesorach i programach.

Jasna sprawa! Tylko nie wiedziałem, że to działa w tak prosty sposób! 255 = 11111111!

Nie denerwuj się proszę, wytłumaczyłeś mi już i tak mega dużo. Lubię dyskutować i podpytywać mądrzejszych Smile

Pozdrawiam, Artur
25-02-2017 15:55
Znajdź wszystkie posty użytkownika Odpowiedz cytując ten post
SQ8MVY Offline
Paweł
****

Liczba postów: 724
Dołączył: 30-07-2011
Post: #10
RE: Sterowanie syntezą LM7001 z Arduino
(25-02-2017 15:55)SP7EZG napisał(a):  Warunkiem w if jest mnożenie logiczne. Czym jest wartość 0x0001? Jedynką reprezentującą ilość bitów?
Pętla sprawdza pozycję bitu, jeśli 1 wysyła, jeśli 0 czeka.

Nie. Przy takim zapisie w języku C
Kod:
a >> b
czyli przesuwanie bitowe liczby a w prawo o b miejsc, wynikiem jest dzielenie. Czyli:

a >> 0 = a
a >> 1 = a/2
a >> 2 = a/4
a >> 3 = a/16

Aby było lepiej dla oczu to przyjmijmy zapis bitowy:
a = 00001111 , co w systemie dziesiętnym jest 15, więc:

00001111 >> 0 = 00001111 // dziesiętnie 15
00001111 >> 1 = 00000111 // dziesiętnie 7
00001111 >> 2 = 00000011 // dziesiętnie 3
00001111 >> 3 = 00000001 // dziesiętnie 1

Natomiast operatorem & w uproszczeniu maskujemy bity. Więc np. dla przykładu tak:

00001111 & 00000001 = 00000001
10101001 & 00001111 = 00001001

Wracając do przykładu pętli...
Mamy jakąś wartość, dla uproszczenia 8 bitową np.:
Kod:
uint8_t Fpom = 0x55;           //zapis binarny dla jasności to 0b01010101
Początkowa wartość idx wynosi 0 jak pętla robi pierwszy obieg.

W warunku if jest w pierwszej kolejności obliczane jest wyrażenie
Kod:
( Fpom >> idx ) & 0x0001 )

Co po rozpisaniu da nam:
01010101 >> 0 = 01010101

Ten wynik teraz jest maskowany przez operator & wartością 0x0001. Uzyskamy taki wynik:

01010101 & 0x0001 = 00000001

Warunek if po obliczeniu wyrażenia decyduje następująco:
jeśli obliczone wyrażenie da nam wartość różną od 0 ( TRUE ) to wykonaj SET_PIN_DATA,
w przeciwnym wypadku ( wartość obliczonego wyrażenia będzie 0 - FALSE ) wykonaj CLEAR_PIN_DATA

W kolejnym obiegu pętli idx przyjmie wartość 1, więc mamy tak:
01010101 >> 1 = 00101010
00101010 & 0x0001 = 00000000

idx = 2

01010101 >> 2 = 00010101
00010101 & 0x0001 = 00000001

itd., itd. aż do wysunięcia wszystkich bitów.

Zapamiętaj, że obliczane wyrażenie w warunku if nie modyfikuje zawartości zmiennej. Obliczenia są wykonywane po cichu na kopii zmiennej.

(25-02-2017 15:55)SP7EZG napisał(a):  Pętla sprawdza pozycję bitu, jeśli 1 wysyła, jeśli 0 czeka.
Przecież to jasne jak słońce!
Widzisz dalej nie jest to jasne dla Ciebie. Dlaczego jeśli jest 0 to ma czekać ? Gdzie czeka ? i co czeka ?

Jeśli wynikiem jest 1 to wystawia na linię DATA wartość 1, jeżeli wynikiem jest 0, to na linię DATA wystawiana jest wartość 0.

[/code]
(25-02-2017 15:55)SP7EZG napisał(a):  Nie denerwuj się proszę....

Bez obawy, nie denerwuje się... Lubię swoją wiedzę przekazywać innym.

73 Paweł
(Ten post był ostatnio modyfikowany: 25-02-2017 17:07 przez SQ8MVY.)
25-02-2017 16:41
Znajdź wszystkie posty użytkownika Odpowiedz cytując ten post
Odpowiedz 


Skocz do:


Użytkownicy przeglądający ten wątek: 7 gości