Spisu treści:

Superszybkie napięcia analogowe z Arduino: 10 kroków (ze zdjęciami)
Superszybkie napięcia analogowe z Arduino: 10 kroków (ze zdjęciami)

Wideo: Superszybkie napięcia analogowe z Arduino: 10 kroków (ze zdjęciami)

Wideo: Superszybkie napięcia analogowe z Arduino: 10 kroków (ze zdjęciami)
Wideo: Podstawy Arduino, Odczyt Pinów Cyfrowych i Analogowych w Arduino, digitalRead, analogRead 2024, Lipiec
Anonim
Image
Image

Ta instrukcja pokazuje, jak generować superszybkie zmiany napięcia analogowego z Arduino i prostej pary rezystorów i kondensatorów. Jedną z aplikacji, w której jest to przydatne, jest generowanie grafiki na oscyloskopie. Jest kilka innych projektów, które to zrobiły. Johngineer pokazuje prostą choinkę wykorzystującą modulację szerokości impulsu (PWM). Inni ulepszyli ten projekt, używając drabinki rezystorowej lub dedykowanego układu przetwornika cyfrowo-analogowego.

Korzystanie z PWM powoduje duże migotanie, podczas gdy użycie drabinki rezystorowej lub przetwornika cyfrowo-analogowego wymaga większej liczby pinów wyjściowych i komponentów, które mogą nie być łatwo dostępne. Obwód, którego używam, to ten sam martwy, prosty rezystor i para kondensatorów, który zastosowano w demo choinki, ale działa ze znacznie mniejszym migotaniem.

Najpierw przeprowadzę Cię przez proces budowania obwodu. Następnie nauczę Cię, jak dodać własny obraz. Na koniec przedstawię teorię, co przyspiesza.

Jeśli podobał Ci się ten Instructable, rozważ zagłosowanie na niego!:)

Krok 1: Budowanie obwodu

Budowanie obwodu
Budowanie obwodu

Aby zbudować obwód, będziesz potrzebować:

a) Arduino oparte na Atmel 16MHz ATmega328P, takie jak Arduino Uno lub Arduino Nano.

b) Dwa rezystory o wartości R co najmniej 150Ω.

c) Dwa kondensatory o wartości C takie, że C = 0,0015/R, przykłady:

  • R = 150Ω i C = 10µ
  • R = 1,5kΩ i C = 1µ
  • R = 15kΩ i C = 100nF
  • R = 150kΩ i C = 10nF

Powody wyboru tych wartości są dwojakie. Przede wszystkim chcemy utrzymać prąd na pinach Arduino poniżej maksymalnego prądu znamionowego 40mA. Zastosowanie wartości 150Ω ogranicza prąd do 30mA przy zasilaniu Arduino napięciem 5V. Większe wartości R zmniejszą prąd i dlatego są akceptowalne.

Drugim ograniczeniem jest to, że chcemy, aby stała czasowa, będąca iloczynem R i C, wynosiła około 1,5 ms. Oprogramowanie zostało specjalnie dostrojone do tej stałej czasowej. Chociaż w oprogramowaniu można dostosować wartości R i C, istnieje wąski zakres, wokół którego będzie działać, więc wybieraj komponenty jak najbliżej sugerowanego stosunku.

Dokładniejsze wyjaśnienie, dlaczego stała RC jest ważna, zostanie podane w części teoretycznej, po tym, jak pokażę ci, jak zmontować obwód demonstracyjny.

Krok 2: Konfiguracja oscyloskopu

Konfiguracja oscyloskopu
Konfiguracja oscyloskopu

Demonstracja wymaga oscyloskopu ustawionego w trybie X/Y. Przewody pomiarowe należy podłączyć tak, jak pokazano na schemacie. Twój oscyloskop będzie się różnić od mojego, ale przejdę przez niezbędne kroki, aby ustawić tryb X/Y na moim urządzeniu:

a) Ustaw przemiatanie w poziomie, które ma być kontrolowane przez kanał B (oś X).

b) Ustaw oscyloskop w tryb dwukanałowy.

c) Ustaw wolty/działkę na obu kanałach, aby mógł wyświetlać napięcia od 0V do 5V. Ustawiłem mój na 0.5V/dz.

d) Ustaw tryb sprzęgania na DC na obu kanałach.

