Konfiguracja portu COM:
Standardowa ramka UART -> 8 bitów danych, 1 bit stopu, bez kontroli parzystości i przepływu
Prędkość można ustawiać w pliku eu07.ini. Ja używam 0,5Mbps (przejściówka UART-USB).
Jak działa transmisja:
Transmisję rozpoczyna PC-et wysyłając pierwszy bajt danych. Mikrokontroler od razu odsyła pierwszy bajt danych.
Drugi bajt danych z PC - drugi bajt danych z uKontrolera itd.
Jeżeli uKontrolerowi skończą się dane do wysłania to tylko odbiera.

- link aktywny będzie w przyszłości
Pogrubione elementy już działają i są przeze mnie przetestowane:
Przesyłane Bajty:
z PC-ta:
1B: prędkość w km/h bez cyfr po przecinku
2B: wyjścia cyfrowe
3B: wyjścia cyfrowe
4B: wyjścia cyfrowe
5B: wyjścia cyfrowe -> ogrzewanie składu, jazda na oporach, poślizg, żaluzje wentylatorów, -, -, czuwak, SHP
6B: wyjścia cyfrowe -> stycz.liniowe, różnicowy obw. pomocniczych, nadmiar. przetwornicy, róznicowy obw. gł, nadm. silników, WS, zanik prądu przy jeździe na oporach, nadmiar. sprężarki
7B: wyjścia cyfrowe -> Hasler: 1 i 2 bit rysik1, 3 i 4 bit rysik2, 5 rysik3, -, -, brzęczyk SHP
8B: wyjście PWM1 - cylinder hamulcowy - młodsze bity
9B: wyjście PWM1 - cylinder hamulcowy - starsze bity
10B: wyjście PWM2 - przewód główny - młodsze bity
11B: wyjście PWM2 - przewód główny - starsze bity
12B: wyjście PWM3 - zbiornik główny - młodsze bity
13B: wyjście PWM3 - zbiornik główny - starsze bity
14B: wyjście PWM4 - amperomierz 1 grupy silników - młodsze bity
15B: wyjście PWM4 - amperomierz 1 grupy silników - starsze bity
16B: wyjście PWM5 - amperomierz 2 grupy silników - młodsze bity
17B: wyjście PWM5 - amperomierz 2 grupy silników - starsze bity
18B: wyjście PWM6 - amperomierz 3 grupy silników - młodsze bity
19B: wyjście PWM6 - amperomierz 3 grupy silników - starsze bity
20B: wyjście PWM7 - woltomierz WN - młodsze bity
21B: wyjście PWM7 - woltomierz WN - starsze bity
22B: wyjście PWM8 - kanał wolny - młodsze bity
23B: wyjście PWM8 - kanał wolny - starsze bity
24B: wyjście PWM9 - kanał wolny - młodsze bity
25B: wyjście PWM9 - kanał wolny - starsze bity
26B: wyjście PWM10 - kanał wolny - młodsze bity
27B: wyjście PWM10 - kanał wolny - starsze bity
28B: wyjście PWM11 - kanał wolny - młodsze bity
29B: wyjście PWM11 - kanał wolny - starsze bity
30B: wyjście PWM12 - kanał wolny - młodsze bity
31B: wyjście PWM12 - kanał wolny - starsze bity
z uKontrolera (pulpitu):
1B: wejścia cyfrowe -> puste, wyłącznik WS-a, impuls zał. WS, odblok. silników trakc., puste, odblok nadmiar. przetwornicy i ogrzewania poc., wył. styczników lin., kasowanie CA/SHP
2B: wejścia cyfrowe -> puste, przetwornica, sprężarka, piasecznica(?), ogrzewanie składu, przełącznik hamowania, przełącznik hamowania, rozruch wysoki/niski
3B: wejścia cyfrowe -> patyk1, patyk2, przyhamowanie przy poślizgu, przyciemnienie świateł lok, przyciemnienie świateł lok, odluźniacz, syrena wysoka, syrena niska
4B: wejścia cyfrowe -> bateria, puste
5B: wejścia cyfrowe -> puste
6B: wejścia cyfrowe -> puste
7B: wejście cyfrowe -> puste
8B: pozycja nastawnika od 0
9B: pozycja bocznika od 0
10B: wejście analogowe1 - hamulec zasadniczy - młodsze bity
11B: wejście analogowe1 - hamulec zasadniczy - starsze bity
12B: wejście analogowe2 - hamulec pomocniczy - młodsze bity
13B: wejście analogowe2 - hamulec pomocniczy - starsze bity
14B: wejście analogowe3 - kanał wolny - młodsze bity
15B: wejście analogowe3 - kanał wolny - starsze bity
16B: wejście analogowe4 - kanał wolny - młodsze bity
17B: wejście analogowe4 - kanał wolny - starsze bity
Jak widać wszystko było robione pod ET22 ale nie widzę powodu, żeby w wolne miejsca powrzucać do innych loków.
Jak może ktoś zauważył, część opisanych przełączników i kontrolek MaSzyna jeszcze nie obsługuje ale miejsce na nie już jest zarezerwowane ;)
Aktualizacja 2016.11.14 0850:
Rainsted obsługuje wybór komunikacji po porcie COM (feedbackmode 5).
Co się stanie gdy będę chciał otworzyć port COM a takiego nie będzie lub nie będzie podpięty sprzęt do komputera? - Komunikacja po porcie zostanie wyłączona i będzie można normalnie sterować z klawiatury.
Aktualizacja 2016.11.16 1905:
Zmiana ramki danych: 12 PWM-ów 16 bitowych i 4 kanały ADC max 16 bitowe. Uaktualnienie w exe i tekście wyżej już niedługo.
Aktualizacja 2016.11.19 1900:
Zmiana rozdzielczości ADC i PWM do max 16bitów. Aktualizacja ramki i funkcji pinów
Aktualizacja 2016.11.20 2300:
Kolejna aktualizacja danych: prędkość przeniesiona na pierwszy bajt, zmiana przesyłania starszych i młodszych bitów danych 16 bitowych - aktualizacja exe
Aktualizacja 2016.11.21 1200
Były drobne błędy we wcześniejszym exe. Teraz wszystko już działa jak powinno. Zaznacze pogrubieniem to, co już działa
Aktualizacja 2016.11.21 1800
Aktualizacja exe - mierniki działają w odpowiedniej kolejności.
Aktualizacja 2016.11.23 2030
Właśnie napisałem w jaki sposób można się połączyć z komputerem za pomocą mikrokontrolera. Dodatkowo wrzuciłem prosty program do testowania transmisji bez potrzeby włączania MaSzyny. Teraz każda nowa aktualizacja będzie pogrubiona dla większej czytelności. Zapraszam do dyskusji poniżej!
Aktualizacja 2016.12.16 1645
Dodany wpis mwdinputenable do pliku eu07.ini
Aktualizacja 2017.05.13 1540Udostępnienie pliku MWD-dokumentacja.xls - dokumentacja interfejsu.
Kilka słów jak przyłączyć się do projektu jako tester i zbudować własny pulpit (lub choćby sam kontroler):
Co będzie potrzebne? Podstawowa znajomość mikrokontrolerów (obsługa UART) i przejściówka UART-USB :) Przejściówkę można kupić na np allegro już za 7 zł (bez przesyłki). Podłączając przejściówkę należy zacząć od masy (GND) - masę mikrokontrolera podłączyć z masą przejściówki, TXD do RXD oraz RXD do TXD - linie te odpowiadają za przesyłanie danych między komputerem (za pośrednictwem przejściówki) a mikrokontrolerem.
Na wstępie napiszę, że program został tak napisany, że nie blokuje klawiatury. Jedyne co na razie może nam blokować klawiaturę to krany hamulców ale je możemy wyłączyć w pliku eu07.ini zmieniając tekst obok mwdbreakenable z yes na 0 lub no ;)
Pierwszym krokiem jest zaprogramowanie mikrokontrolera w taki sposób, żeby odbierał dokładnie tyle danych ile znajduje się w ramce oraz odsyłał dokładnie tyle samo danych (mogą być zera). Dane najprościej zapisywać do tablicy 8-bitowej ( zmienna 8-bitowa - 1 Bajt). Tablica powinna mieć wymiar przynajmniej taki ile mamy bajtów danych - 31 bajty (na dzisiejszy dzień - 23.11.2016). Jeżeli będziemy chcieli także wysyłać dane zwrotne to przyda nam się druga tablica przynajmniej 17 bajtowa. Ze względu na większą prostotę (moim zdaniem) odbierania danych na temat lampek, manometrów i innych wskaźników skupię się na odbieraniu danych.
Jeżeli piszemy w C to najprościej zadeklarować i zainicjalizować je np w taki sposób:
uint8_t TablicaZPC[31] = {0}, TablicaDoPC[17] = {0};
Zmienne te dobrze jest umieścić poza ciałem głównej funkcji jako zmienne globalne (warto napisać przed deklaracją słowo "volatile").
Dla bardziej wtajemniczonych "kodopisarzy" polecam użycie struktur.
Jak widać, od razu zeruje ich wartości żeby nie było problemów np: przesyłamy cały czas jakąś przypadkową wartość i symulator trzyma nam wciśnięty przycisk kasowania CA/SHP.
W jaki sposób odebrać dane? Jestem przyzwyczajony do ATMEG więc na nich oprę swój "poradnik":
Najprościej napisać nasz program w taki sposób aby działał sekwencyjnie. Oznacza to, że program będzie wykonywał zadanie po zadaniu bez skoków "w bok" np do przerwań. Podstawową sprawą w każdym programie jest inicjalizacja zmiennych i konfigurowanie peryferiów układu (wejścia/wyjścia, timery, PWM-y itd...). Tym jednak zajmiemy się na końcu, a zaczniemy od sprawdzenia co w ogóle będzie nam potrzebne przez napisanie części kodu.
Kolejną ważną rzeczą w programie jest pętla nieskończona. W niej umieścimy odbieranie danych, wysyłanie danych, odczyt wartości z klawiszy i przetwornika ADC oraz sterowanie wyjściami.
Tak jak wspomniałem wcześniej, nasz kod będzie wykonywał się sekwencyjnie. Pierwszym krokiem jest odbiór i wysyłanie danych. Musimy pamiętać, że naszym obowiązkiem jest odebrać
WSZYSTKIE bajty z komputera i wysłać
WSZYSTKIE bajty, na które komputer będzie czekał. To czy wykorzystamy wszystkie dane, które odebraliśmy lub uzupełnimy wszystkie bajty, które powędrują do komputera nie jest już istotne. W zależności od mikrokontrolera nasz kod może się nieco różnić, np atmega32 ma tylko jeden układ USART (korzystamy z jego wersji asynchronicznej - UART) ale np już inna atmega może mieć dwa! Wtedy rejestry, których będziemy używać będą nazywać się inaczej, mianowicie będą miały swoje numerki (np UDR-atmega32 i UDR0-atmega168). W nocie (datasheet) układu znajdziemy przykładowe kody, które możemy wykorzystać w naszym programie:
- inicjalizacja UART - wykonujemy tylko RAZ przed wejściem w pętlę główną programu
- odbiór bajtu danych
- nadawanie bajtu danych
Na razie skupmy się nad komunikacją: musimy odebrać 31 bajtów i od razu wysłać 17. Możemy to zrobić w następujący sposób:
for(i=0; i<31; i++) //pętla umożliwiająca wysłanie 31 bajtów danych
{
while (!(UCSRA & (1<<RXC)); //czekamy na odebranie bajtu danych
TablicaZPC[i] = UDR; //zapis danych do naszej tablicy
if (i < 17) //zabezpiecznie, żeby nie wysłać za dużo danych do komputera
{
while (!(UCSRA & (1<<UDRE))); //sprawczanie czy już wysłano wcześniejsze dane (czekanie na wysłanie danych)
UDR = TablicaDoPC[i]; // wysłanie danych do komputera
}
}
W taki oto prosty sposób wysłaliśmy i odebraliśmy wszystkie niezbędne dane :)
Teraz zostaje nam tylko przetworzyć te dane według wiedzy wyżej (czyli który bit, którego bajtu odpowiada) i wyrzucenie tych informacji np na wyjście mikrokontrolera.
Teraz wracamy do kodu przed główną pętlą (nieskończoną - while(1)) i inicjalizujemy UART zgodnie z wytycznymi na początku wątku.
Teraz poniżej możemy wykonywać resztę czynności takich jak odczyt przycisków i zapisywanie ich do tablicy lub czytać z tablicy i "świecić" odpowiednimi wyjściami mikrokontrolera. [/s]