Skip to content

Arduino library helping creation of DIY consoles for MaSzyna Train Simulator (aka EU07)

License

Notifications You must be signed in to change notification settings

marcinn/maszynaduino

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

37 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

maszynaduino

experimental

Maszynaduino jest biblioteką dla Arduino (Uno, Mega, etc) ułatwiającą oprogramowanie pulpitów budowanych na potrzeby symulatora MaSzyna (aka EU07).

Biblioteka posiada obiektowy interfejs i ułatwia korzystanie z analogowych multiplekserów umożliwiających obsługę większej ilości kontrolek, przełączników i mierników, niż fizycznie posiadają mikrokontrolery.

Możliwości

  • obiektowy interfejs
  • szeregowa konsola do diagnostyki
  • wsparcie dla analogowych multiplekserów (typu 74HC4067)
  • obsługa kontrolek i przełączników
  • prostota użycia i czytelność
  • kompatybilność z MaSzyną wysyłającą preambułę w komunikacji UART (cztery bajty 0xEF na początkach ramek wejść i wyjść)

Pierwsze kroki

Użycie biblioteki należy rozpocząć od załadowania plików nagłówkowych:

#include "maszynaduino.h"

W dalszej części (przed setup() i loop()) trzeba zadeklarować kontrolki, przełączniki i sam pulpit. Przykładowo przełącznik baterii podłączony do portu 2 można zadeklarować następująco:

#define PIN_BATERIA 2

Switch *bateria = new PinSwitch(PIN_BATERIA, 0, 2)

Parametry konstruktora PinSwitch są następujące:

  • nr pinu
  • nr bajtu ramki wyjścia (tu: 0, liczony bez preambuły)
  • nr bitu do gaszenia / zapalania (tu: 2)

Do pinu 3 podłączymy kontrolkę lampki czuwaka:

#define PIN_LAMPKA_CZUWAK 3

Indicator *lampkaCzuwaka = new PinIndicator(PIN_LAMPKA_CZUWAK, 4, 6);

Parametry konstuktora PinIndicator są następujące:

  • nr pinu
  • nr bajtu ramki wejścia (tu: 4, liczony bez preambuły)
  • nr bitu określającego stan kontrolki (tu: 6)

W następnym kroku należy utworzyć pulpit określając szeregowy port do komunikacji:

Console *sm42 = new Console(&Serial);

W funkcji setup() należy dodać do pulpitu utworzone przełącznik i kontrolkę, oraz zainicjować pulpit.

void setup() {
    sm42->addSwitch(bateria);           // dodanie przełącznika baterii
    sm42->addIndicator(lampkaCzuwaka);  // dodanie kontrolki czuwaka
    sm42->setup();                      // zainicjowanie pulpitu
}

W funkcji loop() należy dodać aktualizację pulpitu oraz transmisję danych:

void loop() {
    sm42->update();            // aktualizacja pulpitu
    sm42->transmit();          // komunikacja Pulpit <-> PC
}

Aby przykład zadziałał w MaSzynie, w pliku eu07_input-uart.ini, musi pojawić się adekwatny wpis:

2 toggle batteryenable batterydisable

Kompletny przykład:

#include "maszynaduino.h"

#define PIN_BATERIA 2
#define PIN_LAMPKA_CZUWAK 3

Switch *bateria = new PinSwitch(PIN_BATERIA, 0, 2);
Indicator *lampkaCzuwaka = new PinIndicator(PIN_LAMPKA_CZUWAK, 4, 6);

Console *sm42 = new Console(&Serial);


void setup() {
  sm42->addSwitch(bateria);
  sm42->addIndicator(lampkaCzuwaka);
  sm42->setup();
}

void loop() {
  sm42->update();
  sm42->transmit();
}

Schemat połączeń

Do przełączników nie trzeba podłączać rezystorów ściągających, ponieważ Maszynaduino domyślnie konfiguruje wejścia w trybie INPUT_PULLUP (z rezystorami podciągającymi wbudowanymi w Arduino). W razie potrzeby dowolny przełącznik można skonfigurować bez użycia rezystora podciągającego - biblioteka zadba o prawidłową interpretację stanu wejścia.

maszynaduino-example-01

Transmisja danych

W tej chwili Console konfiguruje port szeregowy na 57600 bodów (bez możliwości zmiany), i taką prędkość należy ustawić w eu07.ini w MaSzynie.

