Important update: Arm Announces End of Life Timeline for Mbed. This site will be archived in July 2026. Read the full announcement.
Important changes to forums and questions
All forums and questions are now archived. To start a new conversation or read the latest updates go to forums.mbed.com.
A Motor Class - Coding help please

I've debugged the code and compiled it successfully (of sorts) but I'm still stuck on getting my head round the forward reverse direction part? Would I have to write 2 separate classes one for forward and one for reverse which doesn't seem efficient coding so what's the best way to change the sign of the PinName fwdrev bit?
Yeah using '/' in names is not allowed, also your if statements should use '=='.
But what is the problem with forward and reverse? You can just change fwdrev whenever you want.
Hi Erik, that's the bit I'm stuck with in changing the fwdrev from a 0 (Motor A) to a 1 (Motor B), I understand about the class definition but I think I'm confused a bit in the class implementation. Where and how do you change the bit for fwdrev from a 0 to a 1?
Many thanks. I'll post the full corrected code and some pics once I have it driving the Magnevation board correctly. I'd like to publish a library for it as well.
Problem is, I still dont understand what the problem is. If you want to go forward make it a 1, if you want to go reverse make it a 0, I am sure I am missing something, so what is exactly the problem.
To go forward say, the Motor A needs it to be a 1 but the Motor B needs to be a 0 because it is mounted in the opposite sense, so I'm not sure how the fwdrev bit is changed?
Motor::Motor(PinName pwm, PinName fwdrev, PinName brake): //Class Implementation _pwm(pwm), _fwdrev(fwdrev), _brake(brake) { // Set initial condition of PWM _pwm.period(0.001); _pwm = 0; // Initial condition of output enables _fwdrev = 0; //sets output to drive Motor in a direction /* check the motor to see what direction this is from Magnevation Board */ //Initial condition of Brake _brake = 0; //sets brake to ON condition from Magnevation Board }
How do I change _fwdrev for each motor in code efficiently so I have one class but call it for each motor.
Ah, now I understand. I would add a 'direction' variable, then do something like:
Motor::Motor(PinName pwm, PinName fwdrev, PinName brake, bool direction): //Class Implementation _pwm(pwm), _fwdrev(fwdrev), _brake(brake) { _direction = direction; //_direction must then be declared somewhere in your h-file. }
Then when you want to set _fdwrev you just check the value of _direction first.
Or am I still missing something?
I think I get it now Erik, I'll have a play with things and see where it gets me. I'll re-post this thread as soon as I make progress.
It's a PID loop next to keep each motor rotating at the same velocity, so be warned!
Thanks for the help and advice as always.
With Erik's help I now have a fully compiled Class library without errors for the Magnevation Dual H-Bridge board. Before I go through the exercise of saving and publishing it as a library file (I'll physically run it first of course) I'd like to ask a question on best practice code writing. In the main.cpp file I have put together below is it acceptable to write Forward, Reverse, Stop functions as functions contained within the main.cpp file, or is there a more efficient/intuitive way of writing the code?
#include "mbed.h" #include "TextLCD.h" //Uses Wim Huiskamp's corrected file for a 16x4 display #include "motordriver.h" TextLCD lcd(p15, p16, p17, p18, p19, p20); // rs, e, d4-d7 // Test code, this demonstrates working motor drivers. bool direction, norun; Motor A(p21, p5, p6, direction, norun); // pwm, clockwise(logic high) or anti-clockwise(logic low), brake (logic high brake off) Motor B(p22, p7, p8, direction, norun); // pwm, clockwise(logic high) or anti-clcokwise(logic low), brake (logic high brake off) /*Please pay particular attention to motor direction eg for Forward travel of a rover the Right Hand motor * will go clockwise/anti-clockwise and vice versa for the Left Hand motor depending on wiring and mounting. * To call each motor with the same direction value on the Magnevation board at least one motor will be wired * with opposite polarity to the other. */ int main() { //Drive in one direction //if distance > 100 for (float s = 0.0; s < 1.0 ; s += 0.01) { direction = 0, norun = 1; A.speed(s, direction); B.speed(s, direction); wait(0.02); } //if distance < 100 Slow down and Stop for (float s = 1.0; s > 0.0; s -= 0.01) { norun = 1; A.stop(s, norun); B.stop(s, norun); wait(0.02); } norun = 0; float s = 0; A.stop(s, norun); B.stop(s, norun); wait(1); //Drive in other direction if distance > 100 for (float s = 0.0; s < 1.0 ; s += 0.01) { direction = 1, norun = 1; A.speed(s, direction); B.speed(s, direction); wait(0.02); } wait(1); }
Many thanks.
FYI you now norun/direction don't have a value. You probably just want to write true/false there. Or if they are supplied by the speed/stop functions you only need to have them there, then dont put them in the constructor.
Depending on how general a function is you can either put it in your library or just in the main file of the program. For example the basic speed function you of course want to have in your library. But if you for your specific use case need to drive a figure 8, you put that in your main file somewhere (at least not in the library), since that is something very specific which most people wont require.
I'm not sure I understand the first part of your reply, please can you check the validity of the .h and .cpp files below. They compile correctly so I assumed my understanding was 'fairly' correct, but as I'm learning I'm more than willing to be corrected please.
.h file
#ifndef MBED_MOTOR_H #define MBED_MOTOR_H #include "mbed.h" /** Interface to control a standard DC motor * with an H-bridge using a PwmOut and 2 DigitalOuts * Specifically for the Magnevation Board - refer to comments **/ class Motor //Class Declaration { public: /** Create a motor control interface * * @param pwm, A PwmOut pin driving the H-bridge enable line to control the speed * @param fwdrev, A DigitalOut pin note Forward and Reverse is relative to how you implement motor direction. * Refer to Figure 4 pages 6 & 7 in Texas Instrument LMD18200 data sheet. * @param brake, A DigitalOut pin the motor driver board is able to perform a brake i.e. 0 false brake ON, 1 true brake OFF. */ Motor(PinName pwm, PinName fwdrev, PinName brake, bool direction, bool norun); // Function prototype /** Set the speed of the motor * * @param speed The speed of the motor as a normalised value between 0.0 and 1.0. * Magnevation board sets direction on a pin so does not need -1.0 to 0.0. * @return the applied speed to the motor after checking to ensure motor doesn't switch from forward to reverse without stopping. */ float speed(float speed, bool fwdrev); /** Set the the motor to coast * * In a practical world you would not neccessarily leave anything 'coasting' and acting as a dc generator * always better to have a drive under control at all times so I haven't included this * from the origanal class constructor for the Magnevation Board. */ /** Set the motor to dynamicaly brake * * The Magnevation Board has a brake facility and incorporates the Current Limiting features * of the LMD18200. */ float stop(float speed, bool brake); /** return the current state of the motor * * */ protected: PwmOut _pwm; DigitalOut _fwdrev; DigitalOut _brake; bool _direction; bool _norun; }; #endif
now .cpp file
#include "motordriver.h" #include "mbed.h" Motor::Motor(PinName pwm, PinName fwdrev, PinName brake, bool direction, bool norun): //Class Implementation _pwm(pwm), _fwdrev(fwdrev), _brake(brake) { _direction = direction; //Set each motor to rotate in clockwise or counter clockwise _norun = norun; //Stop all motion // Set initial condition of PWM _pwm.period(0.001); _pwm = 0; // Initial condition of output enables _fwdrev = 0; //sets output to drive Motor in a direction /* check the motor to see what direction this is from Magnevation Board */ //Initial condition of Brake _brake = 0; //sets brake to ON condition from Magnevation Board } float Motor::speed(float speed, bool direction) { _fwdrev = direction; _brake = 1; _pwm = (speed > 0.0); _pwm = abs(speed); return speed; } float Motor::stop(float speed, bool norun) { if (speed == 0.0) { wait(0.02); _brake = norun; } _pwm = abs(speed); return speed; }
Dank u wel
The problem is in your main.cpp, the direction and norun values you assign to the constructor dont have a value. They need to be true or false to actually have a meaning.
I then also wonder if norun is needed there, since you also supply it again in your stop function. But maybe I am mistaken there. Finally in speed I expected it something to be like:
float Motor::speed(float speed, bool direction) { if (_direction) //If in forward direction _fwdrev = direction; //Same as before else //If in backward direction _fwdrev = !direction; //Inverted value _brake = 1; _pwm = (speed > 0.0); //Doesnt do anything since you overwrite it immediatly after _pwm = abs(speed); return speed; //Why return this? }
Or dont use a direction value at all there, and simply use a float between -1 and 1. Like you already do get the absolute value for PWM, and look at the sign for direction.
Ok thanks, I'll rework this tonight at home, I think I can see what you are suggesting. Post again later no doubt!
Thanks for your help and patience as always.
Quick thought and reminder, the direction pin sets the direction from the Magnevation Board Refer to Figure 4 pages 6 & 7 in Texas Instrument LMD18200 data sheet, so I need to pass a 0 or a 1.
You are correct I didn't need the norun in a few places and I've corrected that there as I set the value of _brake = 1 when I make the call for speed.
norun basically allows motion in speed and allows a deceleration to 0 speed before putting the brake on in stop.
After a full week of hardware testing, the code works and if the Magnevation board is wired correctly to the correct outputs from the mbed it performs seamlessly.
Would welcome all comments on the software before I attempt publishing it to the library with some pictures of my set up.
Thank you.
header file
/*motor driver libary modified from the following libary, * * mbed simple H-bridge motor controller * Copyright (c) 2007-2010, sford * *by Derek Calland modified for a Magnevation PWM Driver Board based on LMD18200T H-Bridge Driver IC's * *from sford's libary, and some comments program structure from Christopher Haslers * * 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. */ #ifndef MBED_MOTOR_H #define MBED_MOTOR_H #include "mbed.h" /** Interface to control a standard DC motor * with an H-bridge using a PwmOut and 2 DigitalOuts * Specifically for the Magnevation Board - refer to comments **/ class Motor //Class Declaration { public: /* Create a motor control interface * * @param pwm, A PwmOut pin driving the H-bridge enable line to control the speed * @param fwdrev, A DigitalOut pin note Forward and Reverse is relative to how you implement motor direction. * Refer to Figure 4 pages 6 & 7 in Texas Instrument LMD18200 data sheet. * @param brake, A DigitalOut pin the motor driver board is able to perform a brake i.e. 0 false brake OFF, 1 true brake ON. */ Motor(PinName pwm, PinName fwdrev, PinName brake, bool direction, bool stop); // Function prototype /** Set the speed of the motor * * @param speed The speed of the motor as a normalised value between 0.0 and 1.0. * @param fwdrev Magnevation board sets direction on a pin so does not need -1.0 to 0.0. * @paraam stop * @return the applied speed to the motor after checking to ensure motor doesn't switch from forward to reverse without stopping. */ float speed(float speed, bool fwdrev, bool stop); /** Set the the motor to coast * * In a practical world you would not neccessarily leave anything 'coasting' and acting as a dc generator * always better to have a drive under control at all times so I haven't included this * from the origanal class constructor for the Magnevation Board. */ /** Set the motor to dynamicaly brake * * The Magnevation Board has a brake facility and incorporates the Current Limiting features * of the LMD18200. */ float stop(float speed, bool stop); /** return the current state of the motor */ protected: PwmOut _pwm; DigitalOut _fwdrev; DigitalOut _brake; bool _direction; bool _stop; }; #endif
cpp file
/*motor driver libary modified from the following libary, * * mbed simple H-bridge motor controller * Copyright (c) 2007-2010, S Ford * * by Derek Calland modified for a Magnevation PWM Driver Board based on LMD18200T H-Bridge Driver IC's * * from Christopher Hasler originally from Simon Ford's libary, * * 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 "motordriver.h" #include "mbed.h" Motor::Motor(PinName pwm, PinName fwdrev, PinName brake, bool direction, bool stop): //Class Implementation _pwm(pwm), _fwdrev(fwdrev), _brake(brake) { _direction = direction; //Set each motor to rotate in clockwise or counter clockwise _stop = stop; //Stop all motion // Set initial condition of PWM _pwm.period(0.001); _pwm = 0; // Initial condition of output enables _fwdrev = fwdrev; //sets output to drive Motor in a direction /* check the motor to see what direction this is from Magnevation Board */ //Initial condition of Brake _brake = brake; //sets brake to ON/OFF condition to Magnevation Board } float Motor::speed(float speed, bool direction, bool stop) { _fwdrev = direction; _brake = stop; //Sets brake to ON/OFF condition to Magnevation Board _pwm = abs(speed); return speed; } float Motor::stop(float speed, bool stop) { if (speed == 0.0) { wait(0.02); _brake = stop; } _pwm = abs(speed); return speed; }
main or test file I used
#include "mbed.h" #include "TextLCD.h" //Uses Wim Huiskamp's corrected file for a 16x4 display #include "motordriver.h" TextLCD lcd(p15, p16, p17, p18, p19, p20); // rs, e, d4-d7 // Test code, this demonstrates working motor drivers. bool direction, stop; float distance; Motor A(p21, p5, p6, direction, stop); // pwm, clockwise(logic high) or anti-clockwise(logic low), brake (logic high brake ON) Motor B(p22, p7, p8, direction, stop); // pwm, clockwise(logic high) or anti-clcokwise(logic low), brake (logic high brake ON) /*Please pay particular attention to motor direction eg for Forward travel of a rover the Right Hand motor * will go clockwise/anti-clockwise and vice versa for the Left Hand motor depending on wiring and mounting. * To call each motor with the same direction value on the Magnevation board at least one motor will be wired * with opposite polarity to the other. * Most important reference pages are Figure 4 pages 6 & 7 in LMD18200 data sheet and Magnevation board Input Pin References. */ DigitalIn Forward(p9); DigitalIn Reverse(p10); DigitalIn Stop(p11); int main() { while(1) { lcd.cls(); if (Forward) { direction = 1; stop = 0; for (float s = 0.0; s < 1.0 ; s += 0.01) { A.speed(s, direction, stop); B.speed(s, direction, stop); wait(0.02); lcd.printf("Speed %2.f",s); } wait (2.0); } else if (Reverse) { direction = 0; stop = 0; for (float s = 0.0; s < 1.0 ; s += 0.01) { A.speed(s, direction, stop); B.speed(s, direction, stop); wait(0.02); } wait (2.0); } else if (Stop) { // Slow down and Stop for (float s = 1.0; s > 0.0; s -= 0.01) { stop = true; A.stop(s, stop); B.stop(s, stop); wait(0.02); } } } }
I'm trying to write a class for the Magnevation board I have. So instead of using multiple function calls in my original program I want it to use a class and make it more efficient. The problem I'm having is understanding how in the class implementation file the motor direction is controlled by toggling the _fwd/rev(fwd/rev). I've tried to provide explanatory comments throughout.
motordriver.h
motordriver.cpp
main.cpp