HomeMade

Pełna wersja: Sterowanie syntezą LM7001 z Arduino
Aktualnie przeglądasz uproszczoną wersję forum. Kliknij tutaj, by zobaczyć wersję z pełnym formatowaniem.
Stron: 1 2
Cytat:Widzisz dalej nie jest to jasne dla Ciebie. Dlaczego jeśli jest 0 to ma czekać ? Gdzie czeka ? i co czeka ?

No czeka, ustawia na porcie stan niski, i czeka (powinien - w domyślnej wersji programu) na takt CL. Po takcie CL synteza wie, który bit gdzie jest.

AND to koniunkcja. 1 i 1 = 1, ale 1 i 0 = 0. Dlatego if 'szuka' na numerze bitu (idx) wartości 1, jeśli 1 to stan wysoki, jeśli 0 stan niski.

Postać zapisu 0x0001 nie ma znaczenia, bo i to i tak jedynka, obojętnie od zapisu.

Dzięki za PW. Gdy będę miał warunki sprzyjające (w domu mam słaby internet) z przyjemnością się odezwę.
(25-02-2017 17:07)SP7EZG napisał(a): [ -> ][quote]Widzisz dalej nie jest to jasne dla Ciebie. Dlaczego jeśli jest 0 to ma

Postać zapisu 0x0001 nie ma znaczenia, bo i to i tak jedynka, obojętnie od zapisu.

Oj nie do końca nie ma znaczenia. Tak 0x01, czy 0x0001 to jest tylko 1.
Tylko zwróć uwagę na jedną rzecz. Na typ danych !!!

0x01 to liczba 8 bitowa - uint8_t
0x0001 to liczba 16 bitowa - uint16_t

W tak prostym przykładzie pewnie nie ma to znaczenia czy będzie 0x01 czy 0x0001. Ale w rozbudowanych obliczeniach może napsuć krwi, bo kompilator będzie nieraz robił niejawne rzutowania typów danych.

Sam jestem bardzo początkującym w języku C, ale miałem już (nie)przyjemność szukać takich drobnostek związanymi z typami danych.
Ale odbiegamy chyba od tematu LM7001 troszkę...
Kod:
#define DATA 7
#define CL 6
#define CE 5


uint16_t Fpom = 1;
int Sterowanie = 255 ; //25 kHz10100000


void setup() {
pinMode(DATA, OUTPUT);
pinMode(CL, OUTPUT);
pinMode(CE, OUTPUT);
synteza();

}


void loop() {

}


void synteza(){
  
digitalWrite(CE, HIGH);
for( uint8_t idx=0; idx<14; idx++ ) //wysyłanie 14 bitów częstotliwości
{
   if ( ( Fpom >> idx ) & 0x0001 )
   {
      digitalWrite(DATA, HIGH);         // Pin DATA ustawiamy na 1
   } else
   {
      digitalWrite(DATA, LOW) ;         // Pin DATA ustawiamy na 0
   }
   zegarek(); // Generujemy impuls na linii CL
}
    digitalWrite(DATA, LOW); //wysłanie T0
    zegarek();
    digitalWrite(DATA, LOW); //wysłanie T1
    zegarek();
    
for( uint8_t idy=0; idy<8; idy++ ) //wysyłanie 14 bitów częstotliwości
{
   if ( ( Sterowanie >> idy ) & 0x01 )
   {
      digitalWrite(DATA, HIGH);        
   } else
   {
      digitalWrite(DATA, LOW) ;        
   }
   zegarek();
   digitalWrite(DATA, LOW);
}
  
   digitalWrite(CE, LOW);
  
  
}


void zegarek(){
  digitalWrite(CL, LOW);
  delay(10);
  digitalWrite(CL, HIGH);
  delay(10);
  digitalWrite(CL, LOW);
  delay(10);
}

I teraz problem w drugą stronę. Sterowanie przechodzi tylko jako postać dziesiętna korzystając z tej pętelki.
(25-02-2017 18:55)SP7EZG napisał(a): [ -> ][code]
....
uint16_t Fpom = 1;
int Sterowanie = 255 ; //25 kHz10100000

....
....

...Sterowanie przechodzi tylko jako postać dziesiętna....

Nie rozumiem co miałeś na myśli z tą postacią dziesiętną..
Ale po kolei..

Wytłumacz mi, dlaczego Fpom ma wartość 1 ?

Sterowanie zadeklaruj jako uint8_t. Typ int jest tu bardzo na wyrost, a na dodatek jest to typ ze znakiem. Nie potrzeba w tym przypadku marnować pamięci.
Na dodatek zdajesz sobie sprawę, że wartość dziesiętna 255 to nie jest to samo co 0b10100000. Chyba, że komentarz został przez przypadek...

0b10100000 = 0xA0 = 160

Znasz sposoby zapisu w C liczb w postaci binarnej i szesnastkowej ?

zapis szesnastkowy poprzedzamy 0x,
zapis binarny - 0b,
oraz dziesiętny - bez żadnych dodatków.

Tak więc :
255 dzisiętnie, to 0xFF szesnastkowo oraz 0b11111111 w postaci binarnej.
Nie nie, nie sugeruj się zupełnie.

W komentarzu była wartość taka jak być powinna dla 25kHz, ale obie wartości były typowo dla próby. Podłączyłem w miejsce linii diody tak, by móc obserwować i liczyć bity.

255 binarnie to 11111111, więc od 17 bitu linia Data powinna świecić ciurkiem, i tak też się dzieje. CL ma 10 ms przesunięcia tak jak być powinno wg noty katalogowej.

Póki co wszystko jest okej, zaczynam się wdrażać w temat ustawiania kroku i częstotliwości.
Nie mogę sobie poradzić z hardware'owym problemem debouncingu enkodera, musze chyba wykorzystać inną bibliotekę.

Kod:
uint8_t Sterowanie = 0b10100000; //25 kHz10100000
]for( uint8_t idy=0; idy<8; idy++ ) //wysyłanie 14 bitów częstotliwości
{
   if ( ( Sterowanie << idy ) & 0x0001 )
   {
      digitalWrite(DATA, HIGH);        
   } else
   {
      digitalWrite(DATA, LOW) ;        
   }
   zegarek();
   digitalWrite(DATA, LOW);
}
  
   digitalWrite(CE, LOW);


Wygląda na to, że wartość nie jest zapisywana poprawnie. Na pin jest podawana jakby od najmłodszego bitu do najstarszego.



Pozdrówki.
(25-02-2017 20:34)SP7EZG napisał(a): [ -> ]
Kod:
.......
   if ( ( Sterowanie << idy ) & 0x0001 )
......

Wygląda na to, że wartość nie jest zapisywana poprawnie.

Wcale się nie dziwię. Masz w wyrażeniu babola. Dlaczego przestawiłeś kierunek przesuwania bitów << w lewo ?? Jakiś konkretny cel miałeś ??

Jeżeli chcesz bity przesuwać w lewo to powinno to wyglądać tak:
Kod:
if( ( Sterowanie << idy ) & 0x8000 )
{....

Napisałem coś takiego na podstawie dokumentacji LM7001. Sprawdź sobie, bo mogą być błędy.
Kod:
#define DATA 7
#define CL 6
#define CE 5

#define KROK_100K 0b00000000
#define KROK_50K  0b00000100
#define KROK_25K  0b00000010
#define KROK_5K   0b00000110

#define StartFreq       5394        //StartFreq=(145550-10700)/25=5394


void setup()
{
  pinMode(DATA, OUTPUT);
  pinMode(CL, OUTPUT);
  pinMode(CE, OUTPUT);

  digitalWrite(CL, LOW);
  digitalWrite(CE, LOW);
  digitalWrite(DATA, LOW);

  synteza( StartFreq, KROK_25K );
}


void loop() {

}


void synteza( uint16_t Fpom, uint8_t krok )
{
  Fpom &= 0x3fff;  // Tu zadbamy o to, by bity 15 i 14 były zawsze wyzerowane

  uint32_t sterowanie = ( (uint32_t)1<<23 ) | ( (uint32_t)krok<<20 ) | ( (uint32_t)7<<16 ) | Fpom ;
  
  digitalWrite(CE, HIGH);

  for( uint8_t idx=0; idx<24; idx++ )
  {
    if( ( sterowanie >> idx ) & 0x00000001 )
    {
      digitalWrite(DATA, HIGH);        
    } else
    {
      digitalWrite(DATA, LOW) ;        
    }
    zegarek();
  }
  digitalWrite(CE, LOW);
  digitalWrite(DATA, LOW);
}


void zegarek()
{
  delay(10);
  digitalWrite(CL, HIGH);
  delay(10);
  digitalWrite(CL, LOW);
  delay(10);
}

Nie posiadam tego LM-a, więc są to moje przemyślenia. Kompiluje się prawidłowo. Działać chyba też powinno.

Funkcja synteza przyjmuje 2 parametry. Obliczony dzielnik dla częstotliwości, oraz krok strojenia.
W środku jest składana kompletna ramka, która jest wysyłana..

Co do enkodera. Tu najlepiej użyć przerwań, tak jak to jest zrobione w oryginale i koniecznie trzeba podłączyć enkoder poprzez prosty filtr RC.
Odpadnie wówczas problem z drganiem styków - jeżeli to enkoder mechaniczny.
Nie zapomnij oglądnąć i poczytać ten poradnik dotyczący enkodera

Gorąco polecam również pozostałe poradniki Pana Kardasia, bo widzę, że jesteś na samym początku drogi nauki programowania....
Witaj,


Na chwilę obecną funkcja sterująca syntezą wygląda tak


Kod:
void synteza(int frequency_to_dds){
  
  uint8_t Sterowanie;

switch (step_value)
{
  case 100:
  Sterowanie = 0b00000001;
  break;
  
  case 25:
  Sterowanie = 0b00000101;
  break;

   case 1:
  Sterowanie = 0b00001001;
  break;
}

pinMode(DATA, OUTPUT);
pinMode(CL, OUTPUT);
pinMode(CE, OUTPUT);
digitalWrite(CE, HIGH);
for( uint8_t idx=0; idx<14; idx++ ) //wysyłanie 14 bitów częstotliwości
{
   if ( ( frequency_to_dds >> idx ) & 0x0001 )
   {
      digitalWrite(DATA, HIGH);         // Pin DATA ustawiamy na 1
   } else
   {
      digitalWrite(DATA, LOW) ;         // Pin DATA ustawiamy na 0
   }
   zegarek(); // Generujemy impuls na linii CL
}
    digitalWrite(DATA, LOW); //wysłanie T0
    zegarek();
    digitalWrite(DATA, LOW); //wysłanie T1
    zegarek();
    
for( uint8_t idy=0; idy<8; idy++ ) //wysyłanie 8 bitów konfigu
{
   if ( ( Sterowanie >> idy ) & 0x0001 )
   {
      digitalWrite(DATA, HIGH);        
   } else
   {
      digitalWrite(DATA, LOW) ;        
   }
   zegarek();
   digitalWrite(DATA, LOW);
}
  
   digitalWrite(CE, LOW);

  
  
}

void zegarek(){
  digitalWrite(CL, LOW);
  delayMicroseconds(3);
  digitalWrite(CL, HIGH);
  delayMicroseconds(3);
  digitalWrite(CL, LOW);
  delayMicroseconds(3);
}


Została wypisana do Złomka z forum, głównie dlatego, że miałem podobną infrastrukturę, oraz chciałem złożyć próbny układ
Oczywiście się nie synchronizował.

Rzecz jasna książkę Pana Kardasia zamawiam jeszcze w tym tygodniu.
Witaj,

Widzisz, już powoli coś powstaje. Klocuszek po klocuszku.
Najważniejsze przy tym jest logiczne myślenie.

Złomek więc dostaje obsługę nowego VCO....

Co do kroku strojenia. Domyślną częstotliwością dla LM7001 jest chyba 7.2MHz. Aby uzyskać krok 8.33kHz trzeba ustawić krok w LM7001 na 9kHz i obniżyć odrobinę częstotliwość kwarcu. O jaką wartość trzeba obniżyć - metoda prób i błędów.
Tak! Póki co rozmontowałem układ (płytka stykowa) Niestety, jedyny dostępny pod ręką 5 MHz. Nie mam pewności, czy to czasami nie dlatego...
Zmontuję porządnie cały układ, uruchomię generator na NE602, i będę próbował, bo docelowo ma to pracować z heterodyną prostego odbiornika Airband.

Dziękuję Ci serdecznie za pomoc, naprawdę zmotywowałeś mnie do nauki C.
Stron: 1 2
Przekierowanie