Elementy interfejsu programistycznego

Uwaga. Do wydania wersji 1.0 API biblioteki może się zmieniać bez zachowania kompatybilności.

Główne klasy i struktury

Klasa Opis
PinSwitch przełącznik podłączony bezpośrednio do pinu mikrokontrolera
MuxSwitch przełącznik podłączony przez multiplekser
PinIndicator kontrolka podłączona bezpośrednio do pinu mikrokontrolera
Console obiekt opisu i obsługi pulpitu (może być zdefiniowanych wiele pulpitów)
Mux obsługa pojedynczego multipleksera
ConsoleDebug konsola debugowania podłączana do portu szeregowego
Struktura Opis
InputFrame struktura opisująca ramkę wejśc z symulatora (PC)
OutputFrame struktura opisująca ramkę wyjść do symulatora (PC)

Ramki InputFrame i OutputFrame

struct InputFrame {
    uint8_t preamble[4];       // 0-3
    uint16_t tacho;             // 4-5
    uint8_t indicator0;        // 6
    uint8_t indicator1;        // 7
    uint8_t indicator2;        // 8
    uint8_t indicator3;        // 9
    uint8_t indicator4;        // 10
    uint16_t break_pressure;    // 11-12
    uint16_t pipe_pressure;     // 13-14
    uint16_t tank_pressure;     // 15-16
    uint16_t hv_voltage;        // 17-18
    uint16_t hv_current1;       // 19-20
    uint16_t hv_current2;       // 21-22
    uint16_t hv_current3;       // 23-24
    uint16_t year_month;        // 25-26
    uint16_t day_hour_minute;   // 27-28
    uint16_t second_milisecond; // 29-30
    uint32_t odometer;          // 31-34
    uint16_t lv_voltage;        // 35-36
    uint8_t radio_channel;     // 37
    uint8_t unused[14];        // 38-51
};
struct OutputFrame {
    uint8_t preamble[4];
    uint8_t switch0;
    uint8_t switch1;
    uint8_t switch2;
    uint8_t switch3;
    uint8_t switch4;
    uint8_t switch5;
    uint8_t master_controller;
    uint8_t second_controller;
    uint16_t train_brake;
    uint16_t independent_brake;
    uint8_t unused[4];
};

KLasa Console

InputFrame* Console::getInputs();        // odczyt stanu wejść (ostatnio odebrane)
OutputFrame* Console::getOutputs();      // odczyt stanu wyjść (do wysłania)
void addSwitch(Switch *);                // dodanie przełącznika
void addIndicator(Indicator *indicator); // dodanie kontrolki 
void setup();                            // inicjalizacja
void update();                           // aktualizacja przełączników, kontrolek, mierników, itp
void transmit();                         // odebranie i wysłanie danych z/do PC

Konstruktor:

Console(HardwareSerial *serial);
Console(HardwareSerial *serial, Switch **switches, int switchesCount);
Console(HardwareSerial *serial, Switch **switches, int switchesCount, Indicator **indicators, int indicatorsCount);

Przełączniki i kontrolki można podać jako tablice bez konieczności dodawania ich pojedynczo w setup(). Ekwiwalentem dla przykładu z dokumentacji będzie:

Indicator *kontrolki[] = {lampkaCzuwaka};
Switch *hebelki[] = {bateria};

Console *sm42 = new Console(
    &Serial,
    hebelki, ARRAY_LENGTH(hebelki),
    kontrolki, ARRAY_LENGTH(kontrolki)
);

void setup() {
    sm42->setup();
}    

ARRAY_LENGTH jest typowym makrem definiowanym przez bibliotekę.

Użycie multiplekserów

Uwaga. Interfejs obsługi multiplekserów może się zmienić przed wydaniem wersji 1.0

Aby zwiększyć liczbę I/O należy zastosować multiplekser (jeden lub więcej). Biblioteka testowana jest o popularny układ 74HC4067, 16-to kanałowy analogowy multiplekser.

W celu opisania multipleksera wpiętego w układ należy utworzyć instancję klasy Mux z opisem użytych pinów, a przy tworzeniu instancji przełączników lub kontrolek użyć klas dedykowanych dla multipleksera.

