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
SP9MRN Offline
MAc
*****

Liczba postów: 817
Dołączył: 29-08-2009
Post: #121
RE: Fork-Heńka... czyli jak sobie poradzić z DDS za pomocą ARDUINO
Doceniam doceniam :-)
Jeżeli chodzi o odpowiedź, to "wiem ale nie powiem" żeby nie psuć zabawy :-)
W celach edukacyjnych zwrócę jednak uwagę na pojęcia:
"skończy się",
"przekręci się"
oraz na to, co w rzeczywistości dzieje się z liczbami jak licznik "dochodzi do końca".
Można sobie nawet na kartce zasymulować licznik liczący np do pięciu i zastanowić się PO CO korzystamy z licznika i jakie dane z niego (po przetworzeniu) wykorzystujemy.

miłej zabawy
MAc
mrn
31-10-2014 10:34
Odwiedź stronę użytkownika Znajdź wszystkie posty użytkownika Odpowiedz cytując ten post
SQ9MDD Offline
Rysiek
****

Liczba postów: 380
Dołączył: 01-02-2009
Post: #122
RE: Fork-Heńka... czyli jak sobie poradzić z DDS za pomocą ARDUINO
No masz rację Mac. prawidłowa nomenklatura to rzecz ważna...

No dobrze zanim pójdziemy dalej w naszych pracach nad Złomkiem, proponuję wykonać proste ćwiczenie.
Na początek napiszemy sobie kawałek kodu by sprawdzić co dzieje się gdy licznik się przepełnia. Zrobimy to na przykładzie zmiennej typu integer. Zmienna ta jak wiemy jest przechowywana w dwóch bajtach czyli maksymalna jej wartość to 32767 a wartość minimalna -32768, kod wygląda następująco:

Kod:
int licznik = 32750;

void setup(){
  Serial.begin(9600);
}

void loop(){
  Serial.println(licznik);
  licznik++;
  delay(1000);  
}

Tak przygotowany program, wgrywamy do arduino i w monitorze portu szeregowego obserwujemy co się dzieje.
Wartość "licznik" ustawiłem celowo na samym końcu zakresu tak by było widać co się stanie z jego wartością w momencie przepełnienia i by nie musieć czekać długo na efekt.

Następnie zrobimy to samo ćwiczenie ale dla zmiennej typu: unsigned int.
Kod wyglada bardzo podobnie:

Kod:
int unsigned licznik = 65525;

void setup(){
  Serial.begin(9600);  
}

void loop(){
  Serial.println(licznik);
  licznik++;
  delay(1000);  
}

Ciekaw jestem czy efekty są takie jak podejrzewaliscie/oczekiwaliście.

...przede wszystkim nie zakłócać...
02-11-2014 11:17
Odwiedź stronę użytkownika Znajdź wszystkie posty użytkownika Odpowiedz cytując ten post
SP6IFN Offline
Ryszard
****

Liczba postów: 455
Dołączył: 23-03-2010
Post: #123
RE: Fork-Heńka... czyli jak sobie poradzić z DDS za pomocą ARDUINO
Ale fajna......odjazdowa zabawa. Programiści wiedzieli co się stanie, ale ja niestety....nie. Ale już wiem....pouczające doświadczenie...Tongue
Rysio!
02-11-2014 13:31
Odwiedź stronę użytkownika Znajdź wszystkie posty użytkownika Odpowiedz cytując ten post
SP9MRN Offline
MAc
*****

Liczba postów: 817
Dołączył: 29-08-2009
Post: #124
RE: Fork-Heńka... czyli jak sobie poradzić z DDS za pomocą ARDUINO
Bardzo śliczny przykład Ryśka chytrze poprzekręcam (mając w tym paskudny cel)

Kod:
//Wyobraźmy sobie, że  "licznik" to "millis"
// specjalnie używamy "char" bo się szybko "przekręca" - liczy tylko do 255 :-)
//pamiętajmy, że używamy "unsigned char" - bo zwraca nam liczby od 0-255
//w odróżnieniu od "char", które zwróci nam znaki ascii

unsigned char licznik = 0;

void setup(){
  Serial.begin(9600);
delay(500);  
}

void loop(){
  Serial.println(licznik);
  licznik++;
  delay(50);  
}

Zamiana "int" na "unsigned char" ma swój ukryty cel - ale o tym w następnym odcinku

MAc
// *****************

No to następny kawałek :-)
Dla wyjaśnienia - "charami" posługujemy się wyłącznie dlatego, że są jednobajtowe, czyli dziesiętnie przyjmują wartość od 0 do 255, co pozwala nam kilkakrotnie "przewinąć licznik" w sensownym czasie.

Jeżeli dla eksperymentu do tego co mieliśmy wcześniej dołączymy wywołanie i funkcję smetra, to serialmonitor pokaże nam co się dzieje z działaniem funkcji po przewinięciu licznika.
Otóż licznik już po pierwszym przekroczeniu 255 zaczyna głupieć.

