4. Drugi program – transmisja wartości ADC
Schemat nadajnika:

Schemat odbiornika:

Cały „myk” w tym programie polega na tym, aby przesłać zmienną wartość odczytu ADC, a następnie w odbiorniku zinterpretować ją jako „PWM”.
Program nadajnika:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
#include <VirtualWire.h> // dodaj bibliotekę obsługującą moduły RF int wartoscADC = 0; // utwórz zmienną, która będzie przechowywać wartość ADC int potencjometr = A0; // potencjometr podłączony do pinu A0 char adc[3]; // utworz tablice trzyznakową ADC void setup() { pinMode(potencjometr,INPUT); // definiujemy potencjometr jako wejście vw_set_tx_pin(11); // nadajnik RF podłączamy do pinu 12 vw_setup(2000); // ustawiamy prędkość transmisji Serial.begin(9600); } void loop() { wartoscADC = analogRead(A0)/ 4; Serial.println(wartoscADC); dtostrf(wartoscADC, 3, 0, adc); vw_send((uint8_t *)adc, strlen(adc)); // wyślij zawartość zmiennej ADC vw_wait_tx(); // poczekaj aż całość zostanie wysłana } |
Tworzymy zmienną, wartoscADC, która będzie przechowywać wartość z przetwornika A/C oraz trzyznakową tablicę adc. Następnie w pętli startowej- tak jak wcześniej- dodajemy informację do jakiego pinu podłączony jest nadajnik oraz z jaką prędkością odbywa się transmisja. W programie jak widać jest jeszcze zinterpretowana transmisja UART, w celu debugawania. Jeżeli chcesz to możesz ją zostawić, albo usunąć czy też skomentować te dwie linijki. Następnie w pętli głównej programu przypisujemy zmiennej wartoscADC odczyt z przetwornika A/C. Następnie dochodzimy do funkcji dtostrf(), która mówiąc w skrócie rozbija wartość liczby zmiennoprzecinkowej (typu float) lub liczby całkowitej (typu int) na pojedyncze znaki w systemie ASCII. Wartość ADC jest zwracana w liczbach całkowitych więc ta funkcja będzie dla nas przydatna. Aby ta funkcja zaistniała to musimy podać jej 4 argumenty:
|
1 2 3 4 5 6 |
dtostrf(zmienna, ilość_znakoów, ilość_znaków_po_przecinku, zmienna_tablicowa); //zmienna- zmienna z której wprowadzane są liczby całkowite, bądź zmiennoprzecinkowe //ilość_znaków- maksymalna ilość znaków, z której składa się zmienna //ilość_znaków_po_przecinku - ile znaków po przecinku ma zostać zbadane //zmienna_tablicowa- zmienna do której zostaną zapisane znaki ASCII |
Zatem jak widać, chcemy aby naszą zmienną wartoscADC rozbić na pojedyncze znaki ASCII. Maksymalna ilość znaków wynosi 3 (maksymalna wartość ADC 255), ilość znaków po przecinku 0. Po rozbiciu zapisz znaki do zmiennej tablicowej adc. Teraz nasze znaki musimy wysłać. Zatem robimy jak wcześniej czyli, wysyłamy tablicę znaków 8 bitową, ale o długości równej tej tablicy. Wiem, że może brzmi to dziwnie ale już tłumaczę. Funkcja strlen() zwraca długość łańcucha znaków, czyli naszej tablicy. Moglibyśmy oczywiście na stałe wpisać długość 3, jak to zrobiliśmy w przykładzie 1. tylko, że tam wysyłaliśmy jeden rodzaj danych, których długość się nie zmieniała, natomiast tutaj wartość zmienia się w zakresie od 1 do 3 znaków, zatem jest to swego rodzaju optymalizacja kodu. Pozostało nam zakończyć tutaj pętle główną oczekiwaniem na zakończenie transmisji. Na koniec pętli nie dałem żadnego opóźnienia, ponieważ chcemy aby jasność naszej diody zmieniała się z jak najmniejszym opóźnieniem i z jak największą płynnością.
Program odbiornika:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
#include <VirtualWire.h> // dodaj bibliotekę VirtualWire.h int dioda = 3; void setup() { pinMode(dioda,OUTPUT); analogWrite(dioda,0); Serial.begin(9600); // rozpocznij transmisję UART o prędkości 9600 baud vw_setup(2000); // ustal prędkość odbioru RF na 2000 baud vw_rx_start(); // rozpocznij transmisję RF vw_set_rx_pin(11); // odbiornik RF podłączony do pinu 11 } void loop() { uint8_t buf[VW_MAX_MESSAGE_LEN]; // definicja buforu odbioru danych uint8_t buflen = VW_MAX_MESSAGE_LEN; // oraz dlugości otrzymanych danych if (vw_get_message(buf, &buflen)) // jeżeli do buforu danych dotarły dane oraz // transmisja została zakończona i długość danych nie przekracza 8-bitów { int i; // utwórz zmienną i String odczytADC; // utwórz zmienną string dane for (i = 0; i < buflen; i++) // jeżeli wartość i < 0 to odbieraj znaki { odczytADC +=char(buf[i]); // do zmiennej string wprowadź wszystkie otrzymane znaki i je połącz } int PWM = atoi(odczytADC.c_str()); //utwórz zmienną PWM, a następnie przekonwertuj zmienną string na int Serial.println(PWM); analogWrite(dioda,PWM); //przypisz diodzie wartość zmiennej int PWM } } |
W odbiorniku robimy to samo co wcześniej, czyli ustalmy na jaki pin podłączamy odbiornik, z jaką prędkością ma się odbywać transmisja oraz sygnalizujemy gotowość do odbioru danych. W pętli głównej po sprawdzeniu, odebranych danych program przechodzi do utworzenia zmiennej „i” oraz zmiennej string odczytADC. W zmiennej odczytADC będą przechowywane odebrane wartości ADC z nadajnika. Następnie po połączeniu danych w jeden łańcuch znaków, tworzymy zmienną PWM (liczb całkowitych), której przypisujemy funkcję atoi():
|
1 2 |
atoi(zmienna_typu_String.c_str()); //zmienna_typu_String- wpisujemy tutaj nazwę zmiennej typu String |
Gdy już przekonwertujemy odczytADC na zmienną int to możemy przejść do zapalenia diody. W funkcji analogWrite() zapisujemy wartość PWM jako zmienną. Pewnie teraz się zastanawiacie czemu musieliśmy przekonwertować zmienną String na int. Jest to bardzo proste. Zmienna String zwraca nam ciąg znaków, czyli np. 200. Ale nie oznacza to że to jest liczba 200, tylko to są liczby 2, 0, 0 zapisane obok siebie. Natomiast zmienna int czyli liczby całkowite zwraca całą liczbę, czyli w tym przypadku liczbę 200. Więc ważnym było przekonwertować zmienną String na int. Po wgraniu programów powinniśmy otrzymać, taki efekt: