A library to control a standard inkjet printer carriage.

Committer:
mattegan
Date:
Fri Nov 04 06:17:58 2016 +0000
Revision:
0:a2dfb2b5f1c9
[change] initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mattegan 0:a2dfb2b5f1c9 1 #include "mbed.h"
mattegan 0:a2dfb2b5f1c9 2
mattegan 0:a2dfb2b5f1c9 3 /** PrintHead allows you to control a inkjet printer carriage.
mattegan 0:a2dfb2b5f1c9 4 * This library expects the DC motor is controlled using three outputs,
mattegan 0:a2dfb2b5f1c9 5 * one PWM output should set the speed, and the other two should turn the motor
mattegan 0:a2dfb2b5f1c9 6 * on in a the left and right direction when brought high. The implementation
mattegan 0:a2dfb2b5f1c9 7 * circuitry is an implementation detail of which the library has no concern.
mattegan 0:a2dfb2b5f1c9 8 *
mattegan 0:a2dfb2b5f1c9 9 * The library also expects two interrupt pins that are used as inputs from the
mattegan 0:a2dfb2b5f1c9 10 * two photo interrupter outputs from the carriage. If the carriage is moving
mattegan 0:a2dfb2b5f1c9 11 * to the right the "right encoder" input should rise while the "left encoder"
mattegan 0:a2dfb2b5f1c9 12 * or fall while the "left encoder" is low. The opposite should be true for the
mattegan 0:a2dfb2b5f1c9 13 * "left encoder". If in doubt, try one, output the count continuously to a
mattegan 0:a2dfb2b5f1c9 14 * serial terminal. Positive numbers are to the right on the count. If it's
mattegan 0:a2dfb2b5f1c9 15 * backwards, just flip the writing or the declaration of your instance.
mattegan 0:a2dfb2b5f1c9 16 */
mattegan 0:a2dfb2b5f1c9 17
mattegan 0:a2dfb2b5f1c9 18 class PrintHead {
mattegan 0:a2dfb2b5f1c9 19 public:
mattegan 0:a2dfb2b5f1c9 20
mattegan 0:a2dfb2b5f1c9 21 // positive is to the right
mattegan 0:a2dfb2b5f1c9 22 // negative is to the left
mattegan 0:a2dfb2b5f1c9 23 int count;
mattegan 0:a2dfb2b5f1c9 24 int goal;
mattegan 0:a2dfb2b5f1c9 25
mattegan 0:a2dfb2b5f1c9 26 /** Constructor
mattegan 0:a2dfb2b5f1c9 27 *
mattegan 0:a2dfb2b5f1c9 28 * @param PinName left_motor_pin when this pin is high, the carriage should move left
mattegan 0:a2dfb2b5f1c9 29 * @param PinName right_motor_pin when this pin is high, the carriage should move right
mattegan 0:a2dfb2b5f1c9 30 * @param PinName motor_pwm_pin this should control the speed of the motor
mattegan 0:a2dfb2b5f1c9 31 * @param PinName left_encoder_pin the encoder output on the left side of the carriage
mattegan 0:a2dfb2b5f1c9 32 * @param PinName right_encoder_pin the encoder output on the right side of the carriage
mattegan 0:a2dfb2b5f1c9 33 *
mattegan 0:a2dfb2b5f1c9 34 * The initial goal and count position is 0. These are public so change
mattegan 0:a2dfb2b5f1c9 35 * or read them at will. The class will attempt to servo at whatever goal
mattegan 0:a2dfb2b5f1c9 36 * position is set.
mattegan 0:a2dfb2b5f1c9 37 */
mattegan 0:a2dfb2b5f1c9 38 PrintHead(PinName left_motor_pin,
mattegan 0:a2dfb2b5f1c9 39 PinName right_motor_pin,
mattegan 0:a2dfb2b5f1c9 40 PinName motor_pwm_pin,
mattegan 0:a2dfb2b5f1c9 41 PinName left_encoder_pin,
mattegan 0:a2dfb2b5f1c9 42 PinName right_encoder_pin) :
mattegan 0:a2dfb2b5f1c9 43 _left_motor(left_motor_pin),
mattegan 0:a2dfb2b5f1c9 44 _right_motor(right_motor_pin),
mattegan 0:a2dfb2b5f1c9 45 _motor_speed(motor_pwm_pin),
mattegan 0:a2dfb2b5f1c9 46 _left_encoder(left_encoder_pin),
mattegan 0:a2dfb2b5f1c9 47 _right_encoder(right_encoder_pin) {
mattegan 0:a2dfb2b5f1c9 48
mattegan 0:a2dfb2b5f1c9 49 // change the motor pwm speed for smooth motor operation
mattegan 0:a2dfb2b5f1c9 50 // if the pwm frequency is too low the motor jerks the
mattegan 0:a2dfb2b5f1c9 51 // print head along the track as the PWM toggles on and off
mattegan 0:a2dfb2b5f1c9 52 _motor_speed.period(0.0001);
mattegan 0:a2dfb2b5f1c9 53 _motor_speed = 0.6;
mattegan 0:a2dfb2b5f1c9 54
mattegan 0:a2dfb2b5f1c9 55 _left_encoder.rise(this, &PrintHead::left_encoder_rising);
mattegan 0:a2dfb2b5f1c9 56 _left_encoder.fall(this, &PrintHead::left_encoder_falling);
mattegan 0:a2dfb2b5f1c9 57 _right_encoder.rise(this, &PrintHead::right_encoder_rising);
mattegan 0:a2dfb2b5f1c9 58 _right_encoder.fall(this, &PrintHead::right_encoder_falling);
mattegan 0:a2dfb2b5f1c9 59
mattegan 0:a2dfb2b5f1c9 60 _update_motor_ticker.attach_us(this, &PrintHead::update_motor, 1000);
mattegan 0:a2dfb2b5f1c9 61
mattegan 0:a2dfb2b5f1c9 62 count = 0;
mattegan 0:a2dfb2b5f1c9 63 goal = 0;
mattegan 0:a2dfb2b5f1c9 64 }
mattegan 0:a2dfb2b5f1c9 65
mattegan 0:a2dfb2b5f1c9 66 void left_encoder_rising() {
mattegan 0:a2dfb2b5f1c9 67 if(_right_encoder) count--;
mattegan 0:a2dfb2b5f1c9 68 else count++;
mattegan 0:a2dfb2b5f1c9 69 }
mattegan 0:a2dfb2b5f1c9 70
mattegan 0:a2dfb2b5f1c9 71 void left_encoder_falling() {
mattegan 0:a2dfb2b5f1c9 72 if(_right_encoder) count++;
mattegan 0:a2dfb2b5f1c9 73 else count--;
mattegan 0:a2dfb2b5f1c9 74 }
mattegan 0:a2dfb2b5f1c9 75
mattegan 0:a2dfb2b5f1c9 76 void right_encoder_rising() {
mattegan 0:a2dfb2b5f1c9 77 if(_left_encoder) count++;
mattegan 0:a2dfb2b5f1c9 78 else count--;
mattegan 0:a2dfb2b5f1c9 79 }
mattegan 0:a2dfb2b5f1c9 80
mattegan 0:a2dfb2b5f1c9 81 void right_encoder_falling() {
mattegan 0:a2dfb2b5f1c9 82 if(_left_encoder) count--;
mattegan 0:a2dfb2b5f1c9 83 else count++;
mattegan 0:a2dfb2b5f1c9 84 }
mattegan 0:a2dfb2b5f1c9 85
mattegan 0:a2dfb2b5f1c9 86 void update_motor() {
mattegan 0:a2dfb2b5f1c9 87 _left_motor = 0;
mattegan 0:a2dfb2b5f1c9 88 _right_motor = 0;
mattegan 0:a2dfb2b5f1c9 89
mattegan 0:a2dfb2b5f1c9 90 // gate between 0.4 and 1;
mattegan 0:a2dfb2b5f1c9 91 // it should be 1 if we're more than 200 away from the goal
mattegan 0:a2dfb2b5f1c9 92 // between 200 and 0 from the goal, that should be 1 -> 0.4
mattegan 0:a2dfb2b5f1c9 93 int dist = abs(goal - count);
mattegan 0:a2dfb2b5f1c9 94 if(dist > 1000) _motor_speed = 1;
mattegan 0:a2dfb2b5f1c9 95 else _motor_speed = (0.0006 * dist) + 0.4;
mattegan 0:a2dfb2b5f1c9 96 if(dist > 20) {
mattegan 0:a2dfb2b5f1c9 97 _left_motor = (count > goal);
mattegan 0:a2dfb2b5f1c9 98 _right_motor = (count < goal);
mattegan 0:a2dfb2b5f1c9 99 }
mattegan 0:a2dfb2b5f1c9 100 }
mattegan 0:a2dfb2b5f1c9 101
mattegan 0:a2dfb2b5f1c9 102 private:
mattegan 0:a2dfb2b5f1c9 103 DigitalOut _left_motor;
mattegan 0:a2dfb2b5f1c9 104 DigitalOut _right_motor;
mattegan 0:a2dfb2b5f1c9 105 PwmOut _motor_speed;
mattegan 0:a2dfb2b5f1c9 106 InterruptIn _left_encoder;
mattegan 0:a2dfb2b5f1c9 107 InterruptIn _right_encoder;
mattegan 0:a2dfb2b5f1c9 108 Ticker _update_motor_ticker;
mattegan 0:a2dfb2b5f1c9 109
mattegan 0:a2dfb2b5f1c9 110 };