e) Dostosuj położenie X i Y tak, aby kropka znajdowała się w lewym dolnym rogu ekranu, gdy Arduino jest wyłączone.

Krok 3: Pobierz i uruchom oprogramowanie

Image
Image

Pobierz oprogramowanie z repozytorium Fast Vector Display For Arduino. Oprogramowanie jest objęte licencją GNU Affero Public License v3 i może być swobodnie używane i modyfikowane na warunkach tej licencji.

Otwórz plik „fast-vector-display-arduino.ino” w Arduino IDE i prześlij do Arduino. Przez chwilę na ekranie oscyloskopu pojawi się animacja „Szczęśliwego Nowego Roku”.

Opracowałem ten projekt jako osobisty hackaton w tygodniach poprzedzających Boże Narodzenie, więc jest wiadomość o tematyce świątecznej i noworocznej, którą możesz zobaczyć, modyfikując zmienną PATTERN w kodzie.

Krok 4: Stwórz własny niestandardowy rysunek

Zrozum, dlaczego PWM jest tak powolny
Zrozum, dlaczego PWM jest tak powolny

Jeśli chcesz stworzyć własny rysunek, możesz wkleić współrzędne punktu do szkicu Arduino na linii, która definiuje USER_PATTERN.

Odkryłem, że Inkscape to całkiem dobre narzędzie do tworzenia niestandardowych rysunków:

  1. Twórz tekst, używając dużej, pogrubionej czcionki, takiej jak Impact.
  2. Wybierz obiekt tekstowy i wybierz „Obiekt do ścieżki” z menu „Ścieżka”.
  3. Wybierz pojedyncze litery i nałóż je, aby utworzyć połączony kształt
  4. Wybierz „Połączenie” z menu „Ścieżka”, aby połączyć je w jedną krzywą.
  5. Jeśli w dowolnych literach są dziury, wytnij małe nacięcie rysując prostokąt za pomocą narzędzia Prostokąt i odejmij go od konturu za pomocą narzędzia „Różnica”.
  6. Kliknij dwukrotnie ścieżkę, aby wyświetlić węzły.
  7. Prostokąt zaznacz wszystkie węzły i kliknij narzędzie „Utwórz wybrane węzły narożne”.
  8. Zapisz plik SVG.

Ważne jest, aby Twój rysunek miał jedną zamkniętą ścieżkę i nie zawierał dziur. Upewnij się, że Twój projekt ma mniej niż około 130 punktów.

Krok 5: Wklej współrzędne z pliku SVG do Arduino IDE

  1. Otwórz plik SVG i skopiuj współrzędne. Zostaną one osadzone w elemencie „path”. Pierwszą parę współrzędnych można zignorować; zastąp je 0, 0.
  2. Wklej współrzędne do szkicu Arduino w nawiasach tuż po „#define USER_PATTERN”.
  3. Zastąp wszystkie spacje przecinkami, w przeciwnym razie otrzymasz błąd kompilacji. Pomocne może być narzędzie „Zamień i znajdź”.
  4. Skompiluj i uruchom!
  5. Jeśli masz problemy, obserwuj konsolę szeregową pod kątem błędów. W szczególności zobaczysz komunikaty, jeśli twój wzorzec ma zbyt wiele punktów dla wewnętrznego bufora. W takich przypadkach obraz będzie wykazywał nadmierne migotanie.

Krok 6: Zrozum, dlaczego PWM jest tak wolny

Na początek przyjrzyjmy się zachowaniu kondensatora podczas ładowania.

Kondensator podłączony do źródła napięcia Vcc zwiększy napięcie zgodnie z krzywą wykładniczą. Ta krzywa jest asymptotyczna, co oznacza, że będzie zwalniać w miarę zbliżania się do napięcia docelowego. Ze względów praktycznych napięcie jest „wystarczająco zbliżone” po 5 sekundach RC. RC nazywa się „stałą czasową”. Jak widzieliśmy wcześniej, jest to iloczyn wartości rezystora i kondensatora w twoim obwodzie. Problem w tym, że 5 RC to dość długi czas na aktualizację każdego punktu na wyświetlaczu graficznym. Prowadzi to do dużego migotania!

