Skocz do zawartości

[MicroPython v1.23.0, ESP32] Parsowanie sygnałów 433 MHz


orb777

Pomocna odpowiedź

W skrócie:

Do odbioru sygnałów 433 MHz używam modułu "MX-RM-5V", który ma praktycznie zerowe "dane losowe" na wyjściu, chociaż zasięg mizerny nawet z drucianą anteną o długości "173 mm". Jednak do skopiowania kodu z pilota nadaje się. Sygnały odbieram używając przerwań, "wyzwalaczem" są stany IRQ_RISING/IRQ_FALLING. Wersja całości mocno robocza aż strach wklejać.

Ramki wysyłam za pomocą modułu "SYN115". Używam do tego RMT z biblioteki esp32. Przykładowy kod "nadajnika" włącza i wyłącza gniazdo bezprzewodowe, ale robi to na zasadzie "bezmyślnego", podwójnego odtwarzania skopiowanych wcześniej sygnałów. Oczywiście długości sygnałów wypadałoby jakoś uśrednić procentowo zbierając dane z kilku ramek, ale na razie nie skupiam się nad tym.

import esp32, machine, time

# rozdzielczość 1uS
r = esp32.RMT(0, pin = machine.Pin(23, machine.Pin.OUT), clock_div = 80, idle_level = False)

print(">> ON <<")
for i in range(2):
    r.write_pulses([1232, 427, 1218, 425, 405, 1239, 1218, 425, 404, 1242, 1221, 423, 1219, 427, 1217, 428, 402, 1240, 1221, 424, 1218, 428, 1217, 425, 404, 1240, 405, 1241, 1218, 427, 401, 1242, 401, 1248, 396, 1242, 404, 1241, 405, 1240, 1219, 426, 1217, 428, 1216, 427, 1217, 425, 404, 12374, 1222, 425, 1219, 425, 404, 1239, 1221, 425, 400, 1245, 1218, 424, 1220, 424, 1220, 424, 403, 1244, 1219, 424, 1217, 428, 1217, 427, 403, 1242, 401, 1242, 1219, 427, 401, 1244, 401, 1241, 404, 1243, 401, 1243, 401, 1243, 1218, 426, 1218, 428, 1219, 424, 1218, 421, 401, 12377, 1222, 425, 1217, 427, 404, 1239, 1221, 424, 404, 1239, 1220, 429, 1216, 427, 1218, 425, 401, 1244, 1218, 427, 1218, 424, 1218, 427, 401, 1245, 404, 1238, 1219, 428, 401, 1240, 404, 1241, 403, 1241, 404, 1240, 404, 1245, 1215, 428, 1214, 428, 1217, 427, 1218, 424, 402, 12380, 1215, 427, 1222, 421, 404, 1240, 1219, 424, 405, 1239, 1219, 427, 1217, 428, 1217, 427, 401, 1242, 1217, 427, 1219, 426, 1217, 432, 398, 1241, 401, 1245, 1217, 427, 401, 1241, 404, 1243, 400, 1242, 403, 1242, 404, 1241, 1219, 427, 1214, 431, 1216, 427, 1216, 426, 400, 12378, 1218, 427, 1217, 427, 404, 1241, 1220, 423, 403, 1244, 1215, 427, 1217, 427, 1219, 427, 400, 1242, 1219, 427, 1219, 424, 1217, 427, 401, 1244, 401, 1244, 1218, 426, 401, 1244, 401, 1244, 401, 1242, 400, 1244, 403, 1242, 1217, 428, 1219, 427, 1218, 426, 1218, 424, 401, 12377, 1222, 424, 1218, 426, 403, 1241, 1219, 426, 404, 1242, 1218, 427, 1216, 426, 1217, 428, 402, 1244, 1217, 428, 1218, 427, 1216, 426, 401, 1244, 400, 1245, 1216, 428, 401, 1243, 400, 1245, 400, 1244, 403, 1243, 401, 1241, 1219, 428, 1219, 424, 1217, 427, 1218, 425, 401], True)
    
for i in range(3, 0, -1):
    print("Wyłączam za", i)
    time.sleep(1)

