Hallo zusammen,
ich versuche mich gerade daran einen alten Inkjet-Drucker in einen Flachbrettdrucker umzubauen. Da ich den Drucker nicht speziell ansteuern kann, ist mein Plan das Signal vom eingebauten Rotary Optical Encoder auszulesen und damit parallel zum originalen Motor für den Papiereinzug einen Steppermotor anzutreiben. Der originale Motor ist dann quasi nur ein Phantom, was nur den Feedback-Loop für den Drucker aufrecht erhält. Mir ist bewusst, dass das Timing, etc. mit meinem Stepper vorerst nicht passend sein wird, aber es scheint generell so möglich zu sein (siehe: https://www.youtube.com/watch?v=OYe5iC8Qe3E&t=251s ab 4:11).
Ich habe den Encoder bereits durchgemessen und die beiden Signalpins ausfindig gemacht sowie die vom Drucker aus anliegenden Spannungen notiert:
Außerdem habe ich Kabel an die beiden Signalpins (grün und lila) gelötet und diese mit Pin 8 und 9 meines Arduino Uno Rev3 Boards verbunden. Die Signale (zwischen 0V und 3,22V) möchte ich mit folgendem Code auslesen:
#include <avr/interrupt.h> // AVR interrupt handling
#include <Arduino.h> // Arduino core library
#include <stdint.h> // Standard integer types
#include <stdbool.h> // Standard boolean types
volatile uint8_t OldState = 0; // Store the previous state of the encoder pins
volatile int32_t Position = 0; // Store the current position value
volatile bool InvalidInc = false; // Flag indicating an invalid increment
const int8_t IncArray[4][4] = {
{0, -1, 1, 2}, // Lookup table for valid increments based on state transitions
{1, 0, 2, -1},
{-1, 2, 0, 1},
{2, 1, -1, 0}
};
void setup() {
Serial.begin(9600); // Initialize serial communication
pinMode(8, INPUT); // Configure digital pin 8 as input
pinMode(9, INPUT); // Configure digital pin 9 as input
cli(); // Disable interrupts
PCICR |= 0b00000001; // Enable Pin Change Interrupt for PORT B (PCIE0)
PCMSK0 |= 0b00000011; // Enable interrupt for PCINT0 (D8) and PCINT1 (D9)
sei(); // Enable interrupts
}
void loop() {
delay(100); // Delay for readability
Serial.println(Position, DEC); // Print the current position in decimal
if (InvalidInc) {
Serial.println("LOST COUNT"); // Print a message indicating a lost count
InvalidInc = false; // Reset the invalid increment flag
}
}
ISR(PCINT0_vect) {
uint8_t State = PINB & 0b00000011; // Read the state of the encoder pins
int8_t Inc = IncArray[OldState][State]; // Get the increment value from the lookup table
OldState = State; // Update the previous state
Position += Inc; // Update the position value
// Set the InvalidInc flag if the increment is 2
InvalidInc |= (Inc == 2);
}
Den Code habe ich in folgendem Beitrag gefunden: Using a Canon Printer Incremental Encoder + Datasheet - #6 by snuffwooter
Dort habe ich dann auch herausgefunden, dass es sich bei dem Encoder um ein Modell vom Hersteller Kodenshi handelt (die genaue Modellnummer habe ich nicht gefunden) und er anscheinend eine Auflösung von 360 LPI hat.
Nun zum eigentlichen Problem: Im Gegensatz zum Ersteller des Codes funktioniert dieser bei mir nicht korrekt. Ich bekomme alle möglichen verrückten Zustände in der State Variable - auch wenn gar keine Spannung anliegt. Nach ein bisschen Recherche habe ich dann herausgefunden, dass das wahrscheinlich an Floating Pins liegt und ich kein definiertes LOW habe. Also habe ich einen 10k Pulldown-Widerstand eingebaut mit dem Effekt, dass zwar keine falschen Signale mehr ankommen, ich aber auch keine Signale bekomme, wenn sich die Encoder-Scheibe dreht. Meine Schaltung sieht ungefähr so aus:
Dabei sind die beiden langen Verbindungen von rechts die beiden Signalpins vom Encoder.
Als jemand der sich nicht wirklich mit Elektrotechnik auskennt bin ich hier mit meinem Latein am Ende und hoffe, dass jemand mehr Ahnung hat, was ich falsch mache. Eventuell muss ich den Drucker und meinen Arduino auch irgendwie mit mehr als nur den beiden Signalpins verbinden, aber da bin ich sehr unsicher.
Viele Grüße
Nico