Kiedy używamy modulacji szerokości impulsu (PWM) do ładowania kondensatora, nie jesteśmy w lepszej sytuacji. Dzięki PWM napięcie zmienia się szybko między 0V a 5V. W praktyce oznacza to, że szybko naprzemiennie wpychamy ładunek do kondensatora i wyciągamy go trochę z powrotem – to pchanie i ciągnięcie przypomina raczej przebiegnięcie maratonu poprzez zrobienie dużego kroku do przodu, a następnie małego kroku do tyłu w kółko.

Kiedy uśredniasz to wszystko, zachowanie ładowania kondensatora za pomocą PWM jest dokładnie takie samo, jak gdybyś użył stałego napięcia Vpwm do ładowania kondensatora. Nadal potrzebujemy około 5 sekund RC, aby "dostatecznie zbliżyć się" do pożądanego napięcia.

Krok 7: Przejdź od a do B, odrobinę szybciej

Przejdź od a do B, odrobinę szybciej
Przejdź od a do B, odrobinę szybciej

Załóżmy, że mamy kondensator, który jest już naładowany do Va. Załóżmy, że używamy analogWrite() do wypisania nowej wartości b. Jaki jest minimalny czas oczekiwania na osiągnięcie napięcia Vb?

Jeśli zgadłeś 5 sekund RC, to świetnie! Po odczekaniu 5 sekund RC kondensator zostanie naładowany do prawie Vb. Ale jeśli chcemy, możemy poczekać trochę krócej.

Spójrz na krzywą ładowania. Widzisz, kondensator był już w Va, kiedy zaczynaliśmy. Oznacza to, że nie musimy czekać na czas t_a. Musielibyśmy to zrobić tylko wtedy, gdybyśmy ładowali kondensator od zera.

Więc nie czekając tego czasu, widzimy poprawę. Czas t_ab jest w rzeczywistości nieco krótszy niż 5 RC.

Ale trzymaj się, możemy zrobić o wiele lepiej! Spójrz na całą tę przestrzeń nad v_b. To jest różnica między Vcc, maksymalnym dostępnym nam napięciem, a Vb, które zamierzamy osiągnąć. Czy widzisz, jak to dodatkowe napięcie może pomóc nam szybciej dotrzeć tam, gdzie chcemy?

Krok 8: Przejdź z punktu a do punktu B z turboładowarką

Podróżuj z punktu a do punktu B dzięki turbo ładowarce!
Podróżuj z punktu a do punktu B dzięki turbo ładowarce!

Zgadza się. Zamiast używać PWM przy docelowym napięciu V_b, utrzymujemy go na stałym poziomie Vcc przez znacznie, znacznie krótszy okres czasu. Nazywam to metodą Turbo Charger i pozwala nam dotrzeć tam, gdzie chcemy naprawdę, bardzo szybko! Po opóźnieniu czasowym (które musimy obliczyć) hamujemy przełączając się na PWM na V_b. Dzięki temu napięcie nie przekroczy celu.

Dzięki tej metodzie możliwa jest zmiana napięcia w kondensatorze z V_a na V_b w ułamku czasu niż przy użyciu samego PWM. W ten sposób zdobywasz miejsca, kochanie!

Krok 9: Zrozum kod

Zrozum Kodeks
Zrozum Kodeks

