浏览代码

adafruitms1438: Initial implementation

The library implements support for the Adafruit MotorShield 1438:
http://www.adafruit.com/products/1438

This shield supports 4 DC motors or 2 Stepper motors.

It makes use of the pca9685 UPM library, and therefore requires that
PR #123 and PR #134 are merged first:

PR 123: pkgconfig.in: allow a module to specify dependencies on
another module

PR 134: pca9685: Initial implementation

Signed-off-by: Jon Trulson <jtrulson@ics.com>
Signed-off-by: Zion Orent <zorent@ics.com>
Signed-off-by: Mihai Tudor Panu <mihai.tudor.panu@intel.com>
Jon Trulson 10 年前
父节点
当前提交
da0071ae71

+ 5
- 0
examples/c++/CMakeLists.txt 查看文件

@@ -99,6 +99,8 @@ add_executable (l298-stepper-example l298-stepper.cxx)
99 99
 add_executable (at42qt1070-example at42qt1070.cxx)
100 100
 add_executable (grovemd-example grovemd.cxx)
101 101
 add_executable (pca9685-example pca9685.cxx)
102
+add_executable (adafruitms1438-example adafruitms1438.cxx)
103
+add_executable (adafruitms1438-stepper-example adafruitms1438-stepper.cxx)
102 104
 
103 105
 include_directories (${PROJECT_SOURCE_DIR}/src/hmc5883l)
104 106
 include_directories (${PROJECT_SOURCE_DIR}/src/grove)
@@ -179,6 +181,7 @@ include_directories (${PROJECT_SOURCE_DIR}/src/l298)
179 181
 include_directories (${PROJECT_SOURCE_DIR}/src/at42qt1070)
180 182
 include_directories (${PROJECT_SOURCE_DIR}/src/grovemd)
181 183
 include_directories (${PROJECT_SOURCE_DIR}/src/pca9685)
184
+include_directories (${PROJECT_SOURCE_DIR}/src/adafruitms1438)
182 185
 
183 186
 target_link_libraries (hmc5883l-example hmc5883l ${CMAKE_THREAD_LIBS_INIT})
184 187
 target_link_libraries (groveled-example grove ${CMAKE_THREAD_LIBS_INIT})
@@ -279,3 +282,5 @@ target_link_libraries (l298-stepper-example l298 ${CMAKE_THREAD_LIBS_INIT})
279 282
 target_link_libraries (at42qt1070-example at42qt1070 ${CMAKE_THREAD_LIBS_INIT})
280 283
 target_link_libraries (grovemd-example grovemd ${CMAKE_THREAD_LIBS_INIT})
281 284
 target_link_libraries (pca9685-example pca9685 ${CMAKE_THREAD_LIBS_INIT})
285
+target_link_libraries (adafruitms1438-example adafruitms1438 ${CMAKE_THREAD_LIBS_INIT})
286
+target_link_libraries (adafruitms1438-stepper-example adafruitms1438 ${CMAKE_THREAD_LIBS_INIT})

+ 82
- 0
examples/c++/adafruitms1438-stepper.cxx 查看文件

@@ -0,0 +1,82 @@
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
+
25
+#include <unistd.h>
26
+#include <signal.h>
27
+#include <iostream>
28
+#include "adafruitms1438.h"
29
+
30
+using namespace std;
31
+using namespace upm;
32
+
33
+int main(int argc, char **argv)
34
+{
35
+//! [Interesting]
36
+  // Instantiate an Adafruit MS 1438 on I2C bus 0
37
+
38
+  upm::AdafruitMS1438 *ms = 
39
+    new upm::AdafruitMS1438(ADAFRUITMS1438_I2C_BUS, 
40
+                            ADAFRUITMS1438_DEFAULT_I2C_ADDR);
41
+
42
+  // Setup for use with a stepper motor connected to the M1 & M2 ports
43
+
44
+  // set a PWM period of 50Hz
45
+
46
+  // disable first, to be safe
47
+  ms->disableStepper(AdafruitMS1438::STEPMOTOR_M12);
48
+
49
+  // configure for a NEMA-17, 200 steps per revolution
50
+  ms->stepConfig(AdafruitMS1438::STEPMOTOR_M12, 200);
51
+
52
+  // set speed at 10 RPM's
53
+  ms->setStepperSpeed(AdafruitMS1438::STEPMOTOR_M12, 10);
54
+  ms->setStepperDirection(AdafruitMS1438::STEPMOTOR_M12, 
55
+                          AdafruitMS1438::DIR_CW);
56
+
57
+  // enable
58
+  cout << "Enabling..." << endl;
59
+  ms->enableStepper(AdafruitMS1438::STEPMOTOR_M12);
60
+
61
+  cout << "Rotating 1 full revolution at 10 RPM speed." << endl;
62
+  ms->stepperSteps(AdafruitMS1438::STEPMOTOR_M12, 200);
63
+
64
+  cout << "Sleeping for 2 seconds..." << endl;
65
+  sleep(2);
66
+  cout << "Rotating 1/2 revolution in opposite direction at 10 RPM speed." 
67
+       << endl;
68
+
69
+  ms->setStepperDirection(AdafruitMS1438::STEPMOTOR_M12, 
70
+                          AdafruitMS1438::DIR_CCW);
71
+  ms->stepperSteps(AdafruitMS1438::STEPMOTOR_M12, 100);
72
+
73
+  cout << "Disabling..." << endl;
74
+  ms->disableStepper(AdafruitMS1438::STEPMOTOR_M12);
75
+
76
+  cout << "Exiting" << endl;
77
+
78
+//! [Interesting]
79
+
80
+  delete ms;
81
+  return 0;
82
+}

+ 75
- 0
examples/c++/adafruitms1438.cxx 查看文件

@@ -0,0 +1,75 @@
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
+
25
+#include <unistd.h>
26
+#include <signal.h>
27
+#include <iostream>
28
+#include "adafruitms1438.h"
29
+
30
+using namespace std;
31
+using namespace upm;
32
+
33
+int main(int argc, char **argv)
34
+{
35
+//! [Interesting]
36
+  // Instantiate an Adafruit MS 1438 on I2C bus 0
37
+
38
+  upm::AdafruitMS1438 *ms = 
39
+    new upm::AdafruitMS1438(ADAFRUITMS1438_I2C_BUS, 
40
+                            ADAFRUITMS1438_DEFAULT_I2C_ADDR);
41
+
42
+  // Setup for use with a DC motor connected to the M3 port
43
+
44
+  // set a PWM period of 50Hz
45
+  ms->setPWMPeriod(50);
46
+
47
+  // disable first, to be safe
48
+  ms->disableMotor(AdafruitMS1438::MOTOR_M3);
49
+
50
+  // set speed at 50%
51
+  ms->setMotorSpeed(AdafruitMS1438::MOTOR_M3, 50);
52
+  ms->setMotorDirection(AdafruitMS1438::MOTOR_M3, AdafruitMS1438::DIR_CW);
53
+
54
+  cout << "Spin M3 at half speed for 3 seconds, then reverse for 3 seconds."
55
+       << endl;
56
+
57
+  ms->enableMotor(AdafruitMS1438::MOTOR_M3);
58
+
59
+  sleep(3);
60
+
61
+  cout << "Reversing M3" << endl;
62
+  ms->setMotorDirection(AdafruitMS1438::MOTOR_M3, AdafruitMS1438::DIR_CCW);
63
+
64
+  sleep(3);
65
+
66
+  cout << "Stopping M3" << endl;
67
+  ms->disableMotor(AdafruitMS1438::MOTOR_M3);
68
+
69
+  cout << "Exiting" << endl;
70
+
71
+//! [Interesting]
72
+
73
+  delete ms;
74
+  return 0;
75
+}

+ 92
- 0
examples/javascript/adafruitms1438-stepper.js 查看文件

@@ -0,0 +1,92 @@
1
+/*jslint node:true, vars:true, bitwise:true, unparam:true */
2
+/*jshint unused:true */
3
+/*
4
+* Author: Zion Orent <zorent@ics.com>
5
+* Copyright (c) 2015 Intel Corporation.
6
+*
7
+* Permission is hereby granted, free of charge, to any person obtaining
8
+* a copy of this software and associated documentation files (the
9
+* "Software"), to deal in the Software without restriction, including
10
+* without limitation the rights to use, copy, modify, merge, publish,
11
+* distribute, sublicense, and/or sell copies of the Software, and to
12
+* permit persons to whom the Software is furnished to do so, subject to
13
+* the following conditions:
14
+*
15
+* The above copyright notice and this permission notice shall be
16
+* included in all copies or substantial portions of the Software.
17
+*
18
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22
+* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23
+* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24
+* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
+*/
26
+
27
+function exit()
28
+{
29
+	console.log("Exiting");
30
+
31
+	myMotorShield_obj = null;
32
+	if (MotorShield_lib)
33
+	{
34
+		MotorShield_lib.cleanUp();
35
+		MotorShield_lib = null;
36
+	}
37
+	process.exit(0);
38
+}
39
+
40
+var MotorShield_lib = require('jsupm_adafruitms1438');
41
+
42
+/* Import header values */
43
+var I2CBus = MotorShield_lib.ADAFRUITMS1438_I2C_BUS;
44
+var I2CAddr = MotorShield_lib.ADAFRUITMS1438_DEFAULT_I2C_ADDR;
45
+
46
+var M12motor = MotorShield_lib.AdafruitMS1438.STEPMOTOR_M12;
47
+var MotorDirCW = MotorShield_lib.AdafruitMS1438.DIR_CW;
48
+var MotorDirCCW = MotorShield_lib.AdafruitMS1438.DIR_CCW;
49
+
50
+
51
+// Instantiate an Adafruit MS 1438 on I2C bus 0
52
+var myMotorShield_obj = new MotorShield_lib.AdafruitMS1438(I2CBus, I2CAddr);
53
+
54
+
55
+// Setup for use with a stepper motor connected to the M1 & M2 ports
56
+
57
+// disable first, to be safe
58
+myMotorShield_obj.disableStepper(M12motor);
59
+
60
+// configure for a NEMA-17, 200 steps per revolution
61
+myMotorShield_obj.stepConfig(M12motor, 200);
62
+
63
+// set speed at 10 RPM's
64
+myMotorShield_obj.setStepperSpeed(M12motor, 10);
65
+myMotorShield_obj.setStepperDirection(M12motor, MotorDirCW);
66
+
67
+console.log("Enabling...");
68
+myMotorShield_obj.enableStepper(M12motor);
69
+
70
+console.log("Rotating 1 full revolution at 10 RPM speed.");
71
+myMotorShield_obj.stepperSteps(M12motor, 200);
72
+
73
+console.log("Sleeping for 2 seconds...");
74
+
75
+
76
+setTimeout(function()
77
+{
78
+	console.log("Rotating 1/2 revolution in opposite direction at 10 RPM speed.");
79
+
80
+	myMotorShield_obj.setStepperDirection(M12motor, MotorDirCCW);
81
+	myMotorShield_obj.stepperSteps(M12motor, 100);
82
+
83
+	console.log("Disabling...");
84
+	myMotorShield_obj.disableStepper(M12motor);
85
+	exit();
86
+}, 2000);
87
+
88
+
89
+process.on('SIGINT', function()
90
+{
91
+	exit();
92
+});

+ 89
- 0
examples/javascript/adafruitms1438.js 查看文件

@@ -0,0 +1,89 @@
1
+/*jslint node:true, vars:true, bitwise:true, unparam:true */
2
+/*jshint unused:true */
3
+/*
4
+* Author: Zion Orent <zorent@ics.com>
5
+* Copyright (c) 2015 Intel Corporation.
6
+*
7
+* Permission is hereby granted, free of charge, to any person obtaining
8
+* a copy of this software and associated documentation files (the
9
+* "Software"), to deal in the Software without restriction, including
10
+* without limitation the rights to use, copy, modify, merge, publish,
11
+* distribute, sublicense, and/or sell copies of the Software, and to
12
+* permit persons to whom the Software is furnished to do so, subject to
13
+* the following conditions:
14
+*
15
+* The above copyright notice and this permission notice shall be
16
+* included in all copies or substantial portions of the Software.
17
+*
18
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22
+* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23
+* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24
+* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
+*/
26
+
27
+function exit()
28
+{
29
+	console.log("Exiting");
30
+
31
+	myMotorShield_obj = null;
32
+	if (MotorShield_lib)
33
+	{
34
+		MotorShield_lib.cleanUp();
35
+		MotorShield_lib = null;
36
+	}
37
+	process.exit(0);
38
+}
39
+
40
+var MotorShield_lib = require('jsupm_adafruitms1438');
41
+
42
+
43
+/* Import header values */
44
+var I2CBus = MotorShield_lib.ADAFRUITMS1438_I2C_BUS;
45
+var I2CAddr = MotorShield_lib.ADAFRUITMS1438_DEFAULT_I2C_ADDR;
46
+
47
+var M3motor = MotorShield_lib.AdafruitMS1438.MOTOR_M3;
48
+var MotorDirCW = MotorShield_lib.AdafruitMS1438.DIR_CW;
49
+var MotorDirCCW = MotorShield_lib.AdafruitMS1438.DIR_CCW;
50
+
51
+
52
+// Instantiate an Adafruit MS 1438 on I2C bus 0
53
+var myMotorShield_obj = new MotorShield_lib.AdafruitMS1438(I2CBus, I2CAddr);
54
+
55
+
56
+// Setup for use with a DC motor connected to the M3 port
57
+
58
+// set a PWM period of 50Hz
59
+myMotorShield_obj.setPWMPeriod(50);
60
+
61
+// disable first, to be safe
62
+myMotorShield_obj.disableMotor(M3motor);
63
+
64
+// set speed at 50%
65
+myMotorShield_obj.setMotorSpeed(M3motor, 50);
66
+myMotorShield_obj.setMotorDirection(M3motor, MotorDirCW);
67
+
68
+process.stdout.write("Spin M3 at half speed for 3 seconds, ");
69
+console.log("then reverse for 3 seconds.");
70
+myMotorShield_obj.enableMotor(M3motor);
71
+
72
+setTimeout(function()
73
+{
74
+	console.log("Reversing M3");
75
+	myMotorShield_obj.setMotorDirection(M3motor, MotorDirCCW);
76
+}, 3000);
77
+
78
+
79
+setTimeout(function()
80
+{
81
+	console.log("Stopping M3");
82
+	myMotorShield_obj.disableMotor(M3motor);
83
+	exit();
84
+}, 6000);
85
+
86
+process.on('SIGINT', function()
87
+{
88
+	exit();
89
+});

+ 10
- 0
src/adafruitms1438/CMakeLists.txt 查看文件

@@ -0,0 +1,10 @@
1
+set (libname "adafruitms1438")
2
+set (libdescription "upm module for the Adafruit Motor Shield 1438")
3
+set (module_src ${libname}.cxx)
4
+set (module_h ${libname}.h)
5
+set (reqlibname "upm-pca9685")
6
+include_directories("../pca9685")
7
+upm_module_init()
8
+target_link_libraries(${libname} pca9685)
9
+swig_link_libraries (jsupm_${libname} -lupm-pca9685 ${MRAA_LIBRARIES} ${NODE_LIBRARIES})
10
+swig_link_libraries (pyupm_${libname} -lupm-pca9685 ${PYTHON_LIBRARIES} ${MRAA_LIBRARIES})

+ 305
- 0
src/adafruitms1438/adafruitms1438.cxx 查看文件

@@ -0,0 +1,305 @@
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
+
25
+#include <unistd.h>
26
+#include <math.h>
27
+#include <iostream>
28
+#include <string>
29
+
30
+#include "adafruitms1438.h"
31
+
32
+using namespace upm;
33
+using namespace std;
34
+
35
+
36
+AdafruitMS1438::AdafruitMS1438(int bus, uint8_t address) :
37
+  m_pca9685(new PCA9685(bus, address))
38
+{
39
+  setupPinMaps();
40
+
41
+  // set a default period of 50Hz
42
+  setPWMPeriod(50);
43
+
44
+  // disable all PWM's (4 of them).  They are shared with each other
45
+  // (stepper/DC), so just disable the DC motors here
46
+  disableMotor(MOTOR_M1);
47
+  disableMotor(MOTOR_M2);
48
+  disableMotor(MOTOR_M3);
49
+  disableMotor(MOTOR_M4);
50
+  
51
+  // Set all 'on time' registers to 0
52
+  m_pca9685->ledOnTime(PCA9685_ALL_LED, 0);
53
+
54
+  // set the default stepper config at 200 steps per rev
55
+  stepConfig(STEPMOTOR_M12, 200);
56
+  stepConfig(STEPMOTOR_M34, 200);
57
+}
58
+
59
+AdafruitMS1438::~AdafruitMS1438()
60
+{
61
+  delete m_pca9685;
62
+}
63
+
64
+void AdafruitMS1438::initClock(STEPMOTORS_T motor)
65
+{
66
+  gettimeofday(&m_stepConfig[motor].startTime, NULL);
67
+}
68
+
69
+uint32_t AdafruitMS1438::getMillis(STEPMOTORS_T motor)
70
+{
71
+  struct timeval elapsed, now;
72
+  uint32_t elapse;
73
+
74
+  // get current time
75
+  gettimeofday(&now, NULL);
76
+
77
+  struct timeval startTime = m_stepConfig[motor].startTime;
78
+
79
+  // compute the delta since m_startTime
80
+  if( (elapsed.tv_usec = now.tv_usec - startTime.tv_usec) < 0 )
81
+    {
82
+      elapsed.tv_usec += 1000000;
83
+      elapsed.tv_sec = now.tv_sec - startTime.tv_sec - 1;
84
+    }
85
+  else
86
+    {
87
+      elapsed.tv_sec = now.tv_sec - startTime.tv_sec;
88
+    }
89
+
90
+  elapse = (uint32_t)((elapsed.tv_sec * 1000) + (elapsed.tv_usec / 1000));
91
+
92
+  // never return 0
93
+  if (elapse == 0)
94
+    elapse = 1;
95
+
96
+  return elapse;
97
+}
98
+
99
+// setup the pin mappings of the pca9685 outputs to the proper motor controls
100
+void AdafruitMS1438::setupPinMaps()
101
+{
102
+  // first the dc motors
103
+  m_dcMotors[0] = (DC_PINMAP_T){ 8, 10, 9 };
104
+  m_dcMotors[1] = (DC_PINMAP_T){ 13, 11, 12 };
105
+  m_dcMotors[2] = (DC_PINMAP_T){ 2, 4, 3 };
106
+  m_dcMotors[3] = (DC_PINMAP_T){ 7, 5, 6 };
107
+
108
+  // now the 2 steppers
109
+  m_stepMotors[0] = (STEPPER_PINMAP_T){ 8, 10, 9,
110
+                                        13, 11, 12 };
111
+  m_stepMotors[1] = (STEPPER_PINMAP_T){ 2, 4, 3,
112
+                                        7, 5, 6 };
113
+}
114
+
115
+void AdafruitMS1438::setPWMPeriod(float hz)
116
+{
117
+  // must be in sleep mode to set the prescale register
118
+  m_pca9685->setModeSleep(true);
119
+  m_pca9685->setPrescaleFromHz(hz);
120
+  m_pca9685->setModeSleep(false);
121
+}
122
+
123
+void AdafruitMS1438::enableMotor(DCMOTORS_T motor)
124
+{
125
+  m_pca9685->ledFullOff(m_dcMotors[motor].pwm, false);
126
+}
127
+
128
+void AdafruitMS1438::disableMotor(DCMOTORS_T motor)
129
+{
130
+  m_pca9685->ledFullOff(m_dcMotors[motor].pwm, true);
131
+}
132
+
133
+void AdafruitMS1438::enableStepper(STEPMOTORS_T motor)
134
+{
135
+  m_pca9685->ledFullOff(m_stepMotors[motor].pwmA, false);
136
+  m_pca9685->ledFullOff(m_stepMotors[motor].pwmB, false);
137
+}
138
+
139
+void AdafruitMS1438::disableStepper(STEPMOTORS_T motor)
140
+{
141
+  m_pca9685->ledFullOff(m_stepMotors[motor].pwmA, true);
142
+  m_pca9685->ledFullOff(m_stepMotors[motor].pwmB, true);
143
+}
144
+
145
+void AdafruitMS1438::setMotorSpeed(DCMOTORS_T motor, int speed)
146
+{
147
+  if (speed < 0)
148
+    speed = 0;
149
+  
150
+  if (speed > 100)
151
+    speed = 100;
152
+
153
+  float percent = float(speed) / 100.0;
154
+  
155
+  m_pca9685->ledOffTime(m_dcMotors[motor].pwm, int(4095.0 * percent));
156
+}
157
+
158
+void AdafruitMS1438::setStepperSpeed(STEPMOTORS_T motor, int speed)
159
+{
160
+  m_stepConfig[motor].stepDelay = 60 * 1000 / 
161
+    m_stepConfig[motor].stepsPerRev / speed;
162
+}
163
+
164
+void AdafruitMS1438::setMotorDirection(DCMOTORS_T motor, DIRECTION_T dir)
165
+{
166
+  if (dir & 0x01)
167
+    {
168
+      m_pca9685->ledFullOn(m_dcMotors[motor].in1, true);
169
+      m_pca9685->ledFullOff(m_dcMotors[motor].in1, false);
170
+    }
171
+  else
172
+    {
173
+      m_pca9685->ledFullOff(m_dcMotors[motor].in1, true);
174
+      m_pca9685->ledFullOn(m_dcMotors[motor].in1, false);
175
+    }
176
+
177
+  if (dir & 0x02)
178
+    {
179
+      m_pca9685->ledFullOn(m_dcMotors[motor].in2, true);
180
+      m_pca9685->ledFullOff(m_dcMotors[motor].in2, false);
181
+    }
182
+  else
183
+    {
184
+      m_pca9685->ledFullOff(m_dcMotors[motor].in2, true);
185
+      m_pca9685->ledFullOn(m_dcMotors[motor].in2, false);
186
+    }
187
+}
188
+
189
+void AdafruitMS1438::setStepperDirection(STEPMOTORS_T motor, DIRECTION_T dir)
190
+{
191
+  switch (dir)
192
+    {
193
+    case DIR_CW:
194
+      m_stepConfig[motor].stepDirection = 1;
195
+      break;
196
+    case DIR_CCW:
197
+      m_stepConfig[motor].stepDirection = -1;
198
+      break;
199
+    default:                // default to 1 if DIR_NONE specified
200
+      m_stepConfig[motor].stepDirection = 1;
201
+      break;
202
+    }
203
+}
204
+
205
+void AdafruitMS1438::stepConfig(STEPMOTORS_T motor, unsigned int stepsPerRev)
206
+{
207
+  m_stepConfig[motor].stepsPerRev = stepsPerRev;
208
+  m_stepConfig[motor].currentStep = 0;
209
+  m_stepConfig[motor].stepDelay = 0;
210
+  m_stepConfig[motor].stepDirection = 1; // forward
211
+
212
+  // now, setup the control pins - we want both FULL ON and FULL OFF.
213
+  // Since FULL OFF has precedence, we can then control the steps by
214
+  // just turning on/off the FULL OFF bit for the relevant outputs
215
+
216
+  m_pca9685->ledFullOff(m_stepMotors[motor].pwmA, true);
217
+  m_pca9685->ledFullOn(m_stepMotors[motor].pwmA, true);
218
+
219
+  m_pca9685->ledFullOff(m_stepMotors[motor].pwmB, true);
220
+  m_pca9685->ledFullOn(m_stepMotors[motor].pwmB, true);
221
+
222
+  m_pca9685->ledFullOff(m_stepMotors[motor].in1A, true);
223
+  m_pca9685->ledFullOn(m_stepMotors[motor].in1A, true);
224
+
225
+  m_pca9685->ledFullOff(m_stepMotors[motor].in2A, true);
226
+  m_pca9685->ledFullOn(m_stepMotors[motor].in2A, true);
227
+
228
+  m_pca9685->ledFullOff(m_stepMotors[motor].in1B, true);
229
+  m_pca9685->ledFullOn(m_stepMotors[motor].in1B, true);
230
+
231
+  m_pca9685->ledFullOff(m_stepMotors[motor].in2B, true);
232
+  m_pca9685->ledFullOn(m_stepMotors[motor].in2B, true);
233
+}
234
+
235
+void AdafruitMS1438::stepperStep(STEPMOTORS_T motor)
236
+{
237
+  int step = m_stepConfig[motor].currentStep % 4;
238
+
239
+  //   Step I0 I1 I2 I3
240
+  //     1  1  0  1  0
241
+  //     2  0  1  1  0
242
+  //     3  0  1  0  1
243
+  //     4  1  0  0  1
244
+
245
+  // we invert the logic since we are essentially toggling an OFF bit,
246
+  // not an ON bit.
247
+  switch (step)
248
+    {
249
+    case 0:    // 1010
250
+      m_pca9685->ledFullOff(m_stepMotors[motor].in1A, false);
251
+      m_pca9685->ledFullOff(m_stepMotors[motor].in2A, true);
252
+      m_pca9685->ledFullOff(m_stepMotors[motor].in1B, false);
253
+      m_pca9685->ledFullOff(m_stepMotors[motor].in2B, true);
254
+      break;
255
+    case 1:    // 0110
256
+      m_pca9685->ledFullOff(m_stepMotors[motor].in1A, true);
257
+      m_pca9685->ledFullOff(m_stepMotors[motor].in2A, false);
258
+      m_pca9685->ledFullOff(m_stepMotors[motor].in1B, false);
259
+      m_pca9685->ledFullOff(m_stepMotors[motor].in2B, true);
260
+      break;
261
+    case 2:    //0101
262
+      m_pca9685->ledFullOff(m_stepMotors[motor].in1A, true);
263
+      m_pca9685->ledFullOff(m_stepMotors[motor].in2A, false);
264
+      m_pca9685->ledFullOff(m_stepMotors[motor].in1B, true);
265
+      m_pca9685->ledFullOff(m_stepMotors[motor].in2B, false);
266
+      break;
267
+    case 3:    //1001
268
+      m_pca9685->ledFullOff(m_stepMotors[motor].in1A, false);
269
+      m_pca9685->ledFullOff(m_stepMotors[motor].in2A, true);
270
+      m_pca9685->ledFullOff(m_stepMotors[motor].in1B, true);
271
+      m_pca9685->ledFullOff(m_stepMotors[motor].in2B, false);
272
+      break;
273
+    }
274
+}
275
+
276
+void AdafruitMS1438::stepperSteps(STEPMOTORS_T motor, unsigned int steps)
277
+{
278
+  while (steps > 0)
279
+    {
280
+      if (getMillis(motor) >= m_stepConfig[motor].stepDelay)
281
+        {
282
+          // reset the clock
283
+          initClock(motor);
284
+
285
+          m_stepConfig[motor].currentStep += m_stepConfig[motor].stepDirection;
286
+
287
+          if (m_stepConfig[motor].stepDirection == 1)
288
+            {
289
+              if (m_stepConfig[motor].currentStep >= 
290
+                  m_stepConfig[motor].stepsPerRev)
291
+                m_stepConfig[motor].currentStep = 0;
292
+            }
293
+          else
294
+            {
295
+              if (m_stepConfig[motor].currentStep <= 0)
296
+                m_stepConfig[motor].currentStep = 
297
+                  m_stepConfig[motor].stepsPerRev;
298
+            }
299
+
300
+          steps--;
301
+          stepperStep(motor);
302
+        }
303
+    }
304
+}
305
+

+ 244
- 0
src/adafruitms1438/adafruitms1438.h 查看文件

@@ -0,0 +1,244 @@
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 UPM module for the Adafruit Motor Shield 1438
42
+   * @defgroup adafruitms1438 libupm-adafruitms1438
43
+   */
44
+
45
+  /**
46
+   * @brief C++ API for the ADAFRUITMS1438 motor shield
47
+   *
48
+   * This class implements support for the stepper and DC motors that
49
+   * can be connected to this Motor Shield.
50
+   * http://www.adafruit.com/products/1438
51
+   *
52
+   * NOTE: The two servo connections are not actually controlled by
53
+   * the pca9685 controller (or this class), rather they are connected
54
+   * directly to digital PWM pins 9 and 10 on the arduino breakout.
55
+   *
56
+   * @ingroup i2c adafruitms1438
57
+   * An example using a DC motor conected to M3
58
+   * @snippet adafruitms1438.cxx Interesting
59
+   * An example using a stepper motor connected to M1 & M2
60
+   * @snippet adafruitms1438-stepper.cxx Interesting
61
+   */
62
+  class AdafruitMS1438 {
63
+  public:
64
+
65
+    /**
66
+     * Enum to specify the direction of a motor
67
+     */
68
+    typedef enum {
69
+      DIR_NONE = 0x00,
70
+      DIR_CW   = 0x01,
71
+      DIR_CCW  = 0x02
72
+    } DIRECTION_T;
73
+
74
+    /**
75
+     * Enum to specify a DC motor
76
+     */
77
+    typedef enum {
78
+      MOTOR_M1 = 0,
79
+      MOTOR_M2 = 1,
80
+      MOTOR_M3 = 2,
81
+      MOTOR_M4 = 3
82
+    } DCMOTORS_T;
83
+
84
+    /**
85
+     * Enum to specify a Stepper motor
86
+     */
87
+    typedef enum {
88
+      STEPMOTOR_M12 = 0,
89
+      STEPMOTOR_M34 = 1
90
+    } STEPMOTORS_T;
91
+
92
+    /**
93
+     * AdafruitMS1438 constructor
94
+     *
95
+     * @param bus i2c bus to use
96
+     * @param address the address for this sensor
97
+     */
98
+    AdafruitMS1438(int bus, uint8_t address = ADAFRUITMS1438_DEFAULT_I2C_ADDR);
99
+
100
+    /**
101
+     * AdafruitMS1438 Destructor
102
+     */
103
+    ~AdafruitMS1438();
104
+
105
+    /**
106
+     * Return the number of milliseconds elapsed since initClock(...)
107
+     * was last called.
108
+     *
109
+     * @return elapsed milliseconds
110
+     */
111
+    uint32_t getMillis(STEPMOTORS_T motor);
112
+
113
+    /**
114
+     * Reset the Clock
115
+     *
116
+     */
117
+    void initClock(STEPMOTORS_T motor);
118
+
119
+    /**
120
+     * Set the PWM period.  Note this applies to all PWM channels.
121
+     *
122
+     * @param hz set the PWM period 
123
+     */
124
+    void setPWMPeriod(float hz);
125
+
126
+    /**
127
+     * enable PWM output for a motor
128
+     *
129
+     * @param motor the DC motor to enable
130
+     */
131
+    void enableMotor(DCMOTORS_T motor);
132
+
133
+    /**
134
+     * disable PWM output for a motor
135
+     *
136
+     * @param motor the DC motor to disable
137
+     */
138
+    void disableMotor(DCMOTORS_T motor);
139
+
140
+    /**
141
+     * enable output for a stepper motor
142
+     *
143
+     * @param motor the stepper motor to enable
144
+     */
145
+    void enableStepper(STEPMOTORS_T motor);
146
+
147
+    /**
148
+     * disable output for a stepper motor
149
+     *
150
+     * @param motor the stepper motor to disable
151
+     */
152
+    void disableStepper(STEPMOTORS_T motor);
153
+
154
+    /**
155
+     * set the speed of a DC motor.  Values can range from 0 (off) to
156
+     * 100 (full speed).
157
+     *
158
+     * @param motor the DC motor to configure
159
+     * @param speed speed to set the motor to
160
+     */
161
+    void setMotorSpeed(DCMOTORS_T motor, int speed);
162
+
163
+    /**
164
+     * set the speed of a stepper in revolution per minute (RPM)
165
+     *
166
+     * @param motor the DC motor to configure
167
+     * @param speed speed to set the motor to
168
+     */
169
+    void setStepperSpeed(STEPMOTORS_T motor, int speed);
170
+
171
+    /**
172
+     * set the direction of a DC motor, clockwise or counter clockwise
173
+     *
174
+     * @param motor the DC motor to configure
175
+     * @param dir direction to set the motor to
176
+     */
177
+    void setMotorDirection(DCMOTORS_T motor, DIRECTION_T dir);
178
+ 
179
+    /**
180
+     * set the direction of a stepper motor, clockwise or counter clockwise
181
+     *
182
+     * @param motor the stepper motor to configure
183
+     * @param dir direction to set the motor to
184
+     */
185
+    void setStepperDirection(STEPMOTORS_T motor, DIRECTION_T dir);
186
+ 
187
+    /**
188
+     * set a stepper motor configuration
189
+     *
190
+     * @param motor the stepper motor to configure
191
+     * @param stepsPerRev the number of step to complete a full revolution
192
+     */
193
+    void stepConfig(STEPMOTORS_T motor, unsigned int stepsPerRev);
194
+
195
+    /**
196
+     * step a stepper motor a specified number of steps
197
+     *
198
+     * @param motor the stepper motor to step
199
+     * @param steps number of steps to move the stepper motor
200
+     */
201
+    void stepperSteps(STEPMOTORS_T motor, unsigned int steps);
202
+
203
+  private:
204
+    // SWIG will generate warning for these 'nested structs', however
205
+    // those can be ignored as these structs are never exposed.
206
+
207
+    // struct to hold mappings of the dc motors
208
+    typedef struct {
209
+      int pwm;
210
+      int in1;
211
+      int in2;
212
+    } DC_PINMAP_T;
213
+
214
+    // struct to hold mappings of the stepper motors
215
+    typedef struct {
216
+      int pwmA;
217
+      int in1A;
218
+      int in2A;
219
+      int pwmB;
220
+      int in1B;
221
+      int in2B;
222
+    } STEPPER_PINMAP_T;
223
+
224
+    // struct to hold some information about each stepper
225
+    typedef struct {
226
+      int stepsPerRev;          // steps per revolution
227
+      int currentStep;          // current step number
228
+      uint32_t stepDelay;       // delay between steps
229
+      int stepDirection;        // direction to step
230
+      struct timeval startTime; // starting time
231
+    } STEPPER_CONFIG_T;
232
+
233
+    void setupPinMaps();
234
+    void stepperStep(STEPMOTORS_T motor);
235
+
236
+    DC_PINMAP_T m_dcMotors[4];
237
+    STEPPER_PINMAP_T m_stepMotors[2];
238
+    STEPPER_CONFIG_T m_stepConfig[2];
239
+
240
+    PCA9685 *m_pca9685;
241
+  };
242
+}
243
+
244
+

+ 8
- 0
src/adafruitms1438/jsupm_adafruitms1438.i 查看文件

@@ -0,0 +1,8 @@
1
+%module jsupm_adafruitms1438
2
+%include "../upm.i"
3
+
4
+%{
5
+    #include "adafruitms1438.h"
6
+%}
7
+
8
+%include "adafruitms1438.h"

+ 13
- 0
src/adafruitms1438/pyupm_adafruitms1438.i 查看文件

@@ -0,0 +1,13 @@
1
+%module pyupm_adafruitms1438
2
+%include "../upm.i"
3
+
4
+%feature("autodoc", "3");
5
+
6
+#ifdef DOXYGEN
7
+%include "adafruitms1438_doc.i"
8
+#endif
9
+
10
+%include "adafruitms1438.h"
11
+%{
12
+    #include "adafruitms1438.h"
13
+%}