1 /*
2  * Author: Jon Trulson <jtrulson@ics.com>
3  * Copyright (c) 2015 Intel Corporation.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining
6  * a copy of this software and associated documentation files (the
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sublicense, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be
14  * included in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24 #pragma once
25 
26 #include <stdint.h>
27 #include <sys/time.h>
28 
29 #include <string>
30 #include <mraa/i2c.h>
31 #include <mraa/gpio.h>
32 
33 #include "pca9685.h"
34 
35 #define ADAFRUITMS1438_I2C_BUS 0
36 #define ADAFRUITMS1438_DEFAULT_I2C_ADDR 0x60
37 
38 namespace upm {
39 
40   /**
41    * @brief Adafruit Motor Shield 1438 library
42    * @defgroup adafruitms1438 libupm-adafruitms1438
43    * @ingroup adafruit i2c motor
44    */
45 
46   /**
47    * @library adafruitms1438
48    * @sensor adafruitms1438
49    * @comname Adafruit Motor Shield
50    * @type motor
51    * @man adafruit
52    * @web http://www.adafruit.com/products/1438
53    * @con i2c
54    *
55    * @brief API for the AdafruitMS1438 Motor Shield
56    *
57    * This class implements support for the stepper and DC motors that
58    * can be connected to this Motor Shield.
59    * Note: the two servo connections are not controlled by the PCA9685
60    * controller (or this class). They are connected directly to digital
61    * PWM pins 9 and 10 on the Arduino* breakout board.
62    *
63    * @image html adafruitms1438.jpg
64    * An example using a DC motor connected to M3
65    * @snippet adafruitms1438.cxx Interesting
66    * An example using a stepper motor connected to M1 & M2
67    * @snippet adafruitms1438-stepper.cxx Interesting
68    */
69   class AdafruitMS1438 {
70   public:
71 
72     /**
73      * Enum to specify the direction of a motor
74      */
75     typedef enum {
76       DIR_NONE = 0x00,
77       DIR_CW   = 0x01,
78       DIR_CCW  = 0x02
79     } DIRECTION_T;
80 
81     /**
82      * Enum to specify a DC motor
83      */
84     typedef enum {
85       MOTOR_M1 = 0,
86       MOTOR_M2 = 1,
87       MOTOR_M3 = 2,
88       MOTOR_M4 = 3
89     } DCMOTORS_T;
90 
91     /**
92      * Enum to specify a stepper motor
93      */
94     typedef enum {
95       STEPMOTOR_M12 = 0,
96       STEPMOTOR_M34 = 1
97     } STEPMOTORS_T;
98 
99     /**
100      * AdafruitMS1438 constructor
101      *
102      * @param bus I2C bus to use
103      * @param address Address for this sensor
104      */
105     AdafruitMS1438(int bus, uint8_t address = ADAFRUITMS1438_DEFAULT_I2C_ADDR);
106 
107     /**
108      * AdafruitMS1438 destructor
109      */
110     ~AdafruitMS1438();
111 
112     /**
113      * Returns the number of milliseconds elapsed since initClock(...)
114      * was last called.
115      *
116      * @return Elapsed milliseconds
117      */
118     uint32_t getMillis(STEPMOTORS_T motor);
119 
120     /**
121      * Resets the clock
122      *
123      */
124     void initClock(STEPMOTORS_T motor);
125 
126     /**
127      * Sets the PWM period.  Note: this applies to all PWM channels.
128      *
129      * @param hz Sets the PWM period
130      */
131     void setPWMPeriod(float hz);
132 
133     /**
134      * Enables PWM output for a motor
135      *
136      * @param motor DC motor to enable
137      */
138     void enableMotor(DCMOTORS_T motor);
139 
140     /**
141      * Disables PWM output for a motor
142      *
143      * @param motor DC motor to disable
144      */
145     void disableMotor(DCMOTORS_T motor);
146 
147     /**
148      * Enables output for a stepper motor
149      *
150      * @param motor Stepper motor to enable
151      */
152     void enableStepper(STEPMOTORS_T motor);
153 
154     /**
155      * Disable output for a stepper motor
156      *
157      * @param motor Stepper motor to disable
158      */
159     void disableStepper(STEPMOTORS_T motor);
160 
161     /**
162      * set the speed of a DC motor.  Values can range from 0 (off) to
163      * 100 (full speed).
164      *
165      * @param motor the DC motor to configure
166      * @param speed speed to set the motor to
167      */
168     void setMotorSpeed(DCMOTORS_T motor, int speed);
169 
170     /**
171      * Sets the speed of a stepper in revolutions per minute (RPM)
172      *
173      * @param motor DC motor to configure
174      * @param speed Speed to set the motor to
175      */
176     void setStepperSpeed(STEPMOTORS_T motor, int speed);
177 
178     /**
179      * Sets the direction of a DC motor, clockwise or counterclockwise
180      *
181      * @param motor DC motor to configure
182      * @param dir Direction to set the motor in
183      */
184     void setMotorDirection(DCMOTORS_T motor, DIRECTION_T dir);
185 
186     /**
187      * Sets the direction of a stepper motor, clockwise or counterclockwise
188      *
189      * @param motor Stepper motor to configure
190      * @param dir Direction to set the motor in
191      */
192     void setStepperDirection(STEPMOTORS_T motor, DIRECTION_T dir);
193 
194     /**
195      * Sets a stepper motor configuration
196      *
197      * @param motor Stepper motor to configure
198      * @param stepsPerRev Number of steps to complete a full revolution
199      */
200     void stepConfig(STEPMOTORS_T motor, unsigned int stepsPerRev);
201 
202     /**
203      * Steps a stepper motor a specified number of steps
204      *
205      * @param motor Stepper motor to step
206      * @param steps Number of steps to move the stepper motor
207      */
208     void stepperSteps(STEPMOTORS_T motor, unsigned int steps);
209 
210   private:
211     // SWIG will generate a warning for these 'nested structs'; however,
212     // it can be ignored as these structs are never exposed.
213 
214     // struct to hold mappings of DC motors
215     typedef struct {
216       int pwm;
217       int in1;
218       int in2;
219     } DC_PINMAP_T;
220 
221     // struct to hold mappings of stepper motors
222     typedef struct {
223       int pwmA;
224       int in1A;
225       int in2A;
226       int pwmB;
227       int in1B;
228       int in2B;
229     } STEPPER_PINMAP_T;
230 
231     // struct to hold information about each stepper
232     typedef struct {
233       int stepsPerRev;          // steps per revolution
234       int currentStep;          // current step number
235       uint32_t stepDelay;       // delay between steps
236       int stepDirection;        // direction to step
237       struct timeval startTime; // starting time
238     } STEPPER_CONFIG_T;
239 
240     void setupPinMaps();
241     void stepperStep(STEPMOTORS_T motor);
242 
243     DC_PINMAP_T m_dcMotors[4];
244     STEPPER_PINMAP_T m_stepMotors[2];
245     STEPPER_CONFIG_T m_stepConfig[2];
246 
247     PCA9685 *m_pca9685;
248   };
249 }
250 
251 
252