print(">> OFF <<")
for i in range(2):
    r.write_pulses([1237, 424, 1225, 421, 402, 1240, 1219, 425, 403, 1241, 1218, 428, 1217, 427, 1217, 427, 401, 1244, 1217, 423, 1219, 427, 1217, 426, 401, 1245, 401, 1241, 1225, 418, 404, 1242, 401, 1243, 401, 1242, 403, 1241, 403, 1242, 1219, 424, 1218, 426, 1219, 427, 401, 1237, 404, 12376, 1220, 421, 1220, 424, 407, 1239, 1221, 423, 404, 1239, 1220, 425, 1218, 427, 1218, 425, 405, 1241, 1215, 427, 1217, 427, 1219, 427, 401, 1242, 401, 1241, 1220, 425, 401, 1243, 401, 1244, 401, 1244, 401, 1242, 402, 1243, 1215, 427, 1219, 427, 1217, 427, 401, 1239, 401, 12378, 1217, 424, 1221, 424, 404, 1241, 1219, 423, 404, 1245, 1217, 424, 1217, 425, 1220, 424, 404, 1240, 1221, 424, 1218, 428, 1219, 424, 400, 1244, 401, 1242, 1219, 427, 401, 1241, 401, 1244, 400, 1244, 401, 1244, 401, 1242, 1217, 425, 1217, 427, 1219, 427, 401, 1240, 401, 12375, 1220, 422, 1221, 427, 403, 1239, 1221, 424, 404, 1239, 1221, 428, 1215, 423, 1225, 422, 400, 1244, 1216, 427, 1218, 427, 1216, 426, 404, 1242, 401, 1244, 1215, 430, 400, 1241, 404, 1240, 404, 1245, 400, 1241, 401, 1242, 1217, 427, 1218, 427, 1216, 430, 398, 1241, 402, 12376, 1221, 425, 1219, 424, 404, 1239, 1218, 427, 401, 1245, 1217, 427, 1216, 427, 1217, 427, 401, 1245, 1216, 431, 1212, 431, 1211, 430, 398, 1247, 397, 1248, 1211, 438, 392, 1247, 395, 1251, 398, 1247, 395, 1249, 395, 1249, 1210, 433, 1210, 437, 1209, 433, 396, 1248, 391, 12386, 1209, 436, 1211, 435, 391, 1250, 1210, 435, 395, 1250, 1210, 437, 1205, 439, 1204, 439, 389, 1255, 1207, 439, 1205, 439, 1203, 441, 389, 1256, 386, 1260, 1200, 445, 383, 1263, 382, 1259, 387, 1260, 382, 1262, 384, 1258, 1200, 447, 1198, 447, 1198, 445, 382, 1259, 384], True)

 

Niektóre piloty do gniazd bezprzewodowych (np. Orno) zachowują się trochę dziwnie i wysyłają za koleją podwójne kody, czyli: (wł/wył)ączający przekaźnik i drugi, który wydaje się być bezużyteczny. Nawet "mundrołek" aka pilot uniwersalny ma wtedy problem ze skopiowaniem właściwego kodu i zaskakuje dopiero za którymś razem.

Do czego zmierzam? Bufor odbiorczy mam regulowany, mogę odebrać tyle sygnałów ile pamięć pomieści. Z tego co zauważyłem 200-500 jest wystarczające. Myślę nad metodą wyłuskania danych kodów, czyli zliczenia i wyświetlenia tych, które powtarzają się. MicroPython szybkością nie grzeszy, więc szukam optymalnej metody. Patrząc na zapis z analizatora stanów logicznych wydaje się to dosyć proste, ale na razie nie potrafię ubrać tego w kod. Zagadnienie może być proste, ale tak objawia się umysłu zaciemnienie. Zakładam, że ktoś już coś takiego robił i może podsunie jakieś słowo klucz, kawałek kodu albo coś w tym stylu.

Edytowano przez orb777
Link do komentarza
Share on other sites

4 godziny temu, orb777 napisał:

MicroPython szybkością nie grzeszy, więc szukam optymalnej metody.

To i tak jest realizowane sprzętowo więc czy to będzie napisane zp: pythona czy C nie powinno mieć znaczenia. Ogólnie polecam przejście na C/C++ 

Link do komentarza
Share on other sites

(edytowany)

@_LM_ , w uPy mam większy "fun", cpp klepałem w innym życiu, trochę zapomniałem.

Przerwania w ESP32 nie są zbyt szybkie, ale szybsze niż w 8266, więc jakoś działa. Wypadałoby wyłuskać kody z bufora z pewną tolerancją dla czasów, np. 5%, uśrednić ich wartości na podstawie kilku ramek i wyświetlić, żeby można było wybrać.

Testowy kod do zbierania sygnałów z eteru wygląda tak:

import machine, time, gc

def get_signals(pin):
    global count, time_prev, sig_buff
    time_now = time.ticks_us()
    sig_buff.append((int(not pin.value()), time_now - time_prev))
    time_prev = time_now
    count += 1
        
def show_signals():
    global sig_buff
    start = sig_buff[0][0]
    for i in sig_buff:
        if i[0] != start:
            return
        start = int(not start)
    print("r.write_pulses(%r, %r)\n%s\n" % ([i[1] for i in sig_buff[1:]], bool(sig_buff[1][0]), line))

p1 = machine.Pin(27, machine.Pin.IN, machine.Pin.PULL_DOWN)
p1.irq(handler = get_signals, trigger = machine.Pin.IRQ_FALLING | machine.Pin.IRQ_RISING)
sig_buff = []
count = time_prev = 0
line = 20 * "_____"