Tyle tylko, że w naszym przypadku nie ma to większego znaczenia - od czasu do czasy sprawdzi smeter trochę "gęściej" i tyle. Niewykluczone nawet, że tego nie zrobi, bo sama funkcja smetra zajmuje trochę czasu, co spowoduje "przeskoczenie" licznika millis().
Tego się nie da niestety zasymulować (chyba, że ktoś wymyśli jak) - prosty "delay()" nie pomaga, bo wstrzymuje też funkcję symulującą millis()
Podsumowując - wygląda na to, że trzeba zostawić złomka na półtora miesiąca i zobaczyć :-)


Kod:
//Wyobraźmy sobie, że  "counter" to "millis"
// specjalnie używamy "char" bo się szybko "przekręca"
unsigned char licznik = 0;
unsigned char s_metr_update_time = 0;
unsigned char currentlicznik = 0;
unsigned char s_metr_update_interval=50;

void setup() {
   Serial.begin(9600);
   delay(500);  
   Serial.println("Zaczynamy...");
}
void loop() {
   for (int x=0; x<1000; x++) { // parę razy przekręcić unsigned char od 0 do 255
// ******* to counter udaje millis()
       licznik++; // powiększa się()
       Serial.println(licznik);
// ******
    show_smetr();  
   }
Serial.println("koniec!");
while(1); // koniec wysylania na serialport
}

void show_smetr(){
  
        if(licznik >= s_metr_update_time){ // czy już wyświetlić?
         Serial.println("Update smeter"); //albo cokolwiek innego zaleznego od czasu
         s_metr_update_time = licznik + s_metr_update_interval;
      }
  
}


Idąc dalej.
Teraz nam to nie przeszkadza, ale może się zdarzyć, że (oczywiście edukacyjnie) będzie to miało znaczenie.
Co nam zatem zostaje?
Zastanowić się jak uniknąć nieuniknionego.
Oszukać przeznaczenie. (1, 2, 3)

A może to wcale nie licznik nam się przewija?
Może sami coś przewijamy korzystając z licznika?

Miłej zabawy

MAc
mrn
(Ten post był ostatnio modyfikowany: 02-11-2014 22:22 przez SP9MRN.)
02-11-2014 18:22
Odwiedź stronę użytkownika Znajdź wszystkie posty użytkownika Odpowiedz cytując ten post
SP3JDZ Offline
Początkujący
**

Liczba postów: 92
Dołączył: 15-03-2014
Post: #125
RE: Fork-Heńka... czyli jak sobie poradzić z DDS za pomocą ARDUINO
Abstrahująć od liczników mam coś z innej beczki.
Zmieniłem obsługę enkodera.
Teraz ciężko jest przyłapać enkoder na przekłamaniach od drgań, no i przy szybkim kręceniu nie gubi impulsów. Kondensatory na wejściach obsługujących enkoder trzeba usunąć. Zmodyfikowałem wersję 1.0.11, ponieważ w wersji 1.0.13 RIT mi się sam włączał i różne takie...
Mała demonstracja działania enkodera:





Dodatkowa biblioteka Timer1:

.zip  TimerOne-r11.zip (Rozmiar: 11.22 KB / Pobrań: 746)

Zmieniony kod:

.zip  zlomek_1_0_11_PD_20141102.zip (Rozmiar: 6.45 KB / Pobrań: 766)

http://witec.pl
02-11-2014 23:15
Odwiedź stronę użytkownika Znajdź wszystkie posty użytkownika Odpowiedz cytując ten post
SQ9MDD Offline
Rysiek
****

Liczba postów: 380
Dołączył: 01-02-2009
Post: #126
RE: Fork-Heńka... czyli jak sobie poradzić z DDS za pomocą ARDUINO
Mac w sumie chodziło Ci o to że jeśli funkcja s-metr wykona się przykładowo na 50msec przed przepełnieniem licznika to kolejny czas jej uruchomienia wypadnie za 100msec czyli poza zakresem licznika. I pytanie jest takie czy stanie się cokolwiek złego.

Witku gratuluję zmian, wprowadziłeś alternatywną obsługę enkodera, muszę to w wolnej chwili przeanalizować.

A przy okazji czy ktoś stwierdził problemy z ostatnią wersją softu, którą sygnalizuje Witek?

...przede wszystkim nie zakłócać...
02-11-2014 23:54
Odwiedź stronę użytkownika Znajdź wszystkie posty użytkownika Odpowiedz cytując ten post
SP5IWI Offline
Janek
*

Liczba postów: 32
Dołączył: 01-02-2009
Post: #127
RE: Fork-Heńka... czyli jak sobie poradzić z DDS za pomocą ARDUINO
Ja nie mam,enkoder juz drugi model,poprzednio blokowalem kondensatorami teraz nie i dzala.Tylko ja testuje go co prawda czesto ale "na sucho",bez podlaczonego trxa.Wgrywam rozne wsady kombinuje ale takich przeklaman nie stwierdzilem
03-11-2014 10:02
Znajdź wszystkie posty użytkownika Odpowiedz cytując ten post
SP9MRN Offline
MAc
*****

