DC Motor board with ZDev

In this second article, in the DC Motor series, we provide sample code to use the DC Motor Board with ZDev on the ZKit-ARM-1343. If you haven’t, you might want to read the DC motor board functionality described in the blog article DC Motor Board, Getting Started, before reading this article.

Hardware

DC Motor interface Block
Figure 1. DC Motor interface Block
  • DC Motor Board

  • ZKit-ARM-1343

  • 10 Pin FRC cable.

Connect the DC Motor board to SPI header of ZKit-ARM-1343. Since Pin 2,3 of SPI header is mapped to PWM Channel 2, 0

Table 1. PIN Connections
PIN# DC Motor Board ZKit-ARM-1343(SPI Header) ZDev API Macro

1

VCC

VCC

-

2

PWM0

SCK

PWM_CH2

3

PWM1

MIS0

PWM_CH0

10

GND

GND

-

Software

The software for controlling a DC Motor uses a finite state machine. To acheive this we are going to use event ZDev Library.

DC Motor State Machine
Figure 2. DC Motor State Machine

The State machine for DC Motor application has two states.

  • Rotate Forward

  • Rotate Reverse

On reset, the motor will rotate forward with 10% speed. State transistion occurs when Key1 or Key2 is pressed.

If,

  • Key1 is pressed the Motor rotate forward.

  • Key2 is pressed the motor will rotate reverse.

  • Key3 is pressed speed will be increased.

  • Key4 is pressed speed will be decreased.

No state transisiton for the follwing events.

If,

  • Key1 is pressed and the motor state is Forward.

  • Key2 is pressed and the motor state is Reverse.

The above logic is implemented by registering handler() function using button_setcb(). By using event_poll() button press is detected and the handler function gets called in the event poll loop.

button_setcb(handler);
event_poll();

Following is the source code for DC Motor application.

/*
 * Controlling a DC motor using PWM
 */

#include <board.h>
#include <pwm.h>
#include <delay.h>
#include <button.h>
#include <event.h>

enum motor_direction {
        FORWARD,
        REVERSE,
        SPEEDUP,
        SPEEDDOWN
};

int duty = 0;
int forward_ch = 0;
int reverse_ch = 0;
int state = FORWARD;

void motor_init(int forward_channel, int reverse_channel)
{
        forward_ch = forward_channel;
        reverse_ch = reverse_channel;

        pwm_set_period(forward_ch, 14);
        pwm_set_period(reverse_ch, 14);
}

/**
 * motor_start - start the motor
 * @direction: direction of the motor rotation (FORWARD | REVERSE)
 * Starts the motor in the current direction.
 */
void motor_start(int direction)
{
        if (direction == FORWARD) {
                pwm_set_duty(reverse_ch, 100);
                pwm_set_duty(forward_ch, duty);
        } else {
                pwm_set_duty(forward_ch, 100);
                pwm_set_duty(reverse_ch, duty);
        }

        pwm_start(forward_ch);
        pwm_start(reverse_ch);
}

/**
 * motor_stop - stops motor
 *
 * stops the motor it slowes down eventually
 */
void motor_stop(void)
{
        pwm_set_duty(forward_ch, 100);
        pwm_set_duty(reverse_ch, 100);
}

/**
 * motor_brake - brakes the motor
 *
 * brakes the motor so it stops immediately
 */
void motor_brake(void)
{
        pwm_set_duty(forward_ch, 0);
        pwm_set_duty(reverse_ch, 0);
}

/**
 * motor_chnage_speed - change the motor speed.
 * @speed - Increment or Decrement of speed (SPEEDUP or SPEEDDOWN)
 **/
void motor_change_speed(int speed)
{
        if (speed == SPEEDUP) {
                duty -= 10;
                if (duty < 0)
                        duty = 0;
        } else if (speed == SPEEDDOWN) {
                duty += 10;
                if (duty > 100)
                        duty = 100;
        }
}

/**
 * handler - Handle the button events
 **/
void handler(void)
{
        char k;

        k = button_getc();

        if (k == 0) {
                state = FORWARD;
                motor_stop();
                mdelay(100);
        } else if (k == 1) {
                state = REVERSE;
                motor_stop();
                mdelay(100);
        } else if (k == 2) {
                motor_change_speed(SPEEDUP);
        } else if (k == 3) {
                motor_change_speed(SPEEDDOWN);
        }

        motor_start(state);
}


int main(void)
{
        board_init();
        pwm_init();
        delay_init();
        button_init();
        motor_init(PWM_CH2, PWM_CH0);

        button_setcb(handler);

        event_poll();

        return 0;
}

Credits

The DC Motor icon is based on the original image located here, at Wikimedia Commons.