Skocz do zawartości

Przeszukaj forum

Pokazywanie wyników dla tagów 'octoprint'.

  • Szukaj wg tagów

    Wpisz tagi, oddzielając przecinkami.
  • Szukaj wg autora

Typ zawartości


Kategorie forum

  • Elektronika i programowanie
    • Elektronika
    • Arduino i ESP
    • Mikrokontrolery
    • Raspberry Pi
    • Inne komputery jednopłytkowe
    • Układy programowalne
    • Programowanie
    • Zasilanie
  • Artykuły, projekty, DIY
    • Artykuły redakcji (blog)
    • Artykuły użytkowników
    • Projekty - roboty
    • Projekty - DIY
    • Projekty - DIY (początkujący)
    • Projekty - w budowie (worklogi)
    • Wiadomości
  • Pozostałe
    • Oprogramowanie CAD
    • Druk 3D
    • Napędy
    • Mechanika
    • Zawody/Konkursy/Wydarzenia
    • Sprzedam/Kupię/Zamienię/Praca
    • Inne
  • Ogólne
    • Ogłoszenia organizacyjne
    • Dyskusje o FORBOT.pl
    • Na luzie
    • Kosz

Szukaj wyników w...

Znajdź wyniki, które zawierają...


Data utworzenia

  • Rozpocznij

    Koniec


Ostatnia aktualizacja

  • Rozpocznij

    Koniec


Filtruj po ilości...

Data dołączenia

  • Rozpocznij

    Koniec


Grupa


