diff --git a/examples/c++/CMakeLists.txt b/examples/c++/CMakeLists.txt index 5d9b8144..67b07cf1 100644 --- a/examples/c++/CMakeLists.txt +++ b/examples/c++/CMakeLists.txt @@ -94,6 +94,8 @@ add_executable (groveemg-example groveemg.cxx) add_executable (groveo2-example groveo2.cxx) add_executable (grovegsr-example grovegsr.cxx) add_executable (ina132-example ina132.cxx) +add_executable (l298-example l298.cxx) +add_executable (l298-stepper-example l298-stepper.cxx) include_directories (${PROJECT_SOURCE_DIR}/src/hmc5883l) include_directories (${PROJECT_SOURCE_DIR}/src/grove) @@ -170,6 +172,7 @@ include_directories (${PROJECT_SOURCE_DIR}/src/groveemg) include_directories (${PROJECT_SOURCE_DIR}/src/groveo2) include_directories (${PROJECT_SOURCE_DIR}/src/grovegsr) include_directories (${PROJECT_SOURCE_DIR}/src/ina132) +include_directories (${PROJECT_SOURCE_DIR}/src/l298) target_link_libraries (hmc5883l-example hmc5883l ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries (groveled-example grove ${CMAKE_THREAD_LIBS_INIT}) @@ -265,3 +268,5 @@ target_link_libraries (groveemg-example groveemg ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries (groveo2-example groveo2 ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries (grovegsr-example grovegsr ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries (ina132-example ina132 ${CMAKE_THREAD_LIBS_INIT}) +target_link_libraries (l298-example l298 ${CMAKE_THREAD_LIBS_INIT}) +target_link_libraries (l298-stepper-example l298 ${CMAKE_THREAD_LIBS_INIT}) diff --git a/examples/c++/l298-stepper.cxx b/examples/c++/l298-stepper.cxx new file mode 100644 index 00000000..8fe2b91d --- /dev/null +++ b/examples/c++/l298-stepper.cxx @@ -0,0 +1,61 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2015 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include "l298.h" + +using namespace std; + +int main () +{ + //! [Interesting] + + // Instantiate a Stepper motor on a L298 Dual H-Bridge. + + // This was tested with the NEMA-17 12V, 350mA, with 200 steps per rev. + upm::L298* l298 = new upm::L298(200, 3, 4, 7, 8, 9); + + l298->setSpeed(10); // 10 RPMs + l298->setDirection(upm::L298::DIR_CW); + l298->enable(true); + cout << "Rotating 1 full revolution at 10 RPM speed." << endl; + // move 200 steps, a full rev + l298->stepperSteps(200); + cout << "Sleeping for 2 seconds..." << endl; + sleep(2); + cout << "Rotating 1/2 revolution in opposite direction at 10 RPM speed." + << endl; + l298->setDirection(upm::L298::DIR_CCW); + l298->stepperSteps(100); + // release + l298->enable(false); + + //! [Interesting] + + cout << "Exiting..." << endl; + + delete l298; + return 0; +} diff --git a/examples/c++/l298.cxx b/examples/c++/l298.cxx new file mode 100644 index 00000000..8e360b23 --- /dev/null +++ b/examples/c++/l298.cxx @@ -0,0 +1,61 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2015 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include "l298.h" + +using namespace std; + +int main () +{ + //! [Interesting] + + // Instantiate one of the 2 possible DC motors on a L298 Dual + // H-Bridge. For controlling a stepper motor, see the l298-stepper + // example. + upm::L298* l298 = new upm::L298(3, 4, 7); + + cout << "Starting motor at 50% for 3 seconds..." << endl; + l298->setSpeed(50); + l298->setDirection(upm::L298::DIR_CW); + l298->enable(true); + + sleep(3); + + cout << "Reversing direction..." << endl; + l298->setDirection(upm::L298::DIR_NONE); // fast stop + l298->setDirection(upm::L298::DIR_CCW); + sleep(3); + + l298->setSpeed(0); + l298->enable(false); + + //! [Interesting] + + cout << "Exiting..." << endl; + + delete l298; + return 0; +} diff --git a/examples/javascript/l298-stepper.js b/examples/javascript/l298-stepper.js new file mode 100644 index 00000000..ef2bbce3 --- /dev/null +++ b/examples/javascript/l298-stepper.js @@ -0,0 +1,77 @@ +/*jslint node:true, vars:true, bitwise:true, unparam:true */ +/*jshint unused:true */ +/* +* Author: Zion Orent +* Copyright (c) 2015 Intel Corporation. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to deal in the Software without restriction, including +* without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to +* permit persons to whom the Software is furnished to do so, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be +* included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +var HBridge_lib = require('jsupm_l298'); + +// Instantiate a Stepper motor on a L298 Dual H-Bridge. +// This was tested with the NEMA-17 12V, 350mA, with 200 steps per rev. +var myHBridge_obj = new HBridge_lib.L298(200, 3, 4, 7, 8, 9); + +/************************************** + * Instantiate H-bridge stepper object +***************************************/ +myHBridge_obj.goForward = function() +{ + myHBridge_obj.setSpeed(10); // 10 RPMs + myHBridge_obj.setDirection(HBridge_lib.L298.DIR_CW); + myHBridge_obj.enable(true); + console.log("Rotating 1 full revolution at 10 RPM speed."); + // move 200 steps, a full rev + myHBridge_obj.stepperSteps(200); +}; + +myHBridge_obj.reverseDirection = function() +{ + console.log("Rotating 1/2 revolution in opposite direction at 10 RPM speed."); + myHBridge_obj.setDirection(HBridge_lib.L298.DIR_CCW); + myHBridge_obj.stepperSteps(100); +}; + +myHBridge_obj.stop = function() +{ + myHBridge_obj.enable(false); +}; + +myHBridge_obj.quit = function() +{ + myHBridge_obj = null; + HBridge_lib.cleanUp(); + HBridge_lib = null; + console.log("Exiting"); + process.exit(0); +}; + + +/************************ + * Run H-bridge stepper! +*************************/ +myHBridge_obj.goForward(); +setTimeout(myHBridge_obj.reverseDirection, 2000); +setTimeout(function() +{ + myHBridge_obj.stop(); + myHBridge_obj.quit(); +}, 4000); diff --git a/examples/javascript/l298.js b/examples/javascript/l298.js new file mode 100644 index 00000000..8d972cb0 --- /dev/null +++ b/examples/javascript/l298.js @@ -0,0 +1,77 @@ +/*jslint node:true, vars:true, bitwise:true, unparam:true */ +/*jshint unused:true */ +/* +* Author: Zion Orent +* Copyright (c) 2015 Intel Corporation. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to deal in the Software without restriction, including +* without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to +* permit persons to whom the Software is furnished to do so, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be +* included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +var HBridge_lib = require('jsupm_l298'); + +// Instantiate one of the 2 possible DC motors on a L298 Dual +// H-Bridge. For controlling a stepper motor, see the l298-stepper +// example. +var myHBridge_obj = new HBridge_lib.L298(3, 4, 7); + +/***************************** + * Instantiate H-bridge object +******************************/ +myHBridge_obj.goForward = function() +{ + console.log("Starting motor at 50% for 3 seconds..."); + myHBridge_obj.setSpeed(50); + myHBridge_obj.setDirection(HBridge_lib.L298.DIR_CW); + myHBridge_obj.enable(true); +}; + +myHBridge_obj.reverseDirection = function() +{ + console.log("Reversing direction..."); + myHBridge_obj.setDirection(HBridge_lib.L298.DIR_NONE); // fast stop + myHBridge_obj.setDirection(HBridge_lib.L298.DIR_CCW); +}; + +myHBridge_obj.stop = function() +{ + myHBridge_obj.setSpeed(0); + myHBridge_obj.enable(false); +}; + +myHBridge_obj.quit = function() +{ + myHBridge_obj = null; + HBridge_lib.cleanUp(); + HBridge_lib = null; + console.log("Exiting"); + process.exit(0); +}; + + +/************************ + * Run H-bridge! +*************************/ +myHBridge_obj.goForward(); +setTimeout(myHBridge_obj.reverseDirection, 3000); +setTimeout(function() +{ + myHBridge_obj.stop(); + myHBridge_obj.quit(); +}, 6000); diff --git a/src/l298/CMakeLists.txt b/src/l298/CMakeLists.txt new file mode 100644 index 00000000..e42e3b57 --- /dev/null +++ b/src/l298/CMakeLists.txt @@ -0,0 +1,5 @@ +set (libname "l298") +set (libdescription "upm l298 dual h-bridge") +set (module_src ${libname}.cxx) +set (module_h ${libname}.h) +upm_module_init() diff --git a/src/l298/jsupm_l298.i b/src/l298/jsupm_l298.i new file mode 100644 index 00000000..7fec3a03 --- /dev/null +++ b/src/l298/jsupm_l298.i @@ -0,0 +1,8 @@ +%module jsupm_l298 +%include "../upm.i" + +%{ + #include "l298.h" +%} + +%include "l298.h" diff --git a/src/l298/l298.cxx b/src/l298/l298.cxx new file mode 100644 index 00000000..7e477b52 --- /dev/null +++ b/src/l298/l298.cxx @@ -0,0 +1,335 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2015 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include + +#include "l298.h" + +using namespace upm; +using namespace std; + +// constructor for the DC motor(s) mode +L298::L298(int pwmA, int dir1, int dir2) +{ + // No stepper in this mode + m_stepper = false; + + // disable until complete + m_motor = false; + + if ( !(m_pwm = mraa_pwm_init(pwmA)) ) + { + cerr << __FUNCTION__ << ": mraa_pwm_init(pwm) failed" << endl; + return; + } + + if ( !(m_dir1 = mraa_gpio_init(dir1)) ) + { + cerr << __FUNCTION__ << ": mraa_gpio_init(dir1) failed" << endl; + mraa_pwm_close(m_pwm); + return; + } + mraa_gpio_dir(m_dir1, MRAA_GPIO_OUT); + + if ( !(m_dir2 = mraa_gpio_init(dir2)) ) + { + cerr << __FUNCTION__ << ": mraa_gpio_init(dir2) failed" << endl; + mraa_pwm_close(m_pwm); + mraa_gpio_close(m_dir1); + return; + } + mraa_gpio_dir(m_dir2, MRAA_GPIO_OUT); + + setPeriodMS(L298_DEFAULT_PWM_PERIOD); + setDirection(DIR_NONE); + setSpeed(0); + m_motor = true; +} + +// constructor for the stepper mode +L298::L298(int stepsPerRev, int en, int i1, int i2, int i3, int i4) +{ + // no DC motors in this mode + m_motor = false; + + // disable until complete + m_stepper = false; + + m_stepsPerRev = stepsPerRev; + m_currentStep = 0; + m_stepDelay = 0; + m_stepDirection = 1; // default is forward + + // init the gpio's we will need + if ( !(m_stepEnable = mraa_gpio_init(en)) ) + { + cerr << __FUNCTION__ << ": mraa_gpio_init(en) failed" << endl; + return; + } + mraa_gpio_dir(m_stepEnable, MRAA_GPIO_OUT); + + if ( !(m_stepI1 = mraa_gpio_init(i1)) ) + { + cerr << __FUNCTION__ << ": mraa_gpio_init(i1) failed" << endl; + return; + } + mraa_gpio_dir(m_stepI1, MRAA_GPIO_OUT); + + if ( !(m_stepI2 = mraa_gpio_init(i2)) ) + { + cerr << __FUNCTION__ << ": mraa_gpio_init(i2) failed" << endl; + mraa_gpio_close(m_stepI1); + return; + } + mraa_gpio_dir(m_stepI2, MRAA_GPIO_OUT); + + if ( !(m_stepI3 = mraa_gpio_init(i3)) ) + { + cerr << __FUNCTION__ << ": mraa_gpio_init(i3) failed" << endl; + mraa_gpio_close(m_stepI1); + mraa_gpio_close(m_stepI2); + return; + } + mraa_gpio_dir(m_stepI3, MRAA_GPIO_OUT); + + if ( !(m_stepI4 = mraa_gpio_init(i4)) ) + { + cerr << __FUNCTION__ << ": mraa_gpio_init(i4) failed" << endl; + mraa_gpio_close(m_stepI1); + mraa_gpio_close(m_stepI2); + mraa_gpio_close(m_stepI3); + + return; + } + mraa_gpio_dir(m_stepI4, MRAA_GPIO_OUT); + + m_stepper = true; +} + + +void L298::initClock() +{ + gettimeofday(&m_startTime, NULL); +} + +uint32_t L298::getMillis() +{ + struct timeval elapsed, now; + uint32_t elapse; + + // get current time + gettimeofday(&now, NULL); + + // compute the delta since m_startTime + if( (elapsed.tv_usec = now.tv_usec - m_startTime.tv_usec) < 0 ) + { + elapsed.tv_usec += 1000000; + elapsed.tv_sec = now.tv_sec - m_startTime.tv_sec - 1; + } + else + { + elapsed.tv_sec = now.tv_sec - m_startTime.tv_sec; + } + + elapse = (uint32_t)((elapsed.tv_sec * 1000) + (elapsed.tv_usec / 1000)); + + // never return 0 + if (elapse == 0) + elapse = 1; + + return elapse; +} + + +L298::~L298() +{ + if (m_stepper) + { + enable(false); + mraa_gpio_close(m_stepEnable); + mraa_gpio_close(m_stepI1); + mraa_gpio_close(m_stepI2); + mraa_gpio_close(m_stepI3); + mraa_gpio_close(m_stepI4); + } + + if (m_motor) + { + setDirection(DIR_NONE); + setSpeed(0); + enable(false); + mraa_pwm_close(m_pwm); + mraa_gpio_close(m_dir1); + mraa_gpio_close(m_dir2); + } +} + +void L298::setPeriodMS(int ms) +{ + if (m_motor) + { + if (mraa_pwm_period_ms(m_pwm, ms) != MRAA_SUCCESS) + cerr << __FUNCTION__ << ": period specified is not supported" + << endl; + } +} + +void L298::enable(bool enable) +{ + if (m_motor) + { + mraa_pwm_enable(m_pwm, ((enable) ? 1 : 0)); + } + + if (m_stepper) + { + mraa_gpio_write(m_stepEnable, ((enable) ? 1 : 0)); + } +} + +void L298::setSpeed(int speed) +{ + if (m_motor) + { + if (speed < 0) + speed = 0; + + if (speed > 100) + speed = 100; + + float percent = float(speed) / 100.0; + + if (m_motor) + { + mraa_pwm_write(m_pwm, percent); + } + } + + if (m_stepper) + { + m_stepDelay = 60 * 1000 / m_stepsPerRev / speed; + } +} + +void L298::setDirection(L298_DIRECTION_T dir) +{ + if (m_motor) + { + if (dir & 0x01) + mraa_gpio_write(m_dir1, 1); + else + mraa_gpio_write(m_dir1, 0); + + if (dir & 0x02) + mraa_gpio_write(m_dir2, 1); + else + mraa_gpio_write(m_dir2, 0); + } + + if (m_stepper) + { + switch (dir) + { + case DIR_CW: + m_stepDirection = 1; + break; + case DIR_CCW: + m_stepDirection = -1; + break; + default: // default to 1 if DIR_NONE specified + m_stepDirection = 1; + break; + } + } + + +} + +void L298::stepperStep() +{ + int step = m_currentStep % 4; + + // Step I0 I1 I2 I3 + // 1 1 0 1 0 + // 2 0 1 1 0 + // 3 0 1 0 1 + // 4 1 0 0 1 + + switch (step) + { + case 0: // 1010 + mraa_gpio_write(m_stepI1, 1); + mraa_gpio_write(m_stepI2, 0); + mraa_gpio_write(m_stepI3, 1); + mraa_gpio_write(m_stepI4, 0); + break; + case 1: // 0110 + mraa_gpio_write(m_stepI1, 0); + mraa_gpio_write(m_stepI2, 1); + mraa_gpio_write(m_stepI3, 1); + mraa_gpio_write(m_stepI4, 0); + break; + case 2: //0101 + mraa_gpio_write(m_stepI1, 0); + mraa_gpio_write(m_stepI2, 1); + mraa_gpio_write(m_stepI3, 0); + mraa_gpio_write(m_stepI4, 1); + break; + case 3: //1001 + mraa_gpio_write(m_stepI1, 1); + mraa_gpio_write(m_stepI2, 0); + mraa_gpio_write(m_stepI3, 0); + mraa_gpio_write(m_stepI4, 1); + break; + } +} + +void L298::stepperSteps(unsigned int steps) +{ + while (steps > 0) + { + if (getMillis() >= m_stepDelay) + { + // reset the clock + initClock(); + + m_currentStep += m_stepDirection; + + if (m_stepDirection == 1) + { + if (m_currentStep >= m_stepsPerRev) + m_currentStep = 0; + } + else + { + if (m_currentStep <= 0) + m_currentStep = m_stepsPerRev; + } + + steps--; + stepperStep(); + // cerr << "STEPNUM: " << m_currentStep << endl; + } + } +} diff --git a/src/l298/l298.h b/src/l298/l298.h new file mode 100644 index 00000000..899edecc --- /dev/null +++ b/src/l298/l298.h @@ -0,0 +1,184 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2015 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#pragma once + +#include +#include + +#include +#include + +// in milliseconds +#define L298_DEFAULT_PWM_PERIOD 4 + +namespace upm { + + /** + * @brief C++ API for the L298 Dual H-Bridge module + * @defgroup l298 libupm-l298 + */ + + /** + * @brief UPM module for the L298 Dual H-Bridge + * + * It was developed using the RobotBase Dual H-Bridge module. + * + * This module can support 2 DC motors, or 1 2-phase stepper motor. + * It requires 3 pins per DC motor (or h-bridge), or 4 pins for + * the stepper (uses both h-bridges). + * + * @ingroup l298 pwm gpio + * Example driving a DC motor + * @snippet l298.cxx Interesting + * Example driving a stepper motor + * @snippet l298-stepper.cxx Interesting + */ + + + class L298 { + public: + + /** + * Enum to specify the direction of a motor + */ + typedef enum { + DIR_NONE = 0x00, + DIR_CW = 0x01, + DIR_CCW = 0x02 + } L298_DIRECTION_T; + + /** + * L298 constructor for DC motor(s) connected. + * + * @param pwm digital pin to use for DC motor - must be PWM capable + * @param dir1 digital pin to use for motor direction pin 1 + * @param dir2 digital pin to use for motor direction pin 2 + */ + L298(int pwm, int dir1, int dir2); + + /** + * L298 constructor for 4-wire stepper motor + * + * @param stepsPerRev number of steps per full revolution + * @param en enable pin + * @param i1 digital pin to use for stepper input 1 + * @param i2 digital pin to use for stepper input 2 + * @param i3 digital pin to use for stepper input 3 + * @param i4 digital pin to use for stepper input 4 + */ + L298(int stepsPerRev, int en, int i1, int i2, int i3, int i4); + + /** + * L298 Destructor + */ + ~L298(); + + /** + * Return the number of milliseconds elapsed since initClock() + * was last called. + * + * @return elapsed milliseconds + */ + uint32_t getMillis(); + + /** + * Reset the Clock + * + */ + void initClock(); + + /** + * set the period in milliseconds + * + * @param ms period in milliseconds + */ + void setPeriodMS(int ms); + + /** + * enable PWM output for a motor + * + * @param enable enable PWM output if true, disable if false + */ + void enable(bool enable); + + /** + * set the speed of a DC or stepp motor. For a DC motor, Values + * can range from 0 (off) to 100 (full speed). For a stepper + * motor, specify the desired RPM. + * + * @param speed speed to set the motor to + */ + void setSpeed(int speed); + + /** + * set the direction of the motor, clockwise or counter clockwise + * + * @param dir direction to set the motor to + */ + void setDirection(L298_DIRECTION_T dir); + + /** + * step the stepper motor a specified number of steps + * + * @param steps number of steps to move the stepper motor + */ + void stepperSteps(unsigned int steps); + + private: + // DC motor mode enabled + bool m_motor; + // stepper mode enabled + bool m_stepper; + + struct timeval m_startTime; + + // DC motor + mraa_pwm_context m_pwm; + mraa_gpio_context m_dir1; + mraa_gpio_context m_dir2; + + // stepper (4-wire) + mraa_gpio_context m_stepEnable; + mraa_gpio_context m_stepI1; + mraa_gpio_context m_stepI2; + mraa_gpio_context m_stepI3; + mraa_gpio_context m_stepI4; + + // steps per revolution + int m_stepsPerRev; + int m_currentStep; + uint32_t m_stepDelay; + + /** + * step the motor one tick + * + */ + void stepperStep(); + + // step direction - 1 = forward, -1 = backward + int m_stepDirection; + }; +} + + diff --git a/src/l298/pyupm_l298.i b/src/l298/pyupm_l298.i new file mode 100644 index 00000000..b35a1b36 --- /dev/null +++ b/src/l298/pyupm_l298.i @@ -0,0 +1,9 @@ +%module pyupm_l298 +%include "../upm.i" + +%feature("autodoc", "3"); + +%include "l298.h" +%{ + #include "l298.h" +%}