0

This may be a very simple problem but it has had me going round and round in circles, it is VERY similar to this [ Problem with wrapping Adafruit Motor Controller function calls in a class] question but try as I might I couldn't resolve the issue using this example. So I will include my code and hope that someone with more experience takes pity on me. This code compiles with no errors but the motors don't start Like the linked question it all worked before it was separated into the individual files.

robot.ino:

#include "E:\chhs2017\LegoRobotics\SketchesThatNeedToWork\RobotBase\RobotBase.h"

RobotBase *base;

void setup(){
    base = new RobotBase();
}

void loop(){
    base->moveRobotForward(base->HALF_SPEED);
//  base->stopRobotAfter(1500);
}

RobotBase.h:

#ifndef ROBOTBASE_H
#define ROBOTBASE_H

#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_MS_PWMServoDriver.h"

class RobotBase{

    public:
        const int MAX_SPEED = 255;
        const int THREE_QUARTER_SPEED = 190;
        const int HALF_SPEED = 127;
        const int QUARTER_SPEED = 90;
        const int MIN_SPEED = 30;

        RobotBase();

        void moveRobotForward(int inSpeed);
        void moveRobotBackward(int inSpeed);
        void moveRobotLeft(int inSpeed);
        void moveRobotRight(int inSpeed);
        void rotateRobotRight(int inSpeed);
        void rotateRobotLeft(int inSpeed);
        void stopRobotAfter(int time);

    protected:
        Adafruit_MotorShield AFMS; 
        Adafruit_DCMotor *myMotorM1;
        Adafruit_DCMotor *myMotorM2;
        Adafruit_DCMotor *myMotorM3;
        Adafruit_DCMotor *myMotorM4;            
};
#endif

RobotBase.ino:

/*************************************************************
* this is the robot base control class which is designed for a 
* four wheel robot construction using an Adafruit_DCMotor controller
* and and arduino Uno 
**************************************************************/

#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_MS_PWMServoDriver.h"
#include "E:/chhs2017/LegoRobotics/SketchesThatNeedToWork/RobotBase/RobotBase.h"

RobotBase::RobotBase()  {
    AFMS = Adafruit_MotorShield(); 
    myMotorM1 = AFMS.getMotor(1);
    myMotorM2 = AFMS.getMotor(2);
    myMotorM3 = AFMS.getMotor(3);
    myMotorM4 = AFMS.getMotor(4);   
}

void RobotBase::stopRobotAfter(int time){
    delay(time);
    myMotorM1->run(RELEASE); 
    myMotorM2->run(RELEASE); 
    myMotorM3->run(RELEASE); 
    myMotorM4->run(RELEASE);   
}

void RobotBase::moveRobotForward(int inSpeed){
    myMotorM1->setSpeed(inSpeed); 
    myMotorM1->run(FORWARD);
    myMotorM2->setSpeed(inSpeed); 
    myMotorM2->run(FORWARD);
    myMotorM3->setSpeed(inSpeed); 
    myMotorM3->run(FORWARD);
    myMotorM4->setSpeed(inSpeed); 
    myMotorM4->run(FORWARD);
}

void RobotBase::moveRobotBackward(int inSpeed){
    myMotorM1->setSpeed(inSpeed); 
    myMotorM1->run(BACKWARD);
    myMotorM2->setSpeed(inSpeed); 
    myMotorM2->run(BACKWARD);
    myMotorM3->setSpeed(inSpeed); 
    myMotorM3->run(BACKWARD);
    myMotorM4->setSpeed(inSpeed); 
    myMotorM4->run(BACKWARD);
}

void RobotBase::moveRobotLeft(int inSpeed){
    myMotorM1->setSpeed(inSpeed); 
    myMotorM1->run(FORWARD);
    myMotorM2->setSpeed(inSpeed); 
    myMotorM2->run(BACKWARD);
    myMotorM3->setSpeed(inSpeed); 
    myMotorM3->run(FORWARD);
    myMotorM4->setSpeed(inSpeed); 
    myMotorM4->run(BACKWARD);
}

void RobotBase::moveRobotRight(int inSpeed){
    myMotorM1->setSpeed(inSpeed); 
    myMotorM1->run(BACKWARD);
    myMotorM2->setSpeed(inSpeed); 
    myMotorM2->run(FORWARD);
    myMotorM3->setSpeed(inSpeed); 
    myMotorM3->run(BACKWARD);
    myMotorM4->setSpeed(inSpeed); 
    myMotorM4->run(FORWARD);
}