while True:
    gc.collect()
    while count < 300:
        pass
    irq_state = machine.disable_irq()
    show_signals()
    sig_buff.clear()
    count = 0
    machine.enable_irq(irq_state)

 

Edytowano przez orb777
kod
Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

2 godziny temu, ethanak napisał:

Bo to "przerwania" maszyny wirtualnej Pythona a nie procesora.

I trzeba z tym żyć, hehe. Ogólnie temat uC jest dla mnie nowy, dopiero obserwuję jak zachowuje się ESP32.

Swoją drogą zmieniłem odrobinę kod. Wyłączam przerwania na czas przetwarzania danych, żeby opróżnić też kolejkę.

Link do komentarza
Share on other sites

A przypadkiem RMT nie można zatrudnić do zbierania danych? Nie bawię się mikrym pytongiem, ale w C/C++ działa to całkiem nieźle (w moim przypadku odbiornik pilota IR).

Link do komentarza
Share on other sites

Niestety nie. Aktualnie RMT wbudowane w bibliotekę esp32 zawiera poniższe funkcje:

__del__ -- <function>
  deinit -- <function>
  clock_div -- <function>
  wait_done -- <function>
  loop -- <function>
  write_pulses -- <function>
  bitstream_channel -- <staticmethod>
  source_freq -- <staticmethod>
  PULSE_MAX -- 32767

 

Jak na razie w testowym firmware "v1.24.0-preview.286.g042693496 (2024-09-04)" też nie dodano funkcji odczytu, w dokumentacji jest tylko informacja:

Cytat

The current MicroPython RMT implementation lacks some features, most notably receiving pulses. RMT should be considered a beta feature and the interface may change in the future.

 

Link do komentarza
Share on other sites

56 minut temu, ethanak napisał:

A przypadkiem RMT nie można zatrudnić do zbierania danych?

Można można, zdaje się że w nowszych esp jest połączone z DMA także wszystko full automat. Ale informacja nie potwierdzona, będę przy kompie to sprawdzę. 

  • Lubię! 1
Link do komentarza
Share on other sites

5 godzin temu, ethanak napisał:

No i to jest powód żeby rzucić mikrego p w kąt i zająć się c/c++.

Oczywiście Python na pc to zupełnie inna sprawa.

Pewnie tak, ale czasem dużo zmian robię podczas testowania. W uPy w zasadzie w locie wgrywa się kod do pamięci i nie muszę orać flasha jeżeli nie używam funkcji typu deepsleep lub restartowania uC. Z WebREPL nie potrzebuję nawet przewodu, czy komputera. Znam składnię cpp, od niego zacząłem naukę programowania. W cpp oczywiście działa to żwawiej, ale w uPy zrobisz często szybciej, zresztą znasz Pythona i sam wiesz jak to jest na blaszaku. Na tym etapie poznawania tematu uC wystarczający jest dla mnie uPy. Do arduino owszem zaglądałem, ale mam mniejszy "fun".

Link do komentarza
Share on other sites

E tam - ESP32 + Arduino core to dopiero fun 🙂 Wystarczy kilka moich kodów (czytak, pogodynka, modelarstwo kolejowe, z drobiazgów joysticki), zerknij do kodów i zobacz co można zrobić  z Arduino.

A Python na pc jest też świetny pod warunkiem, że potrafisz pisać moduły w C.

  • Lubię! 1
Link do komentarza
Share on other sites

@ethanak , spoko, przejrzę. Widzę, że jesteś człowiek legenda, skoro nawet gierki pod commodore pisałeś. Także bez urazy za orcę dla emerytów, nawet nie zaglądałem na profil. 🙂

Link do komentarza
Share on other sites

9 godzin temu, orb777 napisał:

bez urazy za orcę dla emerytów

A żadnej urazy - po prostu wyobraziłem sobie emeryta próbującego zrozumieć tryby przeglądania ekranu (to jeszcze się da) i kilkadziesiąt porąbanych kombinacji klawiszy różnych dla każdej aplikacji 🙂

A co do zerknięcia w kody - nie pisałem tego żeby się chwalić tylko żeby pokazać, co można zdziałać z Arduino IDE i ESP32. A można duuuużo więcej...

Link do komentarza
Share on other sites

9 godzin temu, orb777 napisał:

bez urazy za orcę dla emerytów

A żadnej urazy - po prostu wyobraziłem sobie emeryta próbującego zrozumieć tryby przeglądania ekranu (to jeszcze się da) i kilkadziesiąt porąbanych kombinacji klawiszy różnych dla każdej aplikacji 🙂

A co do zerknięcia w kody - nie pisałem tego żeby się chwalić tylko żeby pokazać, co można zdziałać z Arduino IDE i ESP32. A można duuuużo więcej...

Link do komentarza
Share on other sites

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...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.