A library to control a standard inkjet printer carriage.

Files at this revision

API Documentation at this revision

Comitter:
mattegan
Date:
Fri Nov 04 06:17:58 2016 +0000
Commit message:
[change] initial commit

Changed in this revision

PrintHead.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PrintHead.h	Fri Nov 04 06:17:58 2016 +0000
@@ -0,0 +1,110 @@
+#include "mbed.h"
+
+/** PrintHead allows you to control a inkjet printer carriage.
+ * This library expects the DC motor is controlled using three outputs,
+ * one PWM output should set the speed, and the other two should turn the motor
+ * on in a the left and right direction when brought high. The implementation
+ * circuitry is an implementation detail of which the library has no concern.
+ *
+ * The library also expects two interrupt pins that are used as inputs from the
+ * two photo interrupter outputs from the carriage. If the carriage is moving
+ * to the right the "right encoder" input should rise while the "left encoder" 
+ * or fall while the "left encoder" is low. The opposite should be true for the
+ * "left encoder". If in doubt, try one, output the count continuously to a
+ * serial terminal. Positive numbers are to the right on the count. If it's
+ * backwards, just flip the writing or the declaration of your instance.
+ */
+
+class PrintHead {
+public:
+
+    // positive is to the right
+    // negative is to the left
+    int count;
+    int goal;
+
+    /** Constructor
+     * 
+     * @param PinName left_motor_pin when this pin is high, the carriage should move left
+     * @param PinName right_motor_pin when this pin is high, the carriage should move right
+     * @param PinName motor_pwm_pin this should control the speed of the motor
+     * @param PinName left_encoder_pin the encoder output on the left side of the carriage
+     * @param PinName right_encoder_pin the encoder output on the right side of the carriage
+     *
+     * The initial goal and count position is 0. These are public so change
+     * or read them at will. The class will attempt to servo at whatever goal
+     * position is set.
+     */ 
+    PrintHead(PinName left_motor_pin, 
+              PinName right_motor_pin, 
+              PinName motor_pwm_pin,
+              PinName left_encoder_pin,
+              PinName right_encoder_pin) :
+              _left_motor(left_motor_pin),
+              _right_motor(right_motor_pin),
+              _motor_speed(motor_pwm_pin),
+              _left_encoder(left_encoder_pin),
+              _right_encoder(right_encoder_pin) {
+        
+        // change the motor pwm speed for smooth motor operation
+        // if the pwm frequency is too low the motor jerks the
+        // print head along the track as the PWM toggles on and off
+        _motor_speed.period(0.0001);
+        _motor_speed = 0.6;
+        
+        _left_encoder.rise(this, &PrintHead::left_encoder_rising);
+        _left_encoder.fall(this, &PrintHead::left_encoder_falling);
+        _right_encoder.rise(this, &PrintHead::right_encoder_rising);
+        _right_encoder.fall(this, &PrintHead::right_encoder_falling);
+        
+        _update_motor_ticker.attach_us(this, &PrintHead::update_motor, 1000);
+        
+        count = 0;
+        goal = 0;
+    }
+        
+    void left_encoder_rising() {
+        if(_right_encoder) count--;
+        else count++;
+    }
+    
+    void left_encoder_falling() {
+        if(_right_encoder) count++;
+        else count--;
+    }
+    
+    void right_encoder_rising() {
+        if(_left_encoder) count++;
+        else count--;
+    }
+    
+    void right_encoder_falling() {
+        if(_left_encoder) count--;
+        else count++;
+    }
+    
+    void update_motor() {
+        _left_motor = 0;
+        _right_motor = 0;
+        
+        // gate between 0.4 and 1;
+        // it should be 1 if we're more than 200 away from the goal
+        // between 200 and 0 from the goal, that should be 1 -> 0.4
+        int dist = abs(goal - count);
+        if(dist > 1000) _motor_speed = 1;
+        else _motor_speed = (0.0006 * dist) + 0.4;
+        if(dist > 20) {
+            _left_motor = (count > goal);
+            _right_motor = (count < goal);
+        }
+    }
+    
+private:
+    DigitalOut _left_motor;
+    DigitalOut _right_motor;
+    PwmOut _motor_speed;
+    InterruptIn _left_encoder;
+    InterruptIn _right_encoder;
+    Ticker _update_motor_ticker;
+    
+};