From 58dfa9d95af37e4f577dce749b2b515b004d7ff5 Mon Sep 17 00:00:00 2001 From: Jon Trulson Date: Mon, 24 Oct 2016 16:04:51 -0600 Subject: [PATCH] uln200xa: C implementation and examples Signed-off-by: Jon Trulson --- examples/c++/uln200xa.cxx | 6 +- examples/c/CMakeLists.txt | 1 + examples/c/uln200xa.c | 69 ++++++++ examples/java/ULN200XASample.java | 7 +- examples/javascript/uln200xa.js | 6 +- examples/python/uln200xa.py | 6 +- src/uln200xa/CMakeLists.txt | 13 +- src/uln200xa/javaupm_uln200xa.i | 5 +- src/uln200xa/jsupm_uln200xa.i | 3 +- src/uln200xa/pyupm_uln200xa.i | 1 + src/uln200xa/uln200xa.c | 260 ++++++++++++++++++++++++++++++ src/uln200xa/uln200xa.cxx | 208 ++---------------------- src/uln200xa/uln200xa.h | 122 ++++++++++++++ src/uln200xa/uln200xa.hpp | 62 +------ 14 files changed, 499 insertions(+), 270 deletions(-) create mode 100644 examples/c/uln200xa.c create mode 100644 src/uln200xa/uln200xa.c create mode 100644 src/uln200xa/uln200xa.h diff --git a/examples/c++/uln200xa.cxx b/examples/c++/uln200xa.cxx index 6a953288..486d20d3 100644 --- a/examples/c++/uln200xa.cxx +++ b/examples/c++/uln200xa.cxx @@ -32,7 +32,7 @@ int main () { //! [Interesting] - // Instantiate a Stepper motor on a ULN200XA Dual H-Bridge. + // Instantiate a Stepper motor on a ULN200XA Darlington controller. // This was tested with the Grove Gear Stepper Motor with Driver @@ -41,13 +41,13 @@ int main () upm::ULN200XA* uln200xa = new upm::ULN200XA(4096, 8, 9, 10, 11); uln200xa->setSpeed(5); - uln200xa->setDirection(upm::ULN200XA::DIR_CW); + uln200xa->setDirection(ULN200XA_DIR_CW); cout << "Rotating 1 revolution clockwise." << endl; uln200xa->stepperSteps(4096); cout << "Sleeping for 2 seconds..." << endl; sleep(2); cout << "Rotating 1/2 revolution counter clockwise." << endl; - uln200xa->setDirection(upm::ULN200XA::DIR_CCW); + uln200xa->setDirection(ULN200XA_DIR_CCW); uln200xa->stepperSteps(2048); // turn off the power diff --git a/examples/c/CMakeLists.txt b/examples/c/CMakeLists.txt index 5c8573ee..1de0ca03 100644 --- a/examples/c/CMakeLists.txt +++ b/examples/c/CMakeLists.txt @@ -129,6 +129,7 @@ add_example (rotaryencoder) add_example (rpr220) add_example (md) add_example (linefinder) +add_example (uln200xa) # Custom examples add_custom_example (nmea_gps_i2c-example-c nmea_gps_i2c.c nmea_gps) diff --git a/examples/c/uln200xa.c b/examples/c/uln200xa.c new file mode 100644 index 00000000..3271d15f --- /dev/null +++ b/examples/c/uln200xa.c @@ -0,0 +1,69 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2016 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 +#include "uln200xa.h" + +int main () +{ +//! [Interesting] + + // Instantiate a Stepper motor on a ULN200XA Darlington controller. + + // This was tested with the Grove Gear Stepper Motor with Driver + + // Wire the pins so that I1 is pin D8, I2 is pin D9, I3 is pin D10 and + // I4 is pin D11 + uln200xa_context motor = uln200xa_init(4096, 8, 9, 10, 11); + + if (!motor) + { + printf("uln200xa_init() failed\n"); + return 1; + } + + uln200xa_set_speed(motor, 5); + uln200xa_set_direction(motor, ULN200XA_DIR_CW); + printf("Rotating 1 revolution clockwise.\n"); + uln200xa_stepper_steps(motor, 4096); + + printf("Sleeping for 2 seconds...\n"); + upm_delay(2); + + printf("Rotating 1/2 revolution counter clockwise.\n"); + uln200xa_set_direction(motor, ULN200XA_DIR_CCW); + uln200xa_stepper_steps(motor, 2048); + + // turn off the power + uln200xa_release(motor); + + printf("Exiting...\n"); + + uln200xa_close(motor); +//! [Interesting] + return 0; +} diff --git a/examples/java/ULN200XASample.java b/examples/java/ULN200XASample.java index 81f97ad6..c7b5ac44 100644 --- a/examples/java/ULN200XASample.java +++ b/examples/java/ULN200XASample.java @@ -22,7 +22,6 @@ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -//NOT TESTED!!! public class ULN200XASample { public static void main(String[] args) throws InterruptedException { @@ -34,14 +33,14 @@ public class ULN200XASample { uln200xa.setSpeed(5); System.out.println("Rotating 1 revolution clockwise."); - uln200xa.setDirection(upm_uln200xa.ULN200XA.ULN200XA_DIRECTION_T.DIR_CW); + uln200xa.setDirection(upm_uln200xa.ULN200XA_DIRECTION_T.ULN200XA_DIR_CW); uln200xa.stepperSteps(4096); System.out.println("Sleeping for 2 seconds..."); Thread.sleep(2000); System.out.println("Rotating 1/2 revolution counter clockwise."); - uln200xa.setDirection(upm_uln200xa.ULN200XA.ULN200XA_DIRECTION_T.DIR_CCW); + uln200xa.setDirection(upm_uln200xa.ULN200XA_DIRECTION_T.ULN200XA_DIR_CCW); uln200xa.stepperSteps(2048); // turn off the power @@ -51,4 +50,4 @@ public class ULN200XASample { System.out.println("Exiting..."); } -} \ No newline at end of file +} diff --git a/examples/javascript/uln200xa.js b/examples/javascript/uln200xa.js index 85dd0b81..edad56a8 100644 --- a/examples/javascript/uln200xa.js +++ b/examples/javascript/uln200xa.js @@ -1,6 +1,6 @@ /* * Author: Jon Trulson -* Copyright (c) 2015 Intel Corporation. +* Copyright (c) 2015-2016 Intel Corporation. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -33,7 +33,7 @@ var myUln200xa_obj = new Uln200xa_lib.ULN200XA(4096, 8, 9, 10, 11); myUln200xa_obj.goForward = function() { myUln200xa_obj.setSpeed(5); // 5 RPMs - myUln200xa_obj.setDirection(Uln200xa_lib.ULN200XA.DIR_CW); + myUln200xa_obj.setDirection(Uln200xa_lib.ULN200XA_DIR_CW); console.log("Rotating 1 revolution clockwise."); myUln200xa_obj.stepperSteps(4096); }; @@ -41,7 +41,7 @@ myUln200xa_obj.goForward = function() myUln200xa_obj.reverseDirection = function() { console.log("Rotating 1/2 revolution counter clockwise."); - myUln200xa_obj.setDirection(Uln200xa_lib.ULN200XA.DIR_CCW); + myUln200xa_obj.setDirection(Uln200xa_lib.ULN200XA_DIR_CCW); myUln200xa_obj.stepperSteps(2048); }; diff --git a/examples/python/uln200xa.py b/examples/python/uln200xa.py index 20d0ce6b..48a44482 100755 --- a/examples/python/uln200xa.py +++ b/examples/python/uln200xa.py @@ -1,6 +1,6 @@ #!/usr/bin/python # Author: Jon Trulson -# Copyright (c) 2015 Intel Corporation. +# Copyright (c) 2015-2016 Intel Corporation. # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -48,7 +48,7 @@ def main(): signal.signal(signal.SIGINT, SIGINTHandler) myUln200xa.setSpeed(5) # 5 RPMs - myUln200xa.setDirection(upmULN200XA.ULN200XA.DIR_CW) + myUln200xa.setDirection(upmULN200XA.ULN200XA_DIR_CW) print("Rotating 1 revolution clockwise.") myUln200xa.stepperSteps(4096) @@ -57,7 +57,7 @@ def main(): time.sleep(2) print("Rotating 1/2 revolution counter clockwise.") - myUln200xa.setDirection(upmULN200XA.ULN200XA.DIR_CCW) + myUln200xa.setDirection(upmULN200XA.ULN200XA_DIR_CCW) myUln200xa.stepperSteps(2048) # release diff --git a/src/uln200xa/CMakeLists.txt b/src/uln200xa/CMakeLists.txt index e7189370..046adb71 100644 --- a/src/uln200xa/CMakeLists.txt +++ b/src/uln200xa/CMakeLists.txt @@ -1,5 +1,8 @@ -set (libname "uln200xa") -set (libdescription "Uln200xa darlington stepper driver") -set (module_src ${libname}.cxx) -set (module_hpp ${libname}.hpp) -upm_module_init() +upm_mixed_module_init (NAME uln200xa + DESCRIPTION "Uln200xa darlington stepper driver" + C_HDR uln200xa.h + C_SRC uln200xa.c + CPP_HDR uln200xa.hpp + CPP_SRC uln200xa.cxx + CPP_WRAPS_C + REQUIRES mraa) diff --git a/src/uln200xa/javaupm_uln200xa.i b/src/uln200xa/javaupm_uln200xa.i index 3b11bf2a..8e4004c3 100644 --- a/src/uln200xa/javaupm_uln200xa.i +++ b/src/uln200xa/javaupm_uln200xa.i @@ -1,11 +1,12 @@ %module javaupm_uln200xa %include "../upm.i" +%include "uln200xa.h" +%include "uln200xa.hpp" %{ #include "uln200xa.hpp" %} -%include "uln200xa.hpp" %pragma(java) jniclasscode=%{ static { @@ -16,4 +17,4 @@ System.exit(1); } } -%} \ No newline at end of file +%} diff --git a/src/uln200xa/jsupm_uln200xa.i b/src/uln200xa/jsupm_uln200xa.i index a7ee87d4..31945ee7 100644 --- a/src/uln200xa/jsupm_uln200xa.i +++ b/src/uln200xa/jsupm_uln200xa.i @@ -1,8 +1,9 @@ %module jsupm_uln200xa %include "../upm.i" +%include "uln200xa.h" +%include "uln200xa.hpp" %{ #include "uln200xa.hpp" %} -%include "uln200xa.hpp" diff --git a/src/uln200xa/pyupm_uln200xa.i b/src/uln200xa/pyupm_uln200xa.i index 60a16b76..b420550f 100644 --- a/src/uln200xa/pyupm_uln200xa.i +++ b/src/uln200xa/pyupm_uln200xa.i @@ -5,6 +5,7 @@ %feature("autodoc", "3"); +%include "uln200xa.h" %include "uln200xa.hpp" %{ #include "uln200xa.hpp" diff --git a/src/uln200xa/uln200xa.c b/src/uln200xa/uln200xa.c new file mode 100644 index 00000000..a2b56b6e --- /dev/null +++ b/src/uln200xa/uln200xa.c @@ -0,0 +1,260 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2016 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 "uln200xa.h" + +static void uln200xa_stepper_step(const uln200xa_context dev); + +uln200xa_context uln200xa_init(int stepsPerRev, unsigned int i1, + unsigned int i2, unsigned int i3, + unsigned int i4) +{ + uln200xa_context dev = + (uln200xa_context)malloc(sizeof(struct _uln200xa_context)); + + if (!dev) + return NULL; + + dev->stepI1 = NULL; + dev->stepI2 = NULL; + dev->stepI3 = NULL; + dev->stepI4 = NULL; + + dev->stepsPerRev = stepsPerRev; + dev->currentStep = 0; + dev->stepDelay = 0; + dev->stepDirection = 1; // default is forward + + // make sure MRAA is initialized + int mraa_rv; + if ((mraa_rv = mraa_init()) != MRAA_SUCCESS) + { + printf("%s: mraa_init() failed (%d).\n", __FUNCTION__, mraa_rv); + uln200xa_close(dev); + return NULL; + } + + // MRAA contexts... + if ( !(dev->stepI1 = mraa_gpio_init(i1)) ) + { + printf("%s: mraa_gpio_init(i1) failed\n", + __FUNCTION__); + uln200xa_close(dev); + return NULL; + } + mraa_gpio_dir(dev->stepI1, MRAA_GPIO_OUT); + + if ( !(dev->stepI2 = mraa_gpio_init(i2)) ) + { + printf("%s: mraa_gpio_init(i2) failed\n", + __FUNCTION__); + uln200xa_close(dev); + return NULL; + } + mraa_gpio_dir(dev->stepI2, MRAA_GPIO_OUT); + + if ( !(dev->stepI3 = mraa_gpio_init(i3)) ) + { + printf("%s: mraa_gpio_init(i3) failed\n", + __FUNCTION__); + uln200xa_close(dev); + return NULL; + } + mraa_gpio_dir(dev->stepI3, MRAA_GPIO_OUT); + + if ( !(dev->stepI4 = mraa_gpio_init(i4)) ) + { + printf("%s: mraa_gpio_init(i4) failed\n", + __FUNCTION__); + uln200xa_close(dev); + return NULL; + } + mraa_gpio_dir(dev->stepI4, MRAA_GPIO_OUT); + + // set default speed to 1 + uln200xa_set_speed(dev, 1); + + return dev; +} + +void uln200xa_close(uln200xa_context dev) +{ + assert(dev != NULL); + + uln200xa_release(dev); + if (dev->stepI1) + mraa_gpio_close(dev->stepI1); + if (dev->stepI2) + mraa_gpio_close(dev->stepI2); + if (dev->stepI3) + mraa_gpio_close(dev->stepI3); + if (dev->stepI4) + mraa_gpio_close(dev->stepI4); + + free(dev); +} + +void uln200xa_set_speed(const uln200xa_context dev, unsigned int speed) +{ + assert(dev != NULL); + + dev->stepDelay = 60 * 1000 / dev->stepsPerRev / speed; +} + +void uln200xa_set_direction(const uln200xa_context dev, + ULN200XA_DIRECTION_T dir) +{ + assert(dev != NULL); + + switch (dir) + { + case ULN200XA_DIR_CW: + dev->stepDirection = 1; + break; + case ULN200XA_DIR_CCW: + dev->stepDirection = -1; + break; + } +} + +static void uln200xa_stepper_step(const uln200xa_context dev) +{ + assert(dev != NULL); + + int step = dev->currentStep % 8; + + // This motor requires a different sequencing order in 8-steps than + // usual. + + // Step I0 I1 I2 I3 + // 1 0 0 0 1 + // 2 0 0 1 1 + // 3 0 0 1 0 + // 4 0 1 1 0 + // 5 0 1 0 0 + // 6 1 1 0 0 + // 7 1 0 0 0 + // 8 1 0 0 1 + + switch (step) + { + case 0: // 0001 + mraa_gpio_write(dev->stepI1, 0); + mraa_gpio_write(dev->stepI2, 0); + mraa_gpio_write(dev->stepI3, 0); + mraa_gpio_write(dev->stepI4, 1); + break; + case 1: // 0011 + mraa_gpio_write(dev->stepI1, 0); + mraa_gpio_write(dev->stepI2, 0); + mraa_gpio_write(dev->stepI3, 1); + mraa_gpio_write(dev->stepI4, 1); + break; + case 2: // 0010 + mraa_gpio_write(dev->stepI1, 0); + mraa_gpio_write(dev->stepI2, 0); + mraa_gpio_write(dev->stepI3, 1); + mraa_gpio_write(dev->stepI4, 0); + break; + case 3: // 0110 + mraa_gpio_write(dev->stepI1, 0); + mraa_gpio_write(dev->stepI2, 1); + mraa_gpio_write(dev->stepI3, 1); + mraa_gpio_write(dev->stepI4, 0); + break; + case 4: // 0100 + mraa_gpio_write(dev->stepI1, 0); + mraa_gpio_write(dev->stepI2, 1); + mraa_gpio_write(dev->stepI3, 0); + mraa_gpio_write(dev->stepI4, 0); + break; + case 5: // 1100 + mraa_gpio_write(dev->stepI1, 1); + mraa_gpio_write(dev->stepI2, 1); + mraa_gpio_write(dev->stepI3, 0); + mraa_gpio_write(dev->stepI4, 0); + break; + case 6: // 1000 + mraa_gpio_write(dev->stepI1, 1); + mraa_gpio_write(dev->stepI2, 0); + mraa_gpio_write(dev->stepI3, 0); + mraa_gpio_write(dev->stepI4, 0); + break; + case 7: // 1001 + mraa_gpio_write(dev->stepI1, 1); + mraa_gpio_write(dev->stepI2, 0); + mraa_gpio_write(dev->stepI3, 0); + mraa_gpio_write(dev->stepI4, 1); + break; + default: + // can't happen + break; + } +} + +void uln200xa_stepper_steps(const uln200xa_context dev, unsigned int steps) +{ + assert(dev != NULL); + + while (steps > 0) + { + upm_delay_ms(dev->stepDelay); + dev->currentStep += dev->stepDirection; + + if (dev->stepDirection == 1) + { + if (dev->currentStep >= dev->stepsPerRev) + dev->currentStep = 0; + } + else + { + if (dev->currentStep <= 0) + dev->currentStep = dev->stepsPerRev; + } + + steps--; + uln200xa_stepper_step(dev); + } +} + +void uln200xa_release(const uln200xa_context dev) +{ + assert(dev !=NULL); + + // we do these check since this is also called from + // uln200xa_close() and we can't be sure that all of the contexts + // have been created yet. + if (dev->stepI1) + mraa_gpio_write(dev->stepI1, 0); + if (dev->stepI2) + mraa_gpio_write(dev->stepI2, 0); + if (dev->stepI3) + mraa_gpio_write(dev->stepI3, 0); + if (dev->stepI4) + mraa_gpio_write(dev->stepI4, 0); +} diff --git a/src/uln200xa/uln200xa.cxx b/src/uln200xa/uln200xa.cxx index 49a3dda8..5fe6ebe3 100644 --- a/src/uln200xa/uln200xa.cxx +++ b/src/uln200xa/uln200xa.cxx @@ -1,6 +1,6 @@ /* * Author: Jon Trulson - * Copyright (c) 2015 Intel Corporation. + * Copyright (c) 2015-2016 Intel Corporation. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -31,218 +31,36 @@ using namespace upm; using namespace std; -ULN200XA::ULN200XA(int stepsPerRev, int i1, int i2, int i3, int i4) +ULN200XA::ULN200XA(int stepsPerRev, unsigned int i1, unsigned int i2, + unsigned int i3, unsigned int i4) : + m_uln200xa(uln200xa_init(stepsPerRev, i1, i2, i3, i4)) { - m_stepsPerRev = stepsPerRev; - m_currentStep = 0; - m_stepDelay = 0; - m_stepDirection = 1; // default is forward - - if ( !(m_stepI1 = mraa_gpio_init(i1)) ) - { - throw std::invalid_argument(std::string(__FUNCTION__) + - ": mraa_gpio_init(i1) failed, invalid pin?"); - return; - } - mraa_gpio_dir(m_stepI1, MRAA_GPIO_OUT); - - if ( !(m_stepI2 = mraa_gpio_init(i2)) ) - { - throw std::invalid_argument(std::string(__FUNCTION__) + - ": mraa_gpio_init(i2) failed, invalid pin?"); - mraa_gpio_close(m_stepI1); - return; - } - mraa_gpio_dir(m_stepI2, MRAA_GPIO_OUT); - - if ( !(m_stepI3 = mraa_gpio_init(i3)) ) - { - throw std::invalid_argument(std::string(__FUNCTION__) + - ": mraa_gpio_init(i3) failed, invalid pin?"); - 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)) ) - { - throw std::invalid_argument(std::string(__FUNCTION__) + - ": mraa_gpio_init(i4) failed, invalid pin?"); - mraa_gpio_close(m_stepI1); - mraa_gpio_close(m_stepI2); - mraa_gpio_close(m_stepI3); - - return; - } - mraa_gpio_dir(m_stepI4, MRAA_GPIO_OUT); - - // set default speed to 1 - setSpeed(1); + if (!m_uln200xa) + throw std::runtime_error(std::string(__FUNCTION__) + + ": uln200xa_init() failed"); } -void ULN200XA::initClock() -{ - gettimeofday(&m_startTime, NULL); -} - -uint32_t ULN200XA::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; -} - - ULN200XA::~ULN200XA() { - mraa_gpio_close(m_stepI1); - mraa_gpio_close(m_stepI2); - mraa_gpio_close(m_stepI3); - mraa_gpio_close(m_stepI4); + uln200xa_close(m_uln200xa); } -void ULN200XA::setSpeed(int speed) +void ULN200XA::setSpeed(unsigned int speed) { - m_stepDelay = 60 * 1000 / m_stepsPerRev / speed; + uln200xa_set_speed(m_uln200xa, speed); } void ULN200XA::setDirection(ULN200XA_DIRECTION_T dir) { - switch (dir) - { - case DIR_CW: - m_stepDirection = 1; - break; - case DIR_CCW: - m_stepDirection = -1; - break; - } -} - -void ULN200XA::stepperStep() -{ - int step = m_currentStep % 8; - - // This motor requires a different sequencing order in 8-steps than - // usual. - - // Step I0 I1 I2 I3 - // 1 0 0 0 1 - // 2 0 0 1 1 - // 3 0 0 1 0 - // 4 0 1 1 0 - // 5 0 1 0 0 - // 6 1 1 0 0 - // 7 1 0 0 0 - // 8 1 0 0 1 - - switch (step) - { - case 0: // 0001 - mraa_gpio_write(m_stepI1, 0); - mraa_gpio_write(m_stepI2, 0); - mraa_gpio_write(m_stepI3, 0); - mraa_gpio_write(m_stepI4, 1); - break; - case 1: // 0011 - mraa_gpio_write(m_stepI1, 0); - mraa_gpio_write(m_stepI2, 0); - mraa_gpio_write(m_stepI3, 1); - mraa_gpio_write(m_stepI4, 1); - break; - case 2: // 0010 - mraa_gpio_write(m_stepI1, 0); - mraa_gpio_write(m_stepI2, 0); - mraa_gpio_write(m_stepI3, 1); - mraa_gpio_write(m_stepI4, 0); - break; - case 3: // 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 4: // 0100 - mraa_gpio_write(m_stepI1, 0); - mraa_gpio_write(m_stepI2, 1); - mraa_gpio_write(m_stepI3, 0); - mraa_gpio_write(m_stepI4, 0); - break; - case 5: // 1100 - mraa_gpio_write(m_stepI1, 1); - mraa_gpio_write(m_stepI2, 1); - mraa_gpio_write(m_stepI3, 0); - mraa_gpio_write(m_stepI4, 0); - break; - case 6: // 1000 - mraa_gpio_write(m_stepI1, 1); - mraa_gpio_write(m_stepI2, 0); - mraa_gpio_write(m_stepI3, 0); - mraa_gpio_write(m_stepI4, 0); - break; - case 7: // 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; - } + uln200xa_set_direction(m_uln200xa, dir); } void ULN200XA::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(); - } - } + uln200xa_stepper_steps(m_uln200xa, steps); } void ULN200XA::release() { - mraa_gpio_write(m_stepI1, 0); - mraa_gpio_write(m_stepI2, 0); - mraa_gpio_write(m_stepI3, 0); - mraa_gpio_write(m_stepI4, 0); + uln200xa_release(m_uln200xa); } diff --git a/src/uln200xa/uln200xa.h b/src/uln200xa/uln200xa.h new file mode 100644 index 00000000..a5192699 --- /dev/null +++ b/src/uln200xa/uln200xa.h @@ -0,0 +1,122 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2016 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 + +#ifdef __cplusplus +extern "C" { +#endif + + + /** + * @file uln200xa.h + * @library uln200xa + * @brief C API for the uln200xa driver + * + * @include uln200xa.c + */ + + /** + * Device context + */ + typedef struct _uln200xa_context { + mraa_gpio_context stepI1; // In1 + mraa_gpio_context stepI2; + mraa_gpio_context stepI3; + mraa_gpio_context stepI4; + + int stepsPerRev; + int currentStep; + uint32_t stepDelay; + int stepDirection; + + } *uln200xa_context; + + /** + * Enum to specify the direction of a motor + */ + typedef enum { + ULN200XA_DIR_CW = 0x01, + ULN200XA_DIR_CCW = 0x02 + } ULN200XA_DIRECTION_T; + + /** + * ULN200XA constructor + * + * @param stepsPerRev Number of steps per full revolution + * @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 + * @return Device context + */ + uln200xa_context uln200xa_init(int stepsPerRev, unsigned int i1, + unsigned int i2, unsigned int i3, + unsigned int i4); + + /** + * ULN200XA destructor + */ + void uln200xa_close(uln200xa_context dev); + + /** + * Sets the speed of the stepper motor in revolutions per minute (RPM) + * + * @param dev Device context + * @param speed Speed to set the motor to, in RPM + */ + void uln200xa_set_speed(const uln200xa_context dev, unsigned int speed); + + /** + * Sets the direction of the motor, clockwise or counterclockwise + * + * @param dev Device context + * @param dir Direction to set the motor to + */ + void uln200xa_set_direction(const uln200xa_context dev, + ULN200XA_DIRECTION_T dir); + + /** + * Steps the stepper motor a specified number of steps + * + * @param dev Device context + * @param steps Number of steps to move the stepper motor + */ + void uln200xa_stepper_steps(const uln200xa_context dev, unsigned int steps); + + /** + * Releases the stepper motor by removing power + * + * @param dev Device context + */ + void uln200xa_release(const uln200xa_context dev); + +#ifdef __cplusplus +} +#endif diff --git a/src/uln200xa/uln200xa.hpp b/src/uln200xa/uln200xa.hpp index 5a941b17..20466552 100644 --- a/src/uln200xa/uln200xa.hpp +++ b/src/uln200xa/uln200xa.hpp @@ -1,6 +1,6 @@ /* * Author: Jon Trulson - * Copyright (c) 2015 Intel Corporation. + * Copyright (c) 2015-2016 Intel Corporation. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -23,11 +23,7 @@ */ #pragma once -#include -#include - -#include -#include +#include namespace upm { @@ -62,14 +58,6 @@ namespace upm { class ULN200XA { public: - /** - * Enum to specify the direction of a motor - */ - typedef enum { - DIR_CW = 0x01, - DIR_CCW = 0x02 - } ULN200XA_DIRECTION_T; - /** * ULN200XA constructor * @@ -79,33 +67,20 @@ namespace upm { * @param i3 Digital pin to use for stepper input 3 * @param i4 Digital pin to use for stepper input 4 */ - ULN200XA(int stepsPerRev, int i1, int i2, int i3, int i4); + ULN200XA(int stepsPerRev, unsigned int i1, unsigned int i2, + unsigned int i3, unsigned int i4); /** * ULN200XA destructor */ ~ULN200XA(); - /** - * Returns the number of milliseconds elapsed since initClock() - * was last called. - * - * @return Elapsed milliseconds - */ - uint32_t getMillis(); - - /** - * Resets the clock - * - */ - void initClock(); - /** * Sets the speed of the stepper motor in revolutions per minute (RPM) * * @param speed Speed to set the motor to, in RPM */ - void setSpeed(int speed); + void setSpeed(unsigned int speed); /** * Sets the direction of the motor, clockwise or counterclockwise @@ -127,31 +102,10 @@ namespace upm { */ void release(); + protected: + uln200xa_context m_uln200xa; + private: - struct timeval m_startTime; - - // stepper (4-wire) - 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; - - /** - * Steps the stepper motor one tick - * - */ - void stepperStep(); - - /** - * Defines the step direction: 1 = forward, -1 = backward - * - */ - int m_stepDirection; }; }