Obraz jest wart tysiąca słów, więc diagram pokazuje dane i operacje, które są wykonywane w kodzie. Od lewej do prawej:

  • Dane graficzne są przechowywane w PROGMEM (czyli pamięci flash) jako lista punktów.
  • Każda kombinacja operacji translacji, skalowania i rotacji jest łączona w afiniczną macierz transformacji. Odbywa się to raz na początku każdej klatki animacji.
  • Punkty są odczytywane jeden po drugim z danych graficznych i każdy z nich jest mnożony przez zapisaną macierz transformacji.
  • Przekształcone punkty są podawane przez algorytm nożycowy, który przycina wszystkie punkty poza widocznym obszarem.
  • Korzystając z tabeli wyszukiwania opóźnienia RC, punkty są konwertowane na napięcia sterujące i opóźnienia czasowe. Tablica wyszukiwania opóźnienia RC jest przechowywana w pamięci EEPROM i może być ponownie użyta do wielu przebiegów kodu. Podczas uruchamiania tabela przeglądowa RC jest sprawdzana pod kątem dokładności, a wszelkie nieprawidłowe wartości są aktualizowane. Zastosowanie EEPROM pozwala zaoszczędzić cenną pamięć RAM.
  • Napięcia sterujące i opóźnienia są zapisywane w nieaktywnej ramce w buforze ramki. Bufor ramki zawiera miejsce na ramkę aktywną i ramkę nieaktywną. Po zapisaniu pełnej ramki, nieaktywna ramka staje się aktywna.
  • Procedura obsługi przerwań nieustannie rysuje obraz poprzez odczytywanie wartości napięcia i opóźnień z aktywnego bufora ramki. Na podstawie tych wartości dostosowuje cykle pracy pinów wyjściowych. Timer 1 służy do pomiaru opóźnienia czasowego z dokładnością do kilku nanosekund, natomiast timer 2 służy do sterowania cyklem pracy kołków.
  • Pin o największej zmianie napięcia jest zawsze „turbodoładowany” z cyklem pracy zero lub 100%, zapewniając najszybszy czas ładowania lub rozładowania. Sworzeń o mniejszej zmianie napięcia jest napędzany z cyklem pracy wybranym tak, aby pasował do czasu przejścia pierwszego pinu - tym razem dopasowanie jest ważne, aby zapewnić, że linie są rysowane prosto na oscyloskopie.

Krok 10: Z dużą szybkością wiąże się wielka odpowiedzialność

Ponieważ ta metoda jest o wiele szybsza niż PWM, dlaczego analogWrite() jej nie używa? Cóż, ponieważ używanie tylko PWM jest wystarczająco dobre dla większości programów i jest o wiele bardziej wybaczające. Metoda „Turbo Charger” wymaga jednak starannego kodowania i jest odpowiednia tylko w określonych przypadkach:

  1. Jest niezwykle wrażliwy na czas. Gdy osiągniemy docelowy poziom napięcia, pin sterujący musi natychmiast zostać przełączony w zwykły tryb PWM, aby uniknąć przekroczenia docelowego napięcia.
  2. Wymaga znajomości stałej RC, więc wartości te należy wprowadzić wcześniej. Przy błędnych wartościach rozrząd będzie błędny i napięcia będą nieprawidłowe. Przy zwykłym PWM masz gwarancję, że po pewnym czasie osiągniesz prawidłowe napięcie, nawet jeśli stała RC nie jest znana.
  3. Obliczenie dokładnego przedziału czasowego ładowania kondensatora wymaga równań logarytmicznych, które są zbyt wolne dla obliczeń w czasie rzeczywistym na Arduino. Muszą one być wstępnie obliczone przed każdą ramką animacji i zapisane gdzieś w pamięci podręcznej.
  4. Programy zajmujące się tą metodą muszą borykać się z faktem, że opóźnienia są bardzo nieliniowe (w rzeczywistości są wykładnicze). Napięcia docelowe w pobliżu Vcc lub GND będą wymagały o wiele rzędów wielkości dłużej niż napięcia w pobliżu punktu środkowego.

Aby przezwyciężyć te ograniczenia, mój kod grafiki wektorowej wykonuje następujące czynności:

  1. Wykorzystuje Timer 1 przy 16kHz i procedurę obsługi przerwań do precyzyjnej manipulacji wyjściami i taktowania.
  2. Wymaga zastosowania określonej wartości stałej czasowej RC, ograniczając wybór wartości kondensatora i rezystora.
  3. Przechowuje opóźnienia czasowe dla wszystkich punktów w ramce animacji w buforze pamięci. Oznacza to, że procedura, która oblicza opóźnienia czasowe, działa znacznie wolniej niż procedura obsługi przerwań, która aktualizuje piny wyjściowe. Każdą klatkę można pomalować kilkadziesiąt razy, zanim nowy zestaw opóźnień dla kolejnej klatki będzie gotowy do użycia.
  4. Użycie bufora pamięci ogranicza liczbę punktów, które można narysować na klatkę. Używam kodowania wydajnego w przestrzeni, aby jak najlepiej wykorzystać dostępną pamięć RAM, ale nadal jest ograniczone do około 150 punktów. Powyżej około stu punktów wyświetlacz i tak zacznie migotać, więc jest to kwestia sporna!

Zalecana: