Odpowiedz 
 
Ocena wątku:
  • 6 Głosów - 4 Średnio
  • 1
  • 2
  • 3
  • 4
  • 5
Fork-Heńka... czyli jak sobie poradzić z DDS za pomocą ARDUINO
SQ9MDD Offline
Rysiek
****

Liczba postów: 380
Dołączył: 01-02-2009
Post: #27
RE: Fork-Heńka... czyli jak sobie poradzić z DDS za pomocą ARDUINO
Hejka Panowie... mam nadzieję że jesteście z nami, bo coś ucichło.

W dzisiejszym odcinku ogarniania arduino i DDS-a zajmiemy się zmianą kroku syntezy.
No bo co to za synteza jak by kroku się zmienić nie dało. Wink

W poprzednich wersjach krok był zapisany na sztywno i stanowił 100Hz. Wyglądało to tak że po wykryciu ząbka na enkoderze do bieżącej wartości częstotliwości dodawaliśmy lub odejmowaliśmy 100Hz:

Kod:
czestotliwosc = czestotliwosc + 100;

czestotliwosc = czestotliwosc - 100;

Teraz będziemy to robić nieco inaczej:

Kod:
frequency = frequency + step_value;

frequency = frequency - step_value;

Oczywiście by to zadziałało musimy zmienną "step_value" wcześniej zadeklarować:

Kod:
long step_value = 100;

Zmienna ta jest typu long by uniknąć niespodzianek nieoczekiwanej konwersji typu zmiennych.

Ok mamy zmienną która przechowa wartość kroku syntezy ale musimy napisać obsługę zmiany tego kroku. Zrobimy to za pomocą wejścia A2. Oczywiście każdy może użyć dowolnego innego wejścia.
Po pierwsze musimy zdefiniować zmienną która przechowa numer używanego przez nas portu:

Kod:
const int step_input = A2;

Następnie w funkcji setup musimy ustawić odpowiedni typ wejścia:

Kod:
pinMode(step_input,INPUT_PULLUP);

I tutaj słowo wyjaśnienia, INPUT_PULLUP oznacza że wejście jest wewnętrznie podciągnięte do +5V więc łatwo wykryjemy zmianę stanu gdy zewrzemy je do masy.

Następny krok to stworzenie funkcji pokazującej bieżący krok syntezera:

Kod:
void show_step(){
  lcd.setFont(SmallFont);                     //ustawiamy czcionkę
  sprintf(buffor,"%08lu",step_value);         //konwersja danych do wyświetlenia (ładujemy longa do stringa
  lcd.print(buffor,CENTER,8);                 //wyświetlamy dane na lcd (8 oznacza drugi rząd)
}

A gdy już wszystko mamy gotowe musimy obsłużyć przyciśnięcie przycisku w pętli głównej programu:

Kod:
//obsługa klawisza zmiany kroku
  if(digitalRead(step_input) == LOW){     //sprawdzanie czy przycisk jest wcisnięty
   delay(100);                            //odczekajmy 100msec
    if(digitalRead(step_input) == LOW){   //jeśli klawisz nadal jest wcisnięty (czyli nie są to zakłócenia)
       switch(step_value){                //za pomocą instrukcji swich zmieniamy krok
          case 100000:                    //jeśli krok jest 100kHz ustaw 100Hz
            step_value = 100;
          break;
          case 10000:                     //jeśli krok jest 10kHz ustaw 100kHz
            step_value = 100000;
          break;
          case 1000:                      //jeśli krok jest 1kHz ustaw 10kHz
            step_value = 10000;
          break;
          case 100:                       //jeśli krok jest 100Hz ustaw 1kHz
            step_value = 1000;
          break;
       }
    }
    show_step();                          //pokazuję zmianę kroku na lcd
    delay(300);                           //zwłoka po zmianie kroku 300msec
  }

Używamy tutaj dwóch instrukcji if oraz instrukcji switch. Te dwie instrukcje if służą wykrywaniu wciśnięcia klawisza i eliminują drgania przycisku, natomiast instrukcja switch służy już konkretnie zmianie kroku.

Oczywiście sposób wyświetlania danych na wyświetlaczu nie jest idealny ale póki co zajmujemy się poprawnym ustawieniem mechanizmów pracy syntezera a kosmetykę zostawimy sobie na później.

Poniżej pełny kod po modyfikacjach i spakowane źródło.
Następny odcinek poświęcimy ograniczeniu pracy syntezera do zdefiniowanych widełek częstotliwości górnej i dolnej...


Kod:
//**************************************************​**********************//
// Złomek - kumpel Heńka, projekt pogladowy obsługi DDS AD9850,
// wyświetlacza nokii 5110 i jakiegoś enkodera.
// Projekt otwarty http://sp-hm.pl
// SQ9MDD -  początkowy szkielet programu v 1.0.0
// S_____ -
// S_____ -
//
//**************************************************​**********************//
/* CHANGELOG (nowe na górze)
2014.10.14 - zmiana kroku syntezy
2014.10.12 - początek projektu wspólnego na sp-hm.pl
wymiana biblioteki wyświetlacza lcd na LCDD5110 basic
2014.05.22 - pierwsza wersja kodu warsztaty arduino w komorowie.  
*/
//**************************************************​**********************//
//podłączamy bibliotekę syntezera
#include <AH_AD9850.h>

//podłączamy bibliotekę enkodera
#include <RotaryEncoder.h>;

//podłączamy bibliotekę do obsługi wyświetlacza
#include <LCD5110_Basic.h>

//inicjalizujemy komunikację z syntezerem
//syntezer   - arduino
//CLK        - PIN 8
//FQUP       - PIN 9
//BitData    - PIN 10
//RESET      - PIN 11
AH_AD9850 AD9850(8, 9, 10, 11);

// inicjalizujemy wyświetlacz
// lcd    - arduino
// sclk   - PIN 7
// sdin   - PIN 6
// dc     - PIN 5
// reset  - PIN 3
// sce    - PIN 4
LCD5110 lcd(7,6,5,3,4);
extern uint8_t SmallFont[]; //czcionka z biblioteki
extern uint8_t MediumNumbers[];//czcionka z biblioteki

//inicjalizujemy enkoder
//AO - w lewo
//A1 - w prawo
//nalezy pamiętać o kondensatorach (100nF) pomiędzy liniami encodera a masą
RotaryEncoder encoder(A0,A1,5,6,1000);

//zmienne do modyfikacji
const int kontrast = 70;                     //kontrast wyświetlacza
const int pulses_for_groove = 2;             //ilość impulsów na ząbek enkodera zmienić w zależności od posiadanego egzemplarza
const int step_input = A2;                   //wejście do podłączenia przełącznika zmiany kroku

//zmienne wewnętrzne,
//jeśli nie trzeba proszę nie modyfikować
char buffor[] = "              ";            //zmienna pomocnicza do wyrzucania danych na lcd
long frequency = 10000000;                   //zmienna dla częstotliwości, wstawiamy tam częstotliwość od której startujemy
long step_value = 100;                       //domyślny krok syntezy
int enc_sum = 0;                             //zmienna pomocnicza do liczenia impulsów z enkodera

//funkcja do zmiany kroku syntezy

//funkcja do obsługi wyświetlania zmiany częstotliwości
void show_frequency(){
  lcd.setFont(SmallFont);                    //ustawiamy czcionkę
  sprintf(buffor,"%08lu",frequency);         //konwersja danych do wyświetlenia (ładujemy longa do stringa
  lcd.print(buffor,CENTER,0);                //wyświetlamy dane na lcd
}

//funkcja do wyświetlania aktualnego kroku syntezera
void show_step(){
  lcd.setFont(SmallFont);                     //ustawiamy czcionkę
  sprintf(buffor,"%08lu",step_value);         //konwersja danych do wyświetlenia (ładujemy longa do stringa
  lcd.print(buffor,CENTER,8);                 //wyświetlamy dane na lcd (8 oznacza drugi rząd)
}

// setup funkcja odpalana przy starcie
void setup(){  
  Serial.begin(9600);                          //uruchamiam port szeregowy w celach diagnostycznych
  AD9850.set_frequency(0,0,frequency);        //odpalamy syntezer i ustawiamy częstotliwość startową
  delay(1000);                                //sekunda opóźnienia
  lcd.InitLCD(kontrast);                      //odpalamy lcd ustawiamy kontrast
  show_frequency();                           //pokazmy cos na lcd
  pinMode(step_input,INPUT_PULLUP);           //inicjalizujemy wejście zmiany kroku i podciągamy je do plusa
  show_step();
}

void loop(){  
  int enc = encoder.readEncoder();        //czytamy wartość z encodera
  if(enc != 0) {                          //jeśli wartość jest inna niż zero sumujemy
    enc_sum = enc_sum + enc;              //jeden ząbek encodera to +2 lub -2 tutaj to zliczam
    Serial.println(enc);                  //wyrzucamy na port rs-232 wartość licznika enkodera (debugowanie)
  }
  
  //obsługa klawisza zmiany kroku
  if(digitalRead(step_input) == LOW){     //sprawdzanie czy przycisk jest wcisnięty
   delay(100);                            //odczekajmy 100msec
    if(digitalRead(step_input) == LOW){   //jeśli klawisz nadal jest wcisnięty (czyli nie są to zakłócenia)
       switch(step_value){                //za pomocą instrukcji swich zmieniamy krok
          case 100000:                    //jeśli krok jest 100kHz ustaw 100Hz
            step_value = 100;
          break;
          case 10000:                     //jeśli krok jest 10kHz ustaw 100kHz
            step_value = 100000;
          break;
          case 1000:                      //jeśli krok jest 1kHz ustaw 10kHz
            step_value = 10000;
          break;
          case 100:                       //jeśli krok jest 100Hz ustaw 1kHz
            step_value = 1000;
          break;
       }
    }
    show_step();                          //pokazuję zmianę kroku na lcd
    delay(300);                           //zwłoka po zmianie kroku 300msec
  }
  
  //jesli zaliczyliśmy ząbek dodajemy lub odejmujemy do częstotliwości wartość kroku (na razie na sztywno 100Hz)
  if(enc_sum >= pulses_for_groove){
    frequency = frequency + step_value;  //docelowo frequency = frequency + krok

    AD9850.set_frequency(frequency);  //ustawiam syntezę na odpowiedniej częstotliwości
    show_frequency();                     //drukuję częstotliwość na wyświetlaczu za pomocą gotowej funkcji
    enc_sum = 0;                          //reset zmiennej zliczającej impulsy enkodera
  }
  if(enc_sum <= -(pulses_for_groove)){
    frequency = frequency - step_value;  //docelowo frequency = frequency - krok      
    AD9850.set_frequency(frequency);  //ustawiam syntezę na odpowiedniej częstotliwości
    show_frequency();                     //drukuję częstotliwość na wyświetlaczu za pomocą gotowej funkcji      
    enc_sum = 0;                          //reset zmiennej zliczającej impulsy enkodera
  }  
  delayMicroseconds(5);                    //małe opóźnienie dla prawidłowego działania enkodera
}


Załączone pliki
.zip  zlomek_v_1_0_2-141014a.zip (Rozmiar: 2.31 KB / Pobrań: 1092)

...przede wszystkim nie zakłócać...
14-10-2014 22:19
Odwiedź stronę użytkownika Znajdź wszystkie posty użytkownika Odpowiedz cytując ten post
Odpowiedz 


Wiadomości w tym wątku
RE: Fork-Heńka... czyli jak sobie poradzić z DDS za pomocą ARDUINO - SQ9MDD - 14-10-2014 22:19

Skocz do:


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