Zakładając, że mamy jeden multiplekser wpięty do pinów:

  • 2: pin "enable" multipleksera
  • 3: pin "data" multipleksera
  • 4, 5, 6, 7: piny sterujące "S0-S3" multipleksera, w kodzie programu należy zdefiniować multiplekser następująco:
// Mux(int pinEnable, int pinData, int pinS0, int pinS1, int pinS2, int pinS3);

Mux* mux1 = new Mux(2, 3, 4, 5, 6, 7);

a przełącznik baterii z przykładu należałoy zdefiniować następująco:

// MuxSwitch(Mux *mux, int channel, int nrBajtuRamki, int nrBitu);

Switch *bateria = new MuxSwitch(mux1, MUX_CH1, 0, 2);

Ponieważ multiplekser zajął pin 3, to lampkę czuwaka (z przykładu) należałoby podłączyć do innego pinu (np. 8). To wszystkie zmiany, które należy wprowadzić w celu przeniesienia przełącznika na multiplekser.

Konsola debugowania

Maszynaduino posiada prostą konsolę szeregową do ułatwienia debugowania. Konsolę można podłączyć pod dowolny port szeregowy wpierany przez Arduino.

maszynaduino_consoledebug

// Pulpit będzie komunikował się z PC podstawowym portem (`Serial`)
Console *sm42 = new Console(&Serial);  

// Konsola debugowania będzie używała portu `Serial1`
ConsoleDebug *debug = new ConsoleDebug(sm42, &Serial1);

void setup() {
    sm42->setup();
    debug->setup();
}

void loop() {
    sm42->update();
    sm42->transmit();

    // wysłanie debug output na konsolę debugowania
    debug->send();
}

Aby wykorzystać dodatkowe porty szeregowe do debugowania, konieczna będzie płytka obsługująca większą liczbę portów szeregowych (typu Arduino Mega, Arduino Due) oraz adapter USB.

usb-ttl-serial-adapter

Konsolę debugowania można też uruchomić także na urządzeniach z jednym portem szeregowym (typu Arduino Uno). W tej sytuacji nie powino się transmitować danych z/do PC (za pomocą Console::transmit()), bo zaburzy to dzialanie konsoli. Transmisję danych warto wtedy uruchamiać warunkowo. Przykład:

#define DEBUG

#ifdef DEBUG
ConsoleDebug *debug = new ConsoleDebug(sm42, &Serial);
#endif

void setup() {
  // ...
#ifdef DEBUG
    debug->setup();
#endif
  // ...
}

void loop() {
  // ...
#ifdef DEBUG
    debug->send();
#else
    sm42->update();
    sm42->transmit();
#endif
  // ...
}

Transmisja

Ponieważ konsola debugowania wysyła polecenia terminala do "czyszczenia" ekranu, zalecane jest korzystanie z Putty lub Screena zamiast Serial Monitora wbudowanego w Arduino IDE. Przykładowo:

screen /dev/ttyACM0 57600

Transmisja konsoli debugowania wymaga ustawienia prędkości na 57600 bodów. W przyszłości będzie możliwa zmiana.

Plan rozwoju

1.0

  • przełączniki (bezpośrednio do pinów)
  • przełączniki (przez multiplekser)
  • kontrolki (bezpośrednio do pinów)
  • kontrolki (przez multiplekser)
  • przełączniki wielopozycyjne
  • wskaźniki / mierniki (direct i mux)
  • ułatwienie obsługi wielu multiplekserów (do 4 szt, common data i select)
  • optymalizacje, użycie przerwań, ewentualna przebudowa i stabilizacja API

1.1

  • gotowe rozwiązania dla mierników, manometrów (np. servo)

Sugestie i pytania

Pytania i sugestie proszę wpisywać za pomocą https://github.com/marcinn/maszynaduino/issues

FAQ

Czy można korzystać z biblioteki za darmo?

Tak.

Czy mogę budować swoje produkty w oparciu o nią?

Tak, ale z zachowaniem zasad licencji GPL v3.0 (w skrócie - powstały produkt także musi być tak samo licencjonowany i dystrybuowany).

Biblioteka nie posiada bardzo potrzebnej funkcji.

Należy opisać problem, sugestię lub zapotrzebowanie za pomocą https://github.com/marcinn/maszynaduino/issues.

About

Arduino library helping creation of DIY consoles for MaSzyna Train Simulator (aka EU07)

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages