
Witajcie moi drodzy
W tym temacie najpierw szczegółowo pokażę wnętrze drukarki HP Deskjet D1360, a potem przedstawię jak można wykorzystać jej części z Arduino. Określę pinout enkodera ze środka, napiszę kod pozwalający określić pozycję karetki dzięki użyciu enkodera, oraz też oczywiście posteruję jej silnikiem DC za pomocą dodatkowego modułu mostka H. Końcowym efektem prac będzie własny skecz Arduino pozwalający ustawić karetkę tej drukarki na wybranej przez nas pozycji.
Teardown drukarki HP Deskjet D1360
Drukarkę tą otrzymałem luzem, bez zasilacza - po prostu uratowałem ją z elektrośmieci.

Drukarka od spodu:

Tabliczka znamionowa:

Aby dostać się do środka potrzebny nam będzie śrubokręt typu torx (czyli tzw. sześciokątny/gwiazdowy), taki:

(końcówka śrubokretu typu torx; źródło: Wikipedia)
Taki też przygotowałem:

Często aby odsłonić śruby należy otworzyć pokrywę drukarki:

Śruby są po obu stronach obudowy, z przodu i z tyłu:


Po odkręceniu górnej pokrywy można już zajrzeć do wnętrza drukarki:


W środku rzuca nam się w oczy ruchomy mechanizm karetki wraz z dwoma pojemnikami na tusz (które ruszają się razem z nią).
Co ciekawe, ten mechanizm zrealizowany jest w oparciu o zwykły silnik DC, a nie krokowy. W tym momencie tego jeszcze nie widać, ale łatwo można się przekonać o tym po demontażu całości - do silniczka idą tylko dwa przewody.
Sam silnik i mechanizm karetki też jest przykręcony torxami:

Drukarka określa pozycję karetki w oparciu o enkoder (tutaj ten enkoder jest podwójny - ma jedną diodę i dwa fototranzystory, ale o tym nieco dalej) który zlicza przeskoki kolorów na foliowym pasku:

Teraz pokażę z bliska te paski. Do wykonania tego zdjęcia musiałem użyć lepszego oświetlenia i tła (biała kartka papieru).
Oto foliowy pasek (tzw. 'encoder strip') na zdjęciu dobrej jakości:

Tutaj z powiększeniem:

I jeszcze z nieco większym powiększeniem:


Wyraźnie widać paski.
Sam enkoder po wylutowaniu wygląda tak:





Szczelina na pasek:

Z paskiem:

Środek enkodera; takie przepołowienie go jest oczywiście może być destrukcyjne, zrobiłem to by pokazać tutaj jego wnętrze:

Wyraźnie widać diodę i odbiornik.
(Ale to nie jest enkoder z rozbieranej tutaj drukarki, tylko z innej; z tej drukarki z tematu go nie wylutowywałem)
Do tematu enkodera i jego paska jeszcze wrócę.
Kontynuując teardown drukarki: po wymontowaniu szyny z karetką możemy dostać się do płyty głównej oraz drugiego silnika DC, tutaj odpowiedzialnego za podawanie papieru:

W ten sposób zostajemy już praktycznie z samą plastikową podstawą drukarki:

Jednakże na zdjęciu powyżej ukryty jest jeszcze jeden wartościowy element. Znajduje się on w plastikowym podajniku papieru:


Często nie jest on nawet przykręcony, tylko trzyma się na zaczepach.
Jest to płytka z kolejnym enkoderem, tutaj nawet z symbolem diody (dzięki czemu wiemy jaki jest pinout):

I to już będzie wszystko w kwestii teardown. Poniżej podsumowanie rozbiórki.
Uzyskane elementy
Z drukarki zachowałem tylko to, co uznałem za przydatne. Plastikowa obudowa i zbędne metalowe elementy od razu zostały zutylizowane.
Zostawiłem tylko te części:

Na zdjęciu widać:
- prowadnica karetki wraz z ruchomą karetką (na karetce jest płytka z układem scalonym i podwójnym enkoderem; na prowadnicy jest paskowany czarny pasek dla enkodera)
- dwa silniki DC (jeden od wyrzuconego mechanizmu podajnika papieru, drugi od karetki, tutaj osobno)
- przycisk na osobnej płytce na dwóch kabelkach
- pojedynczy enkoder luzem na osobnej płytce
- płyta główna z drukarki ze złączem USB i kolejnym enkoderem
- śrubki
W powyższym zestawie nie ma ani jednego silnika krokowego (jak już to trafiałem na nie w układach od skaneru) i nie ma zasilacza, gdyż ta drukarka miała zasilacz zewnętrzny który chyba od mnie nie trafił.
Poniżej spróbuję coś z pokazanych tutaj części zdziałać i zademonstrować, że można ich użyć do hobbystycznych projektów.
Pinout enkodera od karetki
Pierwsze czym się zainteresowałem to enkoder pozwalający określić nam bieżącą pozycję karetki. Enkoder posiada szczelinę na wcześniej wspomniany pasek:

Enkoder ten ma 6 wyprowadzeń, z jednej strony dwa, z drugiej cztery:

Enkoder ten zawiera w sobie jedną diodę i dwa czujniki. Jego schemat naszkicowałem poniżej:

Pomiędzy diodą a dwoma czujnikami przesuwa się wcześniej pokazany pasek - w trakcie przesuwania zasłania czujniki (czasem jeden, czasem drugi, czasem oba) co pozwala nam określić jego ruch i co za tym idzie pozycje karetki.
Dioda od enkodera oczywiście wymaga rezystora - możliwe, że jest on gdzieś w pobliżu na PCB. Jeśli będziemy sami uruchamiać enkoder, to też musimy pamiętać by ten rezystor tam dać.
Same wyprowadzenia enkodera nie są oznaczone i nie byłem w stanie znaleźć jego dokumentacji w internecie, choć znalazłem informacje mówiącą o tym, że nie są one standaryzowane i mogą być różne w zależności od modelu drukarki.
Dlatego uważam, że warto wiedzieć, jak samemu określić który pin jest który.
Zacząć można od najprostszego - masy:

Ten pin oczywiście będzie podłączony do masy całego układu/wylewki masowej na płytce. Na zdjęciu powyżej pokazuję że jest bezpośrednie połączenie między wybranym pinem enkodera a testowym pinem masy na PCB.
Następnie warto rozpoznać VDD - zasilanie - w moim przypadku było na dwóch pinach:

O tym, że jest to VDD możemy się domyśleć drogą eliminacji. Jeśli nie jest to masa, to co innego może być na dwóch pinach w takim enkoderze? Właśnie zasilanie - VDD. Jest ono podłączone zarówno do diody od enkodera, jak i do fototranzystorów z niego. VDD też jest często podłączone do + kondensatora elektrolitycznego.
Dalej upewniłem się co do wyprowadzeń diody. Są one po jednej stronie enkodera, tam gdzie są tylko dwa piny. Użyłem do tego testu diody w moim multimetrze - pokazuje on spadek napięcia. Oczywiście dioda przewodzi tylko w jedną stronę, w drugą stronę tego odczytu nie będzie.

W tym momencie można już metodą eliminacji określić które piny (te dwa pozostałe) są wyjściami sygnałowymi czujników.
Tak rozpoznałem wyprowadzenia enkodera.
Na koniec trzeba zwrócić uwagę, że enkodery naprawdę mają różne wyprowadzenia i czasem np. na dwóch pinach mają masę, a czasem na dwóch pinach zasilanie...
Też należy pamiętać, że enkoder przy swojej diodzie nie ma rezystora - musimy sami go tam dać.
Podłączenie się do enkodera i karetki
Teraz coś mało odkrywczego, lecz niezbędnego - sposób na podłączenie się do enkodera na karetce.
Można po prostu dać własne przewody i może tak jest najprościej, ale ja postanowiłem użyć istniejącej tasiemki.
W tym celu usunąłem z płytki zbędny układ scalony z pomocą pistoletu na gorące powietrze oraz usunąłem wszelkie połączenia układu z tasiemką (z jej złączem) z pomocą małej szlifierki:


Podkreślam - przy robieniu podłączenia tą metodą należy usunąć WSZELKIE ZWARCIA oraz ZBĘDNE ELEMENTY z pinów od tasiemki i od nóżek enkodera. Inaczej można stracić dużo czasu na sprawdzanie potem czemu coś nie działa bo będzie np. zwierać zbędnie sygnał nam zapomniany rezystor SMD lub przelotka.
Następnie wykonałem połączenia bezpośrednio od pinów enkodera do pinów złącza tasiemki. Do tego umieściłem tam rezystor:



Gotowa płytka karetki:


Teraz trzeba powtórzyć ten sam zabieg dla złącza z drugiej strony. Złącze na tasiemkę wyciąłem z PCB i sprawdziłem multimetrem czy nie ma zwarć, a te co były to usunąłem.

Do złącza tego przylutowałem kabelki które pasują do Arduino:

Zachowałem kolorystykę połączeń zgodną z tym co miałem przy enkoderze:

Tak powstały wszystkie niezbędne połączenia dla testu już z Arduino, który przedstawię w następnym akapicie.
Test enkodera - ADC
Na początek przetestowałem enkoder z użyciem ADC. Enkoder najpierw zasiliłem z 5V, ale szybko okazało się, że 3.3V z Arduino też starcza i tego napięcia polecam Wam na początek użyć.
Podłączenie do Arduino przedstawiam na zdjęciu:


Użyty sketch:
Code: c
Rezultat (w trakcie przesuwania głowicy):

Wygląda na to, że wszystko jest ok - wartość z ADC jest taka a nie inna dlatego, że enkoder zasiliłem z 3.3V z płytki Arduino a nie z 5V.
1024*(3.3/5)=675, czyli około to co widzimy na UART.
Następnie przerobiłem program tak by nie korzystał z ADC.
Test enkodera - digitalRead
Poniższy kod robi zasadniczo to samo co wcześniejszy przykład, po prostu korzysta z digitalRead zamiast zupełnie zbędnego w tej sytuacji analogRead. Warto zwrócić uwagę, że pin enkodera konfiguruję tutaj w trybie wejścia z rezystorem pullup (do zasilania), czyli INPUT_PULLUP, a nie np. tylko INPUT.
Code: c
Rezultat (w trakcie przesuwania głownicy):

Za pomocą tego kodu sprawdziłem oba wyjścia enkodera i oba dawały poprawny odczyt.
Test enkodera - odczyt z obu czujników
Następnie zmodyfikowałem kod tak, aby odczytywał wartości z obu czujników enkodera jednocześnie. Pozwoli to nam zaobserwować jak zmieniają się one względem siebie w trakcie przesuwania karetki.
Code: c
Poniżej przedstawiam rezultaty działania kodu.
Ruch do strony silnika:

Ruch od strony silnika:

Porównanie na jednym obrazku:

Widać tutaj, że dzięki użyciu dwóch czujników tego enkodera na raz też możliwe jest określenie kierunku w który przesuwa karetka. Nieco dalej na pewno z tego skorzystam.
(oczywiście by mieć sensowne odczyty Arduino musi nadążać z próbkowaniem enkodera i nie może gubić pasków)
Wykrycie pozycji skrajnej/stopu - 'endstop'
Kolejną rzeczą która przyda się zrobić jest wykrycie początkowej (bądź, jak kto woli - końcowej) pozycji karetki - czyli end stop. Jest to coś niemalże nie do obejścia - nawet drukarki 3D (w tym mój Ender 3 Pro) mają podobny mechanizm.
Zrealizuję go tutaj w oparciu o kolejny element wymontowany wcześniej z drukarki:


Element ten po prostu zwiera styki w momencie gdy jest naciśnięty.
Jego oznaczenie to DMBL-01L 1A125 i można znaleźć o nim nieco informacji w sieci. Co ciekawe jest on używany też w myszkach komputerowych:

Ale myślę, że my nie potrzebujemy dodatkowych informacji na jego temat - obsługuje się go tak jak normalny przycisk w Arduino (digitalRead), dla wygody z wewnętrznym rezystorem pullup (tryb INPUT_PULLUP). Element podłączymy między ten pin a masę.
Element zamontowałem z pomocą małej śrubki:

Dodatkowo zakleiłem jego od strony PCB by nie zrobić przypadkiem spięcia:

Zamontowany element:


Zostało tylko przygotować kod - odczyt stanu przycisku i wysyłanie go na UART w celu sprawdzenia czy wszystko działa.
Całość poniżej:
Code: c
Kod przetestowałem w dwóch pozycjach karetki.
Test endstop - karetka zaparkowana (przycisk jest wciśnięty, więc pin jest zwarty do masy, więc mamy 0):


Test endstop - karetka poza pozycja 0 (przycisk nie jest wciśnięty; pin nie jest zwarty do masy, ale jest pullup - rezystor do VCC, więc mamy 1):


Sterowanie silnikiem DC poprzez moduł L298N
Mamy już:
- obsługę enkodera (zliczanie przesunięcia w oparciu o encoder strip)
- obsługę wykrywania endstop
Brakuje nam jeszcze obsługi silnika.
Jest to silnik DC, kierunek przepływu prądu określa kierunek obrotów, więc potrzebny będzie mostek H. Najlepiej użyć gotowego modułu. Wybrałem moduł oparty o układ scalony L298N:

Powyżej pokazany moduł obsługuje dwa silniki DC i łatwo jest go znaleźć w wielu sklepach online.
Pracuje na napięciach do 35V i prądach do 2A. Na pewno starczy.
Schemat podłączenia silnika oraz jego sterowania:

Nota katalogowa L298:
W ramach testu L298 przygotowałem prosty kod, który tylko i wyłącznie steruje silnikiem - po prostu co sekundę zmienia kierunek obrotów:
Code: c
Linia z analogWrite określa wypełnienie PWM czyli szybkość obrotów, natomiast digitalWrite dla pinów DA i DB określają kierunek obrotów.
Niestety napięcie 5V tutaj okazało się za małe dla silnika od karetki; musiałem użyć zasilacza 12V DC:


Po jego odpowiednim podłączeniu silnik ruszył.
Rezultat na filmie:
Karetka już się porusza - w następnym akapicie przedstawię nieco lepsze nią sterowanie.
Parkowanie i zliczanie kroków enkoderem
Następnie mogłem już przygotować nieco bardziej zaawansowany przykład który wykorzysta już wcześniej omówiony detektor parkowania jak również enkoder (ale tylko jeden jego czujnik).
Działanie przykładu opiera się na obsłudze bieżącego stanu urządzenia określonego enumeracją command_e.
Zmienna offset określa bieżącą pozycję karetki.
Zmienna repeats tutaj tylko pomaga wykryć zatrzymanie karetki.
Zmienna prev_encoderA pamięta poprzedni stan odczytany z enkodera (wysoki lub niski), bo potrzebujemy go porównywać z bieżącym by móc wykryć zmianę.
Cały kod poniżej:
Code: c
Przykład powyżej jeszcze nie obsługuje zliczania ruchu na pasku enkodera w obie strony, to przedstawię w następnym akapicie. Mimo to wszystko dobrze działa. co przedstawię na filmikach.
Test z karetką na drugim końcu szyny:
Test z karetką przy początku szyny:
Arduino wykrywa w którym momencie karetka osiągnie skrajną wartość na szynie i wtedy przesuwa ją na drugą stronę. Po wykonaniu ruchu na UART wysyłana jest liczba zliczonych kroków.
Parkowanie i zliczanie kroków enkoderem - na przerwaniach
Kod z poprzedniego akapitu aż prosi się poprawić tak, by korzystał z przerwań - a dokładniej z przerwania 'on change'.
W Arduino UNO jest ono dostępne na pinach 2 i 3.
Więcej informacji tutaj:
https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/
Do takich rzeczy należy używać przerwań, a nie sprawdzać ich co pętle tak jak w poprzednim przykładzie. Sprawdzanie co pętle może zawieść zwłaszcza jeśli chcemy coś w tej pętli robić oprócz sprawdzania.
Przy okazji dodałem też obsługę zliczania kroków enkodera w obie strony - czyli odczyt z drugiego czujnika enkodera. Szczegóły w kodzie (w funkcji przerwania):
Code: c
Przesunięcie karetki do wybranej pozycji
Teraz można jeszcze dodać osobną 'komendę' do kodu, czyli przesuwanie karetki na daną pozycję. Zrealizuję to w obsłudze przerwania, po prostu będę sprawdzać czy karetka jest za czy przed oczekiwaną pozycją. Oczekiwana pozycja będzie opisana zmienną target_offset.
Pełny kod:
Code: c
Rezultat:
Powyższy kod jest bardzo prymitywny. Sprawdzenie osiągnięcia celu karetki realizowane jest tutaj:
Code: c
Niestety takie rozwiązanie w wielu przypadkach może się nie sprawdzić - karetka będzie siłą rozpędu przeskakiwać swój cel i na przemian będzie wywoływać się ruch w prawo i w lewo (raz setup_move(0,120) a raz setup_move(1,120)).
Można tu kombinować i np. bazować moc silnika na odległości od celu, choćby w ten sposób:
Code: c
albo zaprząc do pracy jakiś poważniejszy algorytm.
Poprawić też tu mógłbym mechanikę tej karetki z drukarki, bo w moim przypadku ma luzy na szynie, ale uznałem że w ramach demonstracji jest to dopuszczalne. Być może wkrótce wrócę do tego projektu i coś więcej na nim zrealizuję.
Sam kod powyżej też można by zoptymalizować, choćby digitalWrite w Arduino jest dość wolne (sprawdza indeks pinu, itp):
Spoiler:
Code: c
Można je zamienić na zapis bezpośrednio do rejestru portu (np. do PORTB), operacja wykona się szybciej a efekt będzie ten sam. Jest to o dziwo bardzo duża zmiana, daje raptem jeden rozkaz zamiast kilkunastu lub więcej.
Podsumowanie
Pokazałem tu wnętrze drukarki HP Deskjet D1360 oraz zaprezentowałem jak można samemu obsłużyć jej enkoder i karetkę na platformie Arduino. Pokazane przykłady można by znacznie ulepszyć i pociągnąć dalej, a na bazie ich zrealizować jakiś bardziej zaawansowany projekt.
Oczywiście w pełni zdaję sobie sprawę z tego, że o wiele wygodniej steruje się silnikami krokowymi, ale celem tematu było przedstawienie działania enkodera z drukarki a nie szukanie najlepszego rozwiązania.
W kolejce do rozebrania mam też kilka skanerów z silnikami krokowymi, więc być może je też wkrótce opiszę.
Cool! Ranking DIY