Skip to end of metadata
Go to start of metadata

You are viewing an old version of this content. View the current version.

Compare with Current View Version History

Version 1 Next »

Objective

The objective of this tutorial is to understand how to connect, using a motor controller, a 12V motor to a CrcDuino. It also shows how to control, in the most basic way, said motor using a quadrature relative encoder (like the one built into goBilda motors). Using an encoder allows to precisely monitor a motor rotation in time.

Wiring schematics and complete presentation

Code

Download the Arduino IDE .ino file:

This is a transcript of the code:

//**************************************************************************************************************************
// CrcDuino Tutorial 4 - Basic power motor control using an encoder
// Inspired by: https://www.norwegiancreations.com/2017/09/arduino-tutorial-using-millis-instead-of-delay/ 
//      and     https://www.norwegiancreations.com/2018/10/arduino-tutorial-avoiding-the-overflow-issue-when-using-millis-and-micros/
// The code below uses the millis() native Arduino function, a command that returns the number of milliseconds since the board started running its current sketch, to measure elapsed time.
// NOTE:  To simplify code and focus on the encoder use, this version of the code does not cover the case where the BTN_RUN is still pressed when the encoder reaches its position.
//**************************************************************************************************************************

#include <CrcLib.h>

//"Encoder" library by Paul Stoffregen must first be installed via "Arduino Library Manager")
//  How-to-use https://www.pjrc.com/teensy/td_libs_Encoder.html
//#define ENCODER_OPTIMIZE_INTERRUPTS
#include <Encoder.h>

//Renaming pins with significant names
#define MC_1 CRC_PWM_1
#define BTN_RUN CRC_DIG_1

//Motor1 encoder variable: "Encoder" library pre-requisite
Encoder motor1Enco(CRC_ENCO_A, CRC_ENCO_B); //This encoder is plugged into these 2 pins on the board

//Program execution variable
bool motorRotating = LOW; // will allow Motor_1 rotation

//Program constants
const int STOP_POSITION = 1994; //Found by trial and error to correspond to a 360deg rotation on my setup. Some motor (like the Bilda) have this information in their specs sheets
const int MOTOR_SPEED = 13; //127*0.10=13
//**************************************************************************************************************************

void setup() {
  CrcLib::Initialize();
  Serial.begin(2000000);  //High baud rate for faster printing on screen

  CrcLib::SetDigitalPinMode(BTN_RUN,INPUT);
  CrcLib::InitializePwmOutput(MC_1); //Use CrcLib::InitializePwmOutput(MC_1,1); to rapidly reverse this motor rotation direction all over the code
  
  //At power-up, establish a known encoder position value
  // Best practice would be to instead assign a physical limit switch indicating the zero position, and have the robot search
  // that position itself at sequence start in the void loop() part. This is called "homing".
  motor1Enco.write(0);
}

void loop() {
  CrcLib::Update();
  Serial.println(motor1Enco.read()); //Continuously print on screen the motor position
  
  if(CrcLib::GetDigitalInput(BTN_RUN) == 0)  //Start rotation when button is pressed
  {
    motorRotating = HIGH;
  }
  
  if(motorRotating == HIGH && (motor1Enco.read() <= STOP_POSITION) ) //Encoder position not yet reached
  {
    CrcLib::SetPwmOutput(MC_1,MOTOR_SPEED);
  }
  else
  {
    CrcLib::SetPwmOutput(MC_1,0);
  }

}

Want smoother, more precise control on a motor position?

This tutorial presents the most basic way to control the position; we run at a fixed rotation speed until the position is reached, and we stop abruptly. It's not really a nice way to do things; inertia will make the rotation stop a little over the desired position, and abrupt stops are not very good for motors.
For example, it's much nicer, when you're in a car approaching a red light, if the driver starts braking ahead of time, gradually reducing the speed until you reach the intersection. Wouldn't it be nice if there was a way for the CrcDuino to know that the motor is getting closer and closer to the desired position, and adjust the speed accordingly to gradually come to a smooth stop? A quite simple, and much documented, way to do so is by incorporating a PID control to your program. Search, as an example, "Arduino PID control position motor" in your favorite search engine to start your exploration of this popular technique.
As a short introduction, such a controller should compare the actual position of the motor (the controlled value) and the desired position (the setpoint). Using mathematical calculations (based on the P, I and D factor values you decide to use), the system will adjust the motor speed (the controlled value) depending on the difference between the two position (the error).

  • No labels