Espressif nie przestaje mnie zaskakiwać ;).
Archiwa tagu: esp32
Szeregowanie kooperacyjne w Micropythonie na ESP8266.
Ku mojemu zdziwieniu Micropython na esp8266 nie obsługuje wątków, a potrzebna mi była funkcja „sleep()”, która będzie się wykonywać równolegle do głównego wątku. Dziwne to, bo z FreeRTOS SDK wątki ponoć działają, choć całkiem możliwe, że kosztują zbyt wiele cennych zasobów potrzebnych Micropythonowi do życia. Znalazłem też info, że wynika to z ograniczeń zestawu instrukcji procesora. Cóż, FreeRTOS działa super na esp32 i niech tak zostanie. Niestety bez wątków funkcja zawłaszcza procesor licząc czas w pętli i jak chciałoby się wcześniej zasterować podłączonymi do esp8266 ustrojstwami, to trzeba by to zrobić manualnie ;). Na szczęście dostępna ilość pamięci pozwala na użycie modułu uasyncio i nieblokujących się socketów, bo to też istotne jeśli chcemy obsługiwać sprzęt przez requesty http typu <adres_ip>/onoff czy <adres_ip>/sleep=czas. Jedyny minus, to upip, którym nie zainstalujemy uasyncio ze względu na zbyt małą ilość pamięci. Trzeba to zrobić ręcznie.
import network import usocket as socket import errno sta_if = network.WLAN(network.STA_IF) addr = socket.getaddrinfo(sta_if.ifconfig()[0], 8000)[0][-1] s = socket.socket() s.setblocking(False) s.bind(addr) s.listen(1) print('listening on', addr) import machine pin = machine.Pin(5, machine.Pin.OUT) status = True; timeout = None pin.value(status) import uasyncio as asyncio loop = asyncio.get_event_loop() async def sleep(newtm): global status, timeout if timeout == newtm: return if timeout != None: timeout = newtm return else: timeout = newtm while timeout > 0: await asyncio.sleep(60) timeout = timeout - 60 status = False; timeout = None pin.value(status) async def worker(): global status while True: line = None try: cl, addr = s.accept() print('client connected from', addr) cl_file = cl.makefile('rwb', 0) while not line: line = cl_file.readline() except OSError as exc: if exc.args[0] in [errno.ETIMEDOUT, errno.EAGAIN]: await asyncio.sleep(0) continue print(line, status) if 'onoff' in line: status = not status pin.value(status) if 'sleep' in line: s1 = line.find(b'sleep')+6 s2 = line.find(b'H')-1 try: timeout = int(line[s1:s2]) loop.create_task(sleep(timeout*60)) except ValueError: print('/sleep needs a numeric timeout') cl.close() loop.create_task(worker()) loop.run_forever() # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
Ten sam skrypt na esp32 z użyciem _thread. Esp32 to już jednak potężna bestia, z ogromną ilością pamięci, zwłaszcza z PSRAM na pokładzie, oraz sporym zapasem mocy procesora dual-core ;).
Micropython – itertools.
FreeRTOS tasks.
RTOS w Esp-idf to jest to, co tygryski lubią najbardziej, ale nikt mi nie powie, że Arduino-IDE nie jest fajne? Ani pół include-a i działa :).
//Isn't it cool? void setup() { Serial.begin(115200); delay(1000); xTaskCreate( taskOne, /* Task function. */ "TaskOne", /* String with name of task. */ 2000 , /* Stack size in words. */ NULL, /* Parameter passed as input of the task */ 1, /* Priority of the task. */ NULL); /* Task handle. */ xTaskCreate( taskTwo, /* Task function. */ "TaskTwo", /* String with name of task. */ 2000, /* Stack size in words. */ NULL, /* Parameter passed as input of the task */ 1, /* Priority of the task. */ NULL); /* Task handle. */ } void loop() { delay(1000); } void taskOne( void * parameter ) { for( int i = 0;i<10;i++ ){ Serial.println("Hello from task 1"); delay(1000); } Serial.println("Ending task 1"); vTaskDelete( NULL ); } void taskTwo( void * parameter) { for( int i = 0;i<10;i++ ) { Serial.println("Hello from task 2"); delay(1000); } Serial.println("Ending task 2"); vTaskDelete( NULL ); }
Swoją drogą fajny opis, świetna książka, a ten opis SMP i przeportowanych funkcji RTOS v9 poprostu trzeba przeczytać 😉
Kompletnie nie rozumiem, dlaczego ludzie na Arduino-IDE tak psy wieszają? Dla początkujących jest świetne, geek ugotuje w nim coś na szybko, a SDK nie zając :).