arduino code for motor shield please

Thread Starter

Phillip Lucas

Joined Mar 13, 2017
28
hey
I am next to useless at coding... I have just figured out functions so yeah.
anyway I was thinking about making a nano or micro motor shield. the code will include a rotary encoder to get precise movements and also allow me to adjust PWM based on weight etc. I have a basic copy of the code and schematic etc.
I just need an idea on how to change the code to not burn out the motor and slowly increase the PWM to help when heavier weights are on the end. I was thinking about adding more increasing the PWM incrementally until the device moves. I was also thinking about making a travel speed variable so that when the device moves it moves "x" steps per second and when motor meets that speed it retains the info, when the weight lowers it will also check to maintain speed for accuracy....
so any ideas?


Code:
#define InA1            10                      // INA motor pin
#define InB1            11                      // INB motor pin
#define PWM1            6                       // PWM motor pin
#define encodPinA1      3                       // encoder A pin
#define encodPinB1      8                       // encoder B pin

#define LOOPTIME        100                     // PID loop time
#define FORWARD         1                       // direction of rotation
#define BACKWARD        2                       // direction of rotation

unsigned long lastMilli = 0;                    // loop timing
unsigned long lastMilliPrint = 0;               // loop timing
long count = 0;                                 // rotation counter
long countInit;
long tickNumber = 0;
boolean run = false;                                     // motor moves

void setup() {
pinMode(InA1, OUTPUT);
pinMode(InB1, OUTPUT);
pinMode(PWM1, OUTPUT);
pinMode(encodPinA1, INPUT);
pinMode(encodPinB1, INPUT);
digitalWrite(encodPinA1, HIGH);                      // turn on pullup resistor
digitalWrite(encodPinB1, HIGH);
attachInterrupt(1, rencoder, FALLING);
Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
}

void loop() {
moveMotor(FORWARD, 50, 464*2);                        // direction, PWM, ticks number
delay(3000);
moveMotor(BACKWARD, 50, 464*2);                           // 464=360°
delay(3000);
}

void moveMotor(int direction, int PWM_val, long tick)  {
countInit = count;    // abs(count)
tickNumber = tick;
   Serial.print(tickNumber);  
    delay(300);
    Serial.print(countInit);  
    delay(300);
if(direction==FORWARD)          motorForward(PWM_val);
else if(direction==BACKWARD)    motorBackward(PWM_val);
}

void rencoder()  {                                    // pulse and direction, direct port reading to save cycles
if (PINB & 0b00000001)    count++;                  // if(digitalRead(encodPinB1)==HIGH)   count_r ++;
else                      count--;                  // if (digitalRead(encodPinB1)==LOW)   count_r --;
if(run) 
   if((abs(abs(count)-abs(countInit))) >= tickNumber)      motorBrake();
}

void motorForward(int PWM_val)  {
analogWrite(PWM1, PWM_val);
digitalWrite(InA1, LOW);
digitalWrite(InB1, HIGH);
run = true;
}

void motorBackward(int PWM_val)  {
analogWrite(PWM1, PWM_val);
digitalWrite(InA1, HIGH);
digitalWrite(InB1, LOW);
run = true;
}

void motorBrake()  {
analogWrite(PWM1, 0);
digitalWrite(InA1, HIGH);
digitalWrite(InB1, HIGH);
run = false;
}
 

Attachments

Sensacell

Joined Jun 19, 2012
3,448
Google "PID control algorithm" Your chosen control concept will not yield satisfying results.

Beware also that encoders with high resolution spinning fast can generate very high frequency pulse trains.
The code cannot miss pulses, if it does, you have lost position.

Your motor runs 185 RPM at the output, the gear ratio is 20:1 this gives an encoder RPM of 3700.
This is 61 revs/second or 3700 Hz encoder frequency. Since there are two channels at 90 degrees, your encoder code will need to handle double this speed at a bare minimum, that's 7400 Hz. That's a period of 135 microseconds.

It's doable with a fast MCU, but a good control algorithm does a lot of multiplying, eats bandwidth quickly.
Most digital motor control solutions utilize dedicated hardware to track the encoder position, and a MAC (multiply and accumulate) engine to speed up the control calculations.

(Edit- my encoder calculations are wrong, the encoder resolution is much lower than I thought after reading the text)
 
Last edited:

MrSoftware

Joined Oct 29, 2013
2,197
For speeding up a stepper driving a load that has a lot of inertia, you need to gradually change the delay between the pulses that are sent to the motor. If you send the pulses too quickly (too little delay between) then the motor will not move and will just sit there and buzz. The pulse needs to deliver enough energy to get the stepper to rotate to the next step, and the delay needs to be long enough that another pulse is not sent until the stepper has rotated far enough that the next pulse will help it rotate further. As the motor speeds up, you can decrease delay and send the pulses quicker to continue increasing motor speed.

Some stepper controllers handle this for you by allowing you to set parameters, then the controller handles the rest. This is usually called the acceleration profile. To get things stopped there is a deceleration profile as well. Here's an example with code for a stepper controller that has this capability built into the hardware:

http://play.karlssonrobotics.com/tutorials/stepper-motors/using-l6470-dual-stepper-controller/

If you want to be able to sense direction of rotation, in addition to position, then you can use a quadrature encoder:

http://www.kr4.us/search.asp?keyword=rotary+encoder&search=

If you want your device to automatically know where it is in space, then use some sort of switch or trigger that is tripped every time your device is in a specific position. That way when it turns on, it can self-reset and you can start tracking position from a known location.
 
Top