Znaleziono 1 wynik

  1. Na wstępie od razu uwaga: o ile prezentowane rozwiązania mechaniczne (tzn. sposoby mocowania itd.) dotyczą Anet A8, o tyle elektronika i programy są uniwersalne - wymogiem jest tylko Raspberry Pi i OctoPrint. Zaczęło się od tego, że muszę w końcu skończyć parę robotopodobnych konstrukcji, a z racji niewielkich możliwości warsztatowych (nawet imadła nie mam gdzie przykręcić) postanowiłem kupić drukarkę 3d aby parę brakujących elementów dodrukować. Po przeanalizowaniu finansów (i przekonaniu mojej kochanej że bez drukarki życie mi niemiłe) na szafce stanęła śliczna chińska Anet A8. Krótko potem doszedłem do wniosku, że latanie na drugi koniec mieszkania z kartą aby coś wydrukować nie jest tym, co tygrysy lubią najbardziej. Oczywiście - istnieje kilka różnych opcji, ale postanowiłem wypróbować OctoPrinta (choćby dlatego, że mam starego lapka z połamanym zawiasem który idealnie nadawał się do prób - czyli w sumie mogłem próbować bezkosztowo). Po oswojeniu się z OctoPrintem postanowiłem dokupić jakiś jednopłytkowy komputerek, bo laptop zajmuje jednak trochę zbyt dużo miejsca. Niestety - wyjęty z szuflady NanoPi po uruchomieniu OctoPrinta (jeszcze przed podłączeniem drukarki) uprzejmie się usmażył (nie będę się nad tym rozwodził bo to nie ma nic wspólnego z tematem) - postanowiłem więc kupić Raspberry Pi. Po paru dniach przyszedł Raspberry. Postanowiłem nie instalować OctoPi a normalnego Raspbiana i doinstalować do niego OctoPrinta. Nie wiem czy to dobry wybór - ale wolę mieć normalny system, bo przecież raspberry może słuzyć nie tylko do drukowania! Przez kilka dni Raspberry leżał sobie na szafce w jakiejś prowizorycznej obudowie, w końcu miałem tego dość. Co prawda typowym miejscem do zamontowania RPi na Anetce jest lewa część ramy zaraz nad płytą główną - ale wydrukowałem sobie osłonę kabli osi Z, a pomysł mocowania jej do obudowy RPi uznałem za bezsensowny (niewygodny dostęp do komputerka). Natomiast idealnym miejscem zamontowania wydał mi się wyświetlacz - z tyłu za nim jest mnóstwo miejsca, nawet cztery śruby M3 mamy do dyspozycji. Na Thingiversie znalazłem gotowca (mocowanie), na szczęście najpierw przymierzyłem... i okazało sę, że albo gniazda USB będą z niewłaściwej strony (po prawej), albo wtyczka zasilania z kablem będzie wystawać pod ramą. Postanowiłem więc zrobić własny projekt, gdzie RPi byłby przesunięty maksymalnie do góry. Projekt wyszedł całkiem nieźle (pomijając jeden błąd, naprawiony zresztą w załączonych plikach - mianowicie zapomniałem zostawić otwór na kartę pamięci). Oto on: Montaż jest bardzo prosty - Należy po prostu przykręcić RPi do wydrukowanego mocowania za pomocą czterech śrubek M2 ze stożkowym łbem: Następnie należy odkręcić cztery nakrętki mocujące tylną osłonę wyświetlacza, odłączyć taśmę i na wystające śruby założyć mocowanie: Warto również zastąpić nakrętki trzymające płytę wyświetlacza po prostu podkładkami 2mm (wydrukowałem sobie takie przy okazji) - przybajmniej można będzie całość skręcić zwykłym śrubokrętem bez używania jakichś wymyślnych kluczy. Tak zamocowany RPi został podłączony do zasilacza i działa non stop, niezależnie od drukarki. Dość szybko okazało się, że OctoPrint ma wadę: nie potrafi automatycznie podłączyć się do drukarki po jej włączeniu czy resecie. Niby drobiazg - ale niewygodny. Postanowiłem zrobić jakiś automat, który będzie to robił za mnie. Jak to powinno działać? Program powinien wykryć moment włączenia czy resetu drukarki, i wywołać funkcję "connect" z API OctoPrinta. Tyle założeń, ale jak wykryć włączenie? Po włączeniu pojawi się przecież nowe urządzenie USB, a wykrycie takowego jest już proste; wystarczy odpowiednio oprogramować regułki w udev. Jest tylko jeden problem - co prawda demon udevd potrafi wywołać jakiś tam program, ale nusi być on wykonany jak najszybciej, przy czym oczekiwanie na wykonanie takiego programu blokuje całe działanie demona. Czyli nawet gdyby udało mi się jakoś skrócić czas działania programu - i tak zadziałałby zanim urządzenie pojawi się w systemie Teoretycznie można by było zrobić fork, w potomnym procesie poczekać parę sekund i dopiero wywołać funkcję OctoPrinta, ale wydało mi się to jakieś takie mało profesjonalne... Postanowiłem więc zrobić inaczej. Główny program uruchamiany jest przez systemd przy starcie systemu. Przez cały czas nie robi nic, po prostu czeka na sygnał. Po jego otrzymaniu odczekuje chwilę i wywołuje octoprintowy "connect". Nic nie sprawdza - to wywołanie jest o tyle bezpieczne, że jeśli drukarka już jest do octoprinta podłączona po prostu nic się nie stanie, a próba podłączenia wyłączonej drukarki skończy się po prostu błędem i tyle. Program wgrałem jako /usr/local/bin/watchprinter i nadałem mu prawa do wykonania. Cały kod programu jest tak krótki, że postanowiłem zamieścić go tutaj. #!/usr/bin/env python #coding: utf-8 import requests, json, re, signal, time, yaml class octonector(object): api = None def __init__(self): if not self.__class__.api: conf = yaml.safe_load(open('/home/pi/.octoprint/config.yaml')) self.__class__.api = conf['api']['key'] self._enabled = False def enable(self): self._enabled = True def enabled(self): rc = self._enabled self._enabled = False return rc def doPostRequest(self,cmd,data): path='http://127.0.0.1:5000/api/%s' % cmd rc=requests.post(path, headers={ 'Host': 'localhost', 'Content-Type': 'application/json', 'X-Api-Key' : self.__class__.api}, json=data) return rc.status_code in (204,200) watcher=octonector() def ena(*args): global watcher watcher.enable() signal.signal(signal.SIGUSR1, ena) while True: signal.pause() if watcher.enabled(): time.sleep(5); try: watcher.doPostRequest('connection',{'command':'connect'}) except: pass Jak widać użyłem tu dwóch bibliotek, których w systemie nie ma - requests i yaml. Co prawda mógłbym skorzystać z wirtualnego śwodowiska OctoPrinta (w którym te biblioteki są zainstalowane) - postanowiłem jednak doinstalować je do systemu (szczególnie, że zarówno python-requests jak i python-yaml są w repozytorium i instaluje się je zwykłym aptem). Teraz mogłem już przetestować działanie. Po uruchomieniu i wysłaniu do programu sygnału USR1 drukarka została podłączona do OctoPrinta. Mogłem więc zająć się zautomatyzowaniem wszystkich czynności. Na początek zgrałem swój program z systemd. W tym celu w /etc/systemd/system/ umieściłem plik watchprinter.service z zawartością: [Unit] Description=Autoconnect for octoprint [Service] Type=simple ExecStart=/usr/local/bin/watchprinter Restart=always RestartSec=15 [Install] WantedBy=multi-user.target Po wydaniu polecenia: sudo systemctl start watchprinter mogłem już nie bawić się w szukanie pid-u programu - polecenie sudo systemctl kill -s USR1 watchprinter załatwiało to za mnie. Tak więc nakazałem poprzez "sudo systemctl enable watchprinter" uruchamianie mojego programu przy starcie systemu - pozostało tylko automatyczne wysłanie sygnału po włączeniu drukarki. W tym celu musiałem znaleźć identyfikatory USB podłączonej drukarki. Przy włączonej drukarce polecenie "sudo lsusb" dało następujący wynik: Bus 001 Device 012: ID 1a86:7523 QinHeng Electronics HL-340 USB-Serial adapter Bus 001 Device 004: ID 0424:7800 Standard Microsystems Corp. Bus 001 Device 003: ID 0424:2514 Standard Microsystems Corp. USB 2.0 Hub Bus 001 Device 002: ID 0424:2514 Standard Microsystems Corp. USB 2.0 Hub Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Stwierdziłem, że pierwsza na liście to moja Anetka. Tak więc pozostało mi jedynie dopisać regułki udeva. Do pliku /etc/udev/rules.d/55-printer.rules wpisałem zawartość: ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idProduct}=="7523", ATTRS{idVendor}=="1a86", RUN+="/bin/systemctl kill -s USR1 watchprinter" Jak widać, idVendor i idProduct pobrałem właśnie z informacji podanych przez lsusb. No i po restarcie udeva mogłem już cieszyć się działającym automatem podłączającym drukarkę do OctoPrinta po jej włączeniu. No ale cóż - apetyt rośnie w miarę jedzenia. Zamarzyły mi się dodatkowe klawisze pauzy i restartu przy druku z OctoPrinta oraz jakieś ledy sygnalizujące stan drukarki (a właściwie OctoPrinta). Zacząłem więc od przeglądu szuflady. Razem z Raspberrym kupiłem w Botlandzie wtyk do złącza GPIO (kątowy - żeby się nie pomylić przy wtykaniu) - tak więc połączenie z komputerkiem miałem z głowy. Do tego znalazłem kilka przycisków tact-switch w różnych kolorach i płytkę uniwersalną. Klika diod LED i parę rezystorów - i całą wielce skomplikowaną elektronikę miałem skompletowaną. Z zaprojektowaniem obudowy (a właściwie panela - bo pełna obudowa nie jest przewidziana) już nie było problemów. Kilka linijek w OpenSCADzie - skorzystałem z tego, że w poprzednim projekcie miałem już zwymiarowane przyciski - i gotowe. Otwory w panelu pasują do rastra płytki uniwersalnej, a wygląda tak: Sam panel przykręcony jest czterema śrubami M2 (wkręconymi bezpośrednio w plastik) do bocznych wsporników: Trzeba pamiętać, aby otwory pod ledy poprawić wiertłem 3mm (ja użyłem 3.2mm). Kolej na płytkę. Wyciąłem kawałek o wymiarach 35x32 (gdybym ciął wszystkie krawędzie wzdłuż otworów, byłoby to 35x27.5). Otwory pod śruby nawierciłem po prostu przykładając płytkę do panelu. Po przylutowaniu wszystkich elementów wystarczyło odpowiednio podgiąć nóżki od spodu płytki, aby wszystko bez potrzeby prowadzenia ścieżek połączyć według schematu: A tak wygląda płytka przed przykręceniem do panela: Pozostało już tylko przykręcić płytkę do panela (cztery śruby M2 z łbem stożkowym z nakrętkami) i zamocować całość na ramie Anety. W tym celu usunąłem prawą górną tulejkę dystansową między ramą a płytą wyświetlacza, i w to miejsce wsunąłem prawy wspornik. Po skręceniu i podłączeniu wtyku do GPIO całość prezentuje się tak: Teraz zaczęła się właściwa zabawa - czyli pisanie programu. Od razu założyłem, że obsługa klawiatury i obsługa led to będą dwa oddzielne programy - odpadła zabawa z oczekiwaniem na kilka zdarzeń jednocześnie, czyli z wątkami czy procesami. Zacząłem od sygnalizacji. Zasada działania programu jest prosta: program periodycznie odpytuje OctoPrinta o stan drukowania i zależnie od tego z apala odpowiednią kombinację led. W moim przypadku są to: brak - octoprint wyłączony czerwona - drukarka wyłączona niebieska - drukarka włączona, nic nie robi niebieska + żółta - wydruk niebieska + czerwona - pauza. Dodatkowo przy zmianie stanu OctoPrint sygnalizuje programowi że ma ponownie odpytać o stan. W tym celu skorzystałem z możliwości obsługi zdarzeń przez OctoPrinta - każda zmiana stanu powoduje wysłanie sygnału do programu i natychmiastowe odpytanie. Dodatkowo musiałem doinstalować bibliotekę gpio Pythona: sudo apt install python-rpi.gpio Program w /usr/local/bin/octoindic znów jest bardzo prosty: #!/usr/bin/env python #coding: utf-8 LED_Y = 40 LED_R = 38 LED_B = 36 import RPi.GPIO as GPIO import requests, json, re, signal, time, os GPIO.setmode(GPIO.BOARD) GPIO.setwarnings(False) GPIO.setup([LED_Y, LED_R, LED_B],GPIO.OUT); def led(p): p=p.lower() if p else '' GPIO.output([LED_Y,LED_R, LED_B], ('y' in p, 'r' in p, 'b' in p)) class ledLighter(object): api = None headers={'Host':'localhost'} def __init__(self): if not self.__class__.api: import yaml conf = yaml.safe_load(open('/home/pi/.octoprint/config.yaml')) try: self.__class__.api = conf['api']['key'] self.headers['X-Api-Key']=self.__class__.api except: pass self.getStatus() def getStatus(self): code = self._getStatus() led(code) return code def _getStatus(self): path='http://127.0.0.1:5000/api/printer?exclude=temperature,sd' try: rt=requests.get(path,headers = self.__class__.headers) except: return 'x' try: rt.raise_for_status() except: return 'r' return self.parseStatus(rt.content) def parseStatus(self, content): try: content = json.loads(content)['state']['flags'] except: return 'ry' if content['paused']: return 'rb' if content['printing']: return 'by' if content['ready']: return 'b' return 'ry' lt = ledLighter() def ena(*args): # tu można dodać kawałek kodu reakcji na sygnał pass signal.signal(signal.SIGUSR1, ena) while True: time.sleep(15) lt.getStatus() Jak widać, program sprawdza stan za każdym razem kiedy przyjdzie sygnał USR1 oraz 15 sekund po ostatnim sprawdzeniu. Znów wpis w /etc/systemd/system/octoindic.service jest krótki: [Unit] Description=Led status for octoprint [Service] Type=simple ExecStart=/usr/local/bin/octoindic Restart=always RestartSec=5 User=pi Group=pi [Install] WantedBy=multi-user.target Po wydaniu poleceń: sudo systemctl enable octoindic sudo systemctl start octoindic pozostaje jedynie dokonfigurowanie OctoPrinta. W tym celu do pliku konfiguracji ~/.octoprint/config.yaml dopisujemy: events: enabled: true subscriptions: - event: Startup command: sudo systemctl kill -s USR1 octoindic type: system - event: Shutdown command: sudo systemctl kill -s USR1 octoindic type: system - event: PrinterStateChanged command: sudo systemctl kill -s USR1 octoindic type: system - event: PrintStarted command: sudo systemctl kill -s USR1 octoindic type: system - event: PrintFailed command: sudo systemctl kill -s USR1 octoindic type: system - event: PrintDone command: sudo systemctl kill -s USR1 octoindic type: system - event: PrintCancelled command: sudo systemctl kill -s USR1 octoindic type: system - event: PrintPaused command: sudo systemctl kill -s USR1 octoindic type: system - event: PrintResumed command: sudo systemctl kill -s USR1 octoindic type: system Po restarcie OctoPrinta możemy cieszyć się dziarsko świecącymi diodami Pozostaje kwestia klawiszy - bardzo przydatnych np. przy zmianie koloru filamentu. Znów prosty program w /usr/local/bin/octopauser: #!/usr/bin/env python #coding: utf-8 KEY_PAUSE = 37 KEY_RESUME = 35 import RPi.GPIO as GPIO import requests, json, re, signal, time, os GPIO.setmode(GPIO.BOARD) GPIO.setwarnings(False) GPIO.setup([KEY_RESUME,KEY_PAUSE],GPIO.IN,pull_up_down=GPIO.PUD_UP); class myKeys(object): api = None headers={'Host':'localhost'} postheaders={'Host':'localhost'} def __init__(self): self.times=[0,0] if not self.__class__.api: import yaml conf = yaml.safe_load(open('/home/pi/.octoprint/config.yaml')) try: self.__class__.api = conf['api']['key'] self.__class__.headers['X-Api-Key']=self.__class__.api self.__class__.postheaders['X-Api-Key']=self.__class__.api except: pass def key_press_p(self,*args): if not GPIO.input(KEY_PAUSE): self.times[0] = time.time() elif time.time() - self.times[0] >= 0.2: self.cmdrun("pause") def key_press_r(self,*args): if not GPIO.input(KEY_RESUME): self.times[1] = time.time() elif time.time() - self.times[1] >= 0.2: self.cmdrun("resume") def doPostRequest(self,cmd,data): path='http://127.0.0.1:5000/api/%s' % cmd try: rc=requests.post(path, headers=self.__class__.postheaders, json=data) except: pass def cmdrun(self,cmd): if cmd == "pause": self.doPostRequest("job", {"command" : "pause","action" : "pause" }); elif cmd == "resume": s = self.getStatus() if s == "disconnected": self.doPostRequest("connection",{"command":"connect"}) elif s == "connected": self.doPostRequest("job", {"command" : "pause","action" : "resume" }); def getStatus(self): path='http://127.0.0.1:5000/api/printer?exclude=temperature,sd' try: rt=requests.get(path,headers = self.__class__.headers) except: return "off" try: rt.raise_for_status() except: return "disconnected" return "connected" def arm(self): GPIO.add_event_detect(KEY_PAUSE, GPIO.BOTH, callback = self.key_press_p) GPIO.add_event_detect(KEY_RESUME, GPIO.BOTH, callback = self.key_press_r) ks = myKeys() ks.arm() while True: try: signal.pause() except KeyboardInterrupt: break except: pass I także krótki wpis do /etc/systemd/system/octopauser.service: [Unit] Description=Pause keys for octoprint [Service] Type=simple ExecStart=/usr/local/bin/octopauser Restart=always RestartSec=5 User=pi Group=pi [Install] WantedBy=multi-user.target Po wydaniu poleceń: sudo systemctl enable octopauser sudo systemctl start octopauser możemy już cieszyć się możliwością wygodnego operowania pauzą na poziomie OctoPrinta za pomocą klawiszy. I to wszystko. Oczywiście - całą tę konstrukcję można rozbudować. Przykładowo - czujnik filamentu można dodać równolegle do klawisza pauzy, lub poświęcić jeszcze jeden pin GPIO i lekko przerobić program. Niestety - na razie nie znalazłem czujnika, który zadziała zarówno z miękkim TPU jak i przezroczystym PMMA... Załączam komplet plików (scad, stl oraz kody programów). Octopauser.zip Przyjemnego pauzowania i wznawiania życzy ethanak
×
×
  • Utwórz nowe...