void RobotBase::rotateRobotRight(int inSpeed){
    myMotorM1->setSpeed(inSpeed); 
    myMotorM1->run(FORWARD);
    myMotorM2->setSpeed(inSpeed); 
    myMotorM2->run(FORWARD);
    myMotorM3->setSpeed(inSpeed); 
    myMotorM3->run(BACKWARD);
    myMotorM4->setSpeed(inSpeed); 
    myMotorM4->run(BACKWARD);
}

void RobotBase::rotateRobotLeft(int inSpeed){
    myMotorM1->setSpeed(inSpeed); 
    myMotorM1->run(BACKWARD);
    myMotorM2->setSpeed(inSpeed); 
    myMotorM2->run(BACKWARD);
    myMotorM3->setSpeed(inSpeed); 
    myMotorM3->run(FORWARD);
    myMotorM4->setSpeed(inSpeed); 
    myMotorM4->run(FORWARD);
}

Thanks in Advance!

6
  • You've not actually said what the problem is. You've said "Its similar to this...", but it isn't because you have initialised the pointer. Its strange that you have a RobotBase.ino rather than RobotBase.cpp, but if it compiles that must be OK. You might want to check the values returned by AFMS.getMotor() to make sure they aren't NULL Commented Aug 4, 2017 at 7:51
  • Sorry if i didn't make it clear the problem is the motors don't spin, everything compiles without error but motors don't go. I also thought about the ino vs cpp but didn't have time to test it today
    – EduCoder
    Commented Aug 4, 2017 at 13:09
  • Silly question, are you supplying enough power? Commented Aug 4, 2017 at 14:26
  • 12v dedicated to the motors which comes in via the power input of the motorshield
    – EduCoder
    Commented Aug 4, 2017 at 22:10
  • I was hoping you would say I'm running it of D3 :) Commented Aug 5, 2017 at 13:53

2 Answers 2

1

It may be the way you are initializing the motor shield object. Try doing:

RobotBase::RobotBase() : AFMS() {
     myMotorM1 = AFMS.getMotor(1);
     myMotorM2 = AFMS.getMotor(2);
     myMotorM3 = AFMS.getMotor(3);
     myMotorM4 = AFMS.getMotor(4);  
} 
6
  • I can't test this solution yet as the hardware is at work but could you explain the reasoning behind the idea? Is addind the AFMS () after the call to the constructor extending AFMS? wouldn't i need to define that in the class definition in the .h file first?
    – EduCoder
    Commented Aug 4, 2017 at 13:15
  • 1
    AFMS is an instance of Adafruit_MotorShield and is defined in the header already. All this is doing is initializing it as part of the constructor of RobotBase.
    – Andrew
    Commented Aug 4, 2017 at 14:24
  • AFMS = Adafruit_MotorShield(); takes an instance of Adafruit_MotorShield initialised by the default constructor and copies it to your variable AFMS. :AFMS(){ Initialises your variable AFMS using the default constructor for Adafruit_MotorShield. Its a subtle difference, but not copying things is always a good plan. Do you need to change AFMS? No, because AFMS() is calling the class's default constructor. You could do int aNumber(0); if you wanted, but you do int aNumber = 0; they are the same. Commented Aug 4, 2017 at 14:24
  • You could go a step further and do : AFMS(), myMotorM1(AFMS.getMotor(1)), myMotorM2(AFMS.getMotor(2)), myMotorM3(AFMS.getMotor(3)), myMotorM5(AFMS.getMotor(4)) {} I think that will work, you might get issues with ordering, because of the dependencies on AFMS. Commented Aug 4, 2017 at 14:26
  • Both ideas were tested nothing to note occurred, so I am going to revert the code back to the previous layout. I understand your comment on efficiency and not making unnecessary copies of libraries, But as I am using this code with young (year 9; 14-15yr olds) students I need to consider readability as well as efficiency. To explain bringing Adafruit_MotorShield object to our code and use some of its features is easier if we actually bring the object to our code- I'll work on upping the efficiency later (when I get my head around it) :-D
    – EduCoder
    Commented Aug 6, 2017 at 23:48
0

Hey Guy's As I suspected it was actually an easy fix after leaving it alone for a couple of days came back with fresh eyes and saw the problem straight away. I had failed to start the MotorController board. So all that was needed was the begin function call base->AFMS.begin(); in the setup of robot.ino, all working fine now. Thanks again for your help.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.