Liczba postów: 817
Dołączył: 29-08-2009
Post: #128
RE: Fork-Heńka... czyli jak sobie poradzić z DDS za pomocą ARDUINO
Trochę zagmatwałem :-)
1. Na początku uznałem, że problem z przepełnieniem faktycznie jest poważny i znalazłem na niego lekarstwo.

2. Następnie postanowiłem edukacyjnie pokazać na czym ten problem polega.

3. Jak już napisałem kawałek kodu demonstracyjnego (celowo z "błędem) i zobaczyłem wyświetlane wartości, to wyszło mi, że w NASZYM KONKRETNYM PRZYPADKU fakt przepełniania się licznika millis() najprawdopodobniej nie ma żadnego praktycznego znaczenia.
Smeter będzie działał i PRAWDOPODOBNIE (ponieważ millis działa na przerwaniach) czas potrzebny na obsługę wyświetlania smetra spowoduje, że tych kilka "dzikich" pomiarów występujących po przepełnieniu licznika millis() - (a w demo po przekroczeniu 255) zniweluje się błyskawicznie.

4. muszę jeszcze sprawdzić, ale wygląda na to, że tych "nieoczekiwanych" pomiarów będzie w realnym działaniu kilkadziesiąt - dopóki się liczniki nie wyrównają.

5. Zadanie domowe Ryśka jest cały czas obowiązujące.

Generalnie chodzi o to, że my sami powodujemy przepełnienie naszej zmiennej:
"s_metr_update_time (unsigned long)"
za pomocą linijki:
s_metr_update_time = millis() + s_metr_update_interval;

w której do "kończącego się" licznika millis() (też unsigned long) dodajemy wartość "s_metr_update_interval"
Czyli - jak millis() będzie na 99 przed końcem a my dodamy 100, to millis() się jeszcze nie przepełni ale nasza wartość " s_metr_update_time" się przepełni (przekroczy zakres przewidziany dla zmiennej typu unsigned long") i zacznie przyjmować kolejne wartości od zera.

Podsumowując - żeby się woda nie przelała nie możemy dodawać nic do millis().
.....
ale możemy odejmować ;-)

MAc
mrn

Ale jazda
03-11-2014 11:48
Odwiedź stronę użytkownika Znajdź wszystkie posty użytkownika Odpowiedz cytując ten post
SQ5KVS Offline
Karol
*****

Liczba postów: 1,004
Dołączył: 26-09-2012
Post: #129
RE: Fork-Heńka... czyli jak sobie poradzić z DDS za pomocą ARDUINO
Ja mam "własną" metodę na czytanie enkodera, robię to w przerwaniu co około 7kHz (tak akurat się dzieli 16MHz/256/8), tam sprawdzam tylko podstawowe wejścia/wyjścia - przyciski, enkoder, ptt, coś tam jeszcze, bo musi być to szybkie.
Natomiast wszystkie potencjalnie czas-żerne rzeczy robię w pętli w "main" czyli przede wszystkim obsługa LCD.

Wszystkie wejścia są podciągnięte, i mają 10nF kondensatory.
Robiłem test, i po przekręceniu enkoderem kilkanaście razy szybko w lewo a potem dokładnie tyle samo w prawo, licznik enkodera pokazywał zero, i tak powinno być.
Kod:
//rozdzielczość x4, czyli na ząbek 4 "kroki", co bywa kłopotliwe, bo zadaniem ząbka jest "stabilizacja" enkodera w konkretnej pozycji. W innym miejscu to dziele /4
A = get_input(ENC_A);
B = get_input(ENC_B);
if (A!=pA){
    if (A==B)     enc_ticks++;
             else             
              enc_ticks--;            
    pA = A;
    }
  if (B!=pB) {
        if (A==B)  enc_ticks--;
            else
             enc_ticks++;            
    pB = B;    
}

Ale jak popatrzyłem na kod z biblioteki arduino:
Kod:
uint8_t s = state & 3;            
        if (get_input(ENC_A)) s |= 4;
        if (get_input(ENC_B)) s |= 8;
        
        switch (s) {
            case 0: case 5: case 10: case 15:
                break;
            case 1: case 7: case 8: case 14:
                enc_ticks--; break;
            case 2: case 4: case 11: case 13:
                enc_ticks++; break;
            case 3: case 12:
                enc_ticks -= 2; break;
            default:
                enc_ticks += 2; break;
        }
        state = (s >> 2);
}

To może ta metoda j.w. jest ciut lepsza. Musiałbym sprawdzić co szybciej się wykonuje.

Pozdrawiam
03-11-2014 13:07
Znajdź wszystkie posty użytkownika Odpowiedz cytując ten post
SP2IPT Offline
Jakub
***

Liczba postów: 233
Dołączył: 01-03-2012
Post: #130
RE: Fork-Heńka... czyli jak sobie poradzić z DDS za pomocą ARDUINO
Nie bawilem sie arduino, ale "klasycznie" switch jest szybszy niz if.

pz
03-11-2014 21:12
Znajdź wszystkie posty użytkownika Odpowiedz cytując ten post
Odpowiedz 


Skocz do:


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