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!

  • 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 – Code Gorilla Aug 4 '17 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 Aug 4 '17 at 13:09
  • Silly question, are you supplying enough power? – Code Gorilla Aug 4 '17 at 14:26
  • 12v dedicated to the motors which comes in via the power input of the motorshield – EduCoder Aug 4 '17 at 22:10
  • I was hoping you would say I'm running it of D3 :) – Code Gorilla Aug 5 '17 at 13:53
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);  
} 
  • 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 Aug 4 '17 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 Aug 4 '17 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. – Code Gorilla Aug 4 '17 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. – Code Gorilla Aug 4 '17 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 Aug 6 '17 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, privacy policy and cookie policy

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