Skocz do zawartości

Arduino w modelarstwie kolejowym


Pomocna odpowiedź

10 minut temu, _LM_ napisał:

 czy to by oznaczało że cała strona musiałaby siedzieć w ESP? Ma to swoje zalety że jesteśmy niezależni od posiadanego sprzętu, tablet, pc i inne. No ale REST API to nie moja bajka.

Tylko API, całe UI+UX w aplikacji 😉 REST z zasady zwraca tylko i wyłącznie surowe dane w wybranej formie (np. JSON, ale może też wspierać kilka rodzajów danych np. XML lub JSON, a właściwy wybiera zgodnie z nagłówkami żądania).

No cóż, jeśli chcesz ręcznie implementować to co tcp zawiera natywnie (kolejność pakietów, potwierdzenia, powtórzenia) i jeszcze uważasz to za łatwiejsze to... no nie wiem...

Wiesz, napisałem o tym co ewentualnie umiałbym zrobić. Jak również nie chciałbym aby ta dyskusja schodziła złe tory. A jeśli chodzi o UDP mam napisany program do aktualizacji OTA esp8266 i musi być mocno zawalona sieć aby coś nie przeszło. TCP być może nie stanowi aż takiego wyzwania, no ale nigdy jakoś nie miałem okazji aby przetestować na swoich programikach. 

5 godzin temu, ethanak napisał:

To tyle na dzisiaj - dość duża przeróbka, więc na razie wystarczy

Wszystko działa jak należy na wyświetlaczu jest nazwa semafora i wyświetlany sygnał. po wciśnieciu '*' wyskakuje "zapisano"

sprawdziłem działanie zarówno na 0,91' jak i 0,94' i na obu jest ok

(edytowany)
9 minut temu, ethanak napisał:

A po wciśnięciu samej gwiazdki?

a po wciśnięciu samej gwiazdki pokazuje elegancko jako sygnał jest nadawany na każdym urządzeniu.

Pojawił się inny problem - LEDy nie reagują na  żadne komendy - świeci mi ciągle sygnał Ms2 dla Tem2 czyli tak jakby wcisnąć 'D' '2' '*' i nic się nie zmienia, nawet po odłączeniu zasilania

 

Pomogło ocięcie zasilania na 30sek

Edytowano przez prezesedi
19 minut temu, prezesedi napisał:

Pomogło ocięcie zasilania na 30sek

Trochę trudno stwierdzić co mu dolega, ale mam pewne podejrzenia: ilość pamięci w Arduino. Dlatego zmiana planów - następna wersja będzie już na ESP32.

 

  • Lubię! 1
1 godzinę temu, H1M4W4R1 napisał:

Tylko API, całe UI+UX w aplikacji

E tam - jeśli już to wszystko ciągnąć z ESP, a aplikacja nazywa się przeglądarka 🙂

@prezesedi na ESP32 działa pięknie i nic się nie zacina. Jeśli chcesz to możesz podmienić w getcommand.cpp:

#ifdef ESP32
static byte rowPins[ROWS] = {4,5,18,19};
static byte colPins[COLS] = {13,12,14,27};
#else
#if 1
static byte rowPins[ROWS] = {9,8,7,6};
static byte colPins[COLS] = {5,4,3,2};
#else
static byte rowPins[ROWS] = {5, 4, 3, 2};
static byte colPins[COLS] = {9, 8, 7, 6};
#endif
#endif

i przy okazji poprawić mój debilny błąd - wywalić static z definicji tablicy semafor, ma być:

// teraz tablica obiektów klasy Semafor: dwa semafory i dwie tarcze

Semafor semafor[]={
    Semafor(semaTable,WHERETO(0,0),"Sem1"), // semafor pierwszy piny P0..P4

Krótki programik do sprawdzenia pinów w klawiaturze:

#include <Keypad.h>

static const byte ROWS = 4;
static const byte COLS = 4;

#define KEY_HASH '#'
#define KEY_ASTERISK '*'

static const char keys[ROWS][COLS] = {
    {1,2,3,11},
    {4,5,6,12},
    {7,8,9,13},
    {KEY_ASTERISK,10,KEY_HASH,14}
};

static byte rowPins[ROWS] = {4,5,18,19};
static byte colPins[COLS] = {13,12,14,27};

static Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

void setup()
{
    Serial.begin(115200);
    delay(500);
    printf("Started\n");
}

void loop()
{
    int g = keypad.getKey();
    if (g) printf("Key %d\n", g);
    else delay(5);
}

Na razie nie podłączaj PCF - o tym pogadamy jutro!

  • Lubię! 1
13 godzin temu, ethanak napisał:

E tam - jeśli już to wszystko ciągnąć z ESP, a aplikacja nazywa się przeglądarka 🙂

Zależy jak ładnie ma to wyglądać 😉 ESP uciągnie sporo, ale jednak ma swoje ograniczenia. Poza tym osobiście jestem zwolennikiem rozdzielania backendu od frontendu, bo łatwiej wtedy zmienić np. szatę graficzną, a UI/UX nie przeszkadza w edycji funkcjonalności aplikacji (zakładając stosowanie TDD).

23 minuty temu, H1M4W4R1 napisał:

ESP uciągnie sporo, ale jednak ma swoje ograniczenia.

Jakie znowu ograniczenia??? Przecież on ma tylko dostarczyć przeglądarce parę statycznych plików (html, css, js, najlepiej wkompilowanych w kod żeby ich nie szukać po jakichś filesystemach), reagować na jakiś prosty request  http i odpowiedzieć jakimiś prostymi danymi (w tym przypadku ma dostarczyć informacje o strukturze semaforów [statyczne], informacje o stanie semaforów i przyjąć polecenie zmiany stanu. To nawet ESP8266 zrobi z palcem w GPIO 😉

Panie, nie takie rzeczy się robiło 🙂

 

A więc kontynuujemy.

Tak jak wspominałem - program w tej wersji przeznaczony jest na ESP32. Na AVR-ach działać nie będzie (tzn. pewnie zadziałałby na Mega po poprawkach ale to bez sensu).

Mo i mała dygresja na temat podłączania PCF-ów:

Układy PCF8575 (jak również PCF8574) mogą być zasilane zarówno z 3.3V, jak i 5V. Wyjścia tych układów użyte jako sink mogą natomiast operować obciążeniem zasilanym z 5V. Przyznam się, że w tej sytuacji niespecjalnie rozumiem istnienie na płytce modułu jakiegoś stabilizatora. Moim zdaniem jeśli to są płytki o których pisaliśmy poprzednio należy zastować się do porady z opisu na Amazonie, czyli "przylutować lutownika Lutowodu" (czyli wlutować zworę VCC-VDD). Ale przypominam: jest to moje zdanie, nie mam schematu płytki ani samej płytki, mogę się mylić!

Wróćmy jednak do programu.

Zacznijmy od rzeczy najważniejszej: przystosowania programu do współpracy z dwoma PCF-ami. Załóżny przy okazji, że nie będzie już nam potrzebne wyświetlanie stanu LED na monitorze serial, tak więc program dość mocno się uprości.

Przede wszystkim zamiast pojedynczego adresu ztwórzmy dwuelementową tablicę:

static const uint8_t PCFADR[]={0x20, 0x21};

Jeśli używamy tylko jednego PCF-a, możemy jako adres podać 0, czyli:

static const uint8_t PCFADR[]={0x20, 0};

Trzeba tylko usunąć poprzednią definicję PCFADR i dodać jedną linijkę w funkcji wwrite16:

static void wwrite16(uint8_t adr, uint16_t data)
{
    if (!adr) return;
    Wire.beginTransmission(adr);
    ...

Funkcję SendToPcf usuwamy - jej zadaniem było praktycznie jedynie wyświetlanie stanu LED na serialu.

Funkcję updateLed musimy nieco zmodyfikować:

void updateLed()
{
    static uint16_t oldport[2]={0,0};
    uint32_t port32=0;
    uint16_t port[2];
    int i;
    for (i=0;i<CNT_SEMA;i++) {
        port32 |= (uint32_t)semafor[i].get() << semafor[i].whereto();
    }
    port[0] = port32 & 0xffff;
    port[1] = (port32 >> 16) & 0xffff;
    for (i=0; i<2; i++) {
        if (port[i] != oldport[i]) {
            oldport[i] = port[i];
            wwrite16(PCFADR[i],~port[i]);
        }
    }
}


Jak widzimy, oba ekspandery traktowane są oddzielnie i zapis następuje tylko wtedy, gdy zmieniły się dane dla konkretnego ekspandera.

Teraz możemy już stworzyć tabele dla docelowej ilości 4 senaforów i 4 tarcz:

Semafor semafor[]={
    Semafor(semaTable,WHERETO(0,0),"Sem1"), // semafor pierwszy piny P0..P4
    Semafor(semaTable,WHERETO(1,0),"Sem2"), // semafor drugi piny P10..P14
    Semafor(semaTable,WHERETO(2,0),"Sem3"), // semafor trzeci piny P0..P4
    Semafor(semaTable,WHERETO(3,0),"Sem4"), // semafor czwarty piny P10..P14
    Semafor(tarczaTable,WHERETO(0,5),"TM1"), // tarcza pierwsza piny P5..P6
    Semafor(tarczaTable,WHERETO(1,5),"TM2"), // tarcza druga piny P15..P16
    Semafor(tarczaTable,WHERETO(2,5),"TM3"), // tarcza trzecia piny P5..P6
    Semafor(tarczaTable,WHERETO(3,5),"TM4") // tarcza czwarta piny P15..P16
};

Mapę semaforów zorganizujemy tak, aby przyciskom 1..4 odpowiaday semafory, a A..D tarcze:

int8_t semaforMap[16]={
    0, // zawsze zero
    1,2,3,4,     // semafory na pozycjach 1..4
    0,0,0,0,0,0, // nieobsadzone pozycje 5..9 i 0
    5,6,7,8,     // tarcze na pozycjach A..D
    0 // zawsze zero
};

Możemy sobie to teraz skompilować, wgrać na ESP i cieszyć się działającą aplikacją.

Właściwie aplikacja już działa i można wtykać naszego ESPeka do makiety, ale jedna rzecz mi się nie podoba: jeśli wyświetlane są wszystkie semafory, to zmiana ich stanu (np. automatyczne przejście do S1 po 60 sekundach) nie zostaje odnotowane. Postarajmy się temu zaradzić.

Ale najpierw uporządkujmy sobie nieco wyświetlanie.

Wraz ze zmianą platformy otrzymaliśmy potężne narzędzie o nazwie "printf". zamiast mozolnie klepać litanię Serial.print() czy display.print() możemy posłużyć się tą funkcją.

Zacznijmy od prostej rzeczy: czyli wyświetlania kontrolnego na monitorze Serial. Nowa wersja funkcji wygląda tak:

static void displayKbdStatus(bool done=false)
{
    if (done) {
        displaySemaState(kbdSema, kbdProg, true);
        printf("ZAPISANO %s %s\r\n",
            semafor[semaforMap[kbdSema]-1].name(),
            semafor[semaforMap[kbdSema]-1].pgname(kbdProg));
    }
    else if (!kbdStatus) {
        displaySemaState();
        printf("--\r\n");
    }
    else if (kbdStatus == KBD_SEMA) {
        printf("SEMA %s\r\n",
            semafor[semaforMap[kbdSema]-1].name());
        displaySemaState(kbdSema);
    }
    else {
        displaySemaState(kbdSema, kbdProg);
        printf("SEMA %s PROG %s\r\n",
            semafor[semaforMap[kbdSema]-1].name(),
            semafor[semaforMap[kbdSema]-1].pgname(kbdProg));
    }
}

Jakby trochę krótsza 🙂

Podobnie postąpimy z funkcjami wyświetlacza - podam tylko fragment kodu odpowiedzialnego za wyświetlanie wszystkich semaforów:

 

   for (i=0;i<CNT_SEMA;i++) {
        display.setCursor(64 * (i&1), (i/2) * 8);
        display.printf("%5s %s",semafor[i].name(),
            semafor[i].pgname(semafor[i].current()));
    }

Mało że krótsze, to jeszcze przy okazji równo ustawia napisy (nazwa semafora zawsze zajmuje 5 znaków i jest wyrównana do prawej).

Pozostało tylko zrobić coś, aby wyświetlany stan semaforów aktualizował się automatycznie. Załóżmy, że stany przechowujemy w jakiejś tablicy, stwórzmy więc funkcję wyświetlającą:

static uint8_t semaStates[16];
static void showAllSema()
{
    int i;
    display.clearDisplay();
    display.setTextSize(1);
    display.setTextColor(SSD1306_WHITE);
        
    for (i=0;i<CNT_SEMA;i++) {
        display.setCursor(64 * (i&1), (i/2) * 8);
        display.printf("%5s %s",semafor[i].name(),
            semafor[i].pgname(semaStates[i]));
    }
    display.display();
}

Jak widać funkcja jest żywcem zerżnięta z poprzedniej wersji. Oczywiście musimy teraz odpowiednio przerobić funkcję rozpoczynającą wyświetlanie:

void displayAllSema()
{
    int i;
    for (i=0;i<CNT_SEMA;i++) semaStates[i] = semafor[i].current();
    displayMode = DPM_SHOW;
    showAllSema();
    displayTimer = millis();
}


Jak można zauważyć, funkcja po prostu zapamiętuje stany w tablicy i wyświetla sobie informacje o semaforach. Czyli to już było?

Nie. Stwórzmy teraz dodatkową funkcję sprawdzającą, czy stany semaforów się zmieniły i trzeba wyświetlić nowe wartości:

void updateSemaDisplay()
{
    int i;
    bool redisplay=false;
    uint8_t newpos;
    for (i=0;i<CNT_SEMA;i++) {
        newpos=semafor[i].current();
        if (newpos != semaStates[i]) {
            semaStates[i] = newpos;
            redisplay = true;
        }
    }
    if (redisplay) showAllSema();
}

Tę funkcję będziemy wywoływać na końcu updateDisplay(), czyli zakończenie będzie wyglądało tak:

    ...
    if (displayMode == DPM_SHOW) {
        updateSemaDisplay();
    }
}

Przy okazji warto przedłużyć czas wyświetlania stanu semaforów do minuty.

I to już naprawdę wszystko jeśli chodzi o działającą aplikację. Kod do wgrania do ESP:prezesedi6.zip

ale czy naprawdę wszystko?

No nie. W sumie to co dotychczas powstało na dobrą sprawę można załatwić w Arduino. Wymagałoby to co prawda trochę ekwilibrystyki z PROGMEM i tymi smiesznymi pgm_read_cośtam, może nawet napisania drivera SSD1106 który nie będzie żarł pół pamięci na dzień dobry (bez buforowania), ale to już byłby szczyt jego możliwości. A ja planuję coś więcej - tak że stay tuned 🙂

 


 

  • Lubię! 1
7 godzin temu, H1M4W4R1 napisał:

ESP uciągnie sporo, ale jednak ma swoje ograniczenia.

No to masz: prezesedi7.zip

SSID Kolejka, hasło PrezesEdi7, adres http://192.168.4.1/

O coś takiego mi chodziło.

Prowizorka oczywiście, ale na moim Samsungu hula 😉

Mam problem z podłączeniem ESP32 (ale to nic nowego).

Podpięcie klawiatury bezpośrednio pod piny ESP udało się - na monitorze (i wersji kodu prezesedi6) wyświetlają się zadane sygnały.

Niestety nie wiem czy wszystkie płytki ESP czy tylko moja, nie mieści się na płytce stykowej tak by zostawić jeden rząd pinów do podłączeń. Dlatego wcześniej nabyłem specjalną płytkę rozwojową dla ESP32.

obraz.thumb.png.9093f04441b23445ae15a65529cfc39c.pngobraz.thumb.png.816032837cda0c7387325257eeaaa025.png

i tu przy podpięciu USB bezpośrednim (do ESP) program się ładuje, jednak klawiatura nie działa. Natomiast przy podłączeniu USB do płytki rozwojowej (i zmianie portu na 10), wywala poniższy błąd:

obraz.thumb.png.7e94654f9d50549222539513a926ef36.png

Siedzę nad tym od 22 i dochodzę do wniosku, że coś jest spipcone.

Jeszcze ustawienia w programie:

obraz.thumb.png.808f6601e2d38d2207761a0de66be9ce.png

  • Lubię! 1

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...