W związku z tym, że płytka Atmega328 nie posiada konwertera cyfrowo analogowego to chciałbym zaprezentować jeden z najprostszych sposobów na jego wykonanie.
Zasada jego działania jest bardzo prosta. Do budowy wykorzystuje się rezystory o wartościach, jak sama nazwa wskazuje, równych R lub wartości podwojonej czyli 2R. Ilość wykonanych skoków pozwala na określenie jaką rozdzielczość będzie posiadał przetwornik. Na rysunku poniżej przetwornik 8 oraz 10 bitowy.
Rys. 1. Przetwornik 8 bitowy
Rys. 2. Przetwornik 10 bitowy
Jest to dosyć tania alternatywa dla przetworników scalonych w układach zewnętrznych. Wiadomo, że nie będzie to posiadało tak dobrej dokładności jak układ zewnętrzny, natomiast będzie od niego sporo tańsze. Dodatkowo każdy z "bitów" tego przetwornika odpowiada jednemu wyprowadzeniu mikrokontrolera. Co znacząco zmniejsza ilość pinów GPIO z układu. Zasada działania tego przetwornika opiera się na układaniu rezystorów w dzielniki napięć. Dodatkowo impedancja wyjściowa jest zawsze równa R.
Programowanie
Za każdym razem gdy chce się wygenerować odpowiednią wartość napięcia. Dzielenie rozpoczyna się od wartości 1/2 napięcia zasilającego czyli np 5V lub 3,3V. Dalej schodzi się odpowiednie 1/4, 1/8, 1/16, 1/32 itp. W celu otrzymania żądanej wartości napięcia można dokonać włączenia kilku linii, czyli np. połączyć 1/2 i 1/8 wartości napięcia.
Jak już wspomniałem wcześniej aktywacje danego elementu układu wykonuje się poprzez ustawienie stanu wysokiego na odpowiednim wyprowadzeniu.
Jak już wspomniałem wcześniej aktywacje danego elementu układu wykonuje się poprzez ustawienie stanu wysokiego na odpowiednim wyprowadzeniu.
Dane wyprowadzenia w celu otrzymania przebiegu należy cyklicznie włączać i wyłączać.
Jeśli chodzi o Arduino to program może wyglądać następująco:
- #define PIN0 0
- #define PIN1 1
- #define PIN2 2
- #define PIN3 3
- #define PIN4 4
- #define PIN5 5
- #define PIN6 6
- #define PIN7 7
- void setup() {
- pinMode(PIN0, OUTPUT);
- pinMode(PIN1, OUTPUT);
- pinMode(PIN2, OUTPUT);
- pinMode(PIN3, OUTPUT);
- pinMode(PIN3, OUTPUT);
- pinMode(PIN4, OUTPUT);
- pinMode(PIN5, OUTPUT);
- pinMode(PIN6, OUTPUT);
- pinMode(PIN7, OUTPUT);
- }
- void loop() {
- int i = 0;
- //Przebieg trójkątny
- for(i = 0; i<512; i++)
- set_data(i);
- for(i=510; i>0; i++)
- set_data(i);
- }
- //Wartosci zostaja ustawione poprzez cykliczne
- //Wlaczanie i
- void set_data(byte x)
- {
- digitalWrite(PIN0, x & (1<<7));
- digitalWrite(PIN1, x & (1<<6));
- digitalWrite(PIN2, x & (1<<5));
- digitalWrite(PIN3, x & (1<<4));
- digitalWrite(PIN4, x & (1<<3));
- digitalWrite(PIN5, x & (1<<2));
- digitalWrite(PIN6, x & (1<<1));
- digitalWrite(PIN7, x & 1);
- }
Dane dla innych przebiegów można wykonać przez odpowiednie dobranie punktów pomiarowych i odpowiednie zdefiniowanie jej w tablicy. Tak jak zostało to wykonane w przykładach dla STM32. Ta sama zasada tworzenia układu towarzyszy każdemu z rodzaju mikrokontrolera.
Sygnał możne zostać odpowiednio zmodulowany poprzez dodawanie bądź odejmowanie ilości próbek. Można też odczekać pewną ilość czasu. Dane wyjściowe z buffora można oczywiście odpowiednio wzmocnić poprzez zastosowanie wzmacniacza operacyjnego.