Day 7: (Wed Sep 18) DC Motors and Mechanical Structures

Notes for 2019-09-18. See also the Fall 2019 Calendar.

Agenda

  1. Assignments

  2. In-class

Lecture code samples

(See also Lecture Sample Code).

feedback.ino:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// 1. apply proportional feedback using a dual H-bridge driver and analog position sensor
// 2. demonstrate non-blocking event-loop structure
// 3. demonstrate DRV8833 motor driver pulse width modulation
// 4. demonstrate a smoothing filter on an analog input

// Define DRV8833 control pin wiring as per CKS-1 shield board.
const int MOT_A1_PIN = 5;
const int MOT_A2_PIN = 6;
const int MOT_B1_PIN = 10;
const int MOT_B2_PIN = 9;

const int POS_SENSOR_PIN = A0;

/****************************************************************/
void setup(void)
{
  // Configure the four DRV8833 control lines and set them to a quiescent state.
  pinMode(MOT_A1_PIN, OUTPUT);
  pinMode(MOT_A2_PIN, OUTPUT);
  pinMode(MOT_B1_PIN, OUTPUT);
  pinMode(MOT_B2_PIN, OUTPUT);

  digitalWrite(MOT_A1_PIN, LOW);
  digitalWrite(MOT_A2_PIN, LOW);
  digitalWrite(MOT_B1_PIN, LOW);
  digitalWrite(MOT_B2_PIN, LOW);

  // Start the serial port for the console.
  Serial.begin(115200);
}

/****************************************************************/
void loop(void)
{
  static unsigned long last_update_clock = 0;

  unsigned long now = micros();
  unsigned long interval = now - last_update_clock;
  last_update_clock = now;

  poll_feedback_loop(interval);
}

/****************************************************************/
// Polling function for the feedback process: reads an analog position sensor at
// regular sampling intervals, calculates a new motor speed and configures the
// DRV8833 motor driver PWM outputs.

const long sample_interval = 10000;  // 10 msec, 100 Hz sampling
long sample_timer = 0;

float position = 0.0;     // filtered value of the input (unit normalization)
float target = 0.5;       // target position (unit normalization)

void poll_feedback_loop(unsigned long interval)
{
  sample_timer -= interval;
  if (sample_timer <= 0) {
    sample_timer += sample_interval;

    int raw_value = analogRead(POS_SENSOR_PIN);          // read the current input 
    float calibrated = ((float)raw_value) / 1024.0;      // scale to normalized units 

    // first-order smoothing filter to reduce noise in the position estimate
    float difference = calibrated - position;  // compute the 'error' in the sensor reading
    position += 0.2 * difference;              // apply a constant gain to move the smoothed value toward the reading

    // calculate a proportional position control update
    float position_error = target - position;     // compute the position error
    float control_output = 2.0 * position_error;  // apply a proportional position gain

    int control_pwm = constrain((int)(256.0 * control_output), -255, 255);
    set_motor_pwm(control_pwm, MOT_A1_PIN, MOT_A2_PIN);
  }
}

/****************************************************************/
// Set the current speed and direction for either of the DRV8833 channels.
//
// Parameters:
//  pwm     : integer velocity ranging from -255 to 255.
//  IN1_PIN : either MOT_A1_PIN or MOT_B1_PIN
//  IN2_PIN : either MOT_A2_PIN or MOT_B2_PIN
//
// (Note: uses 'fast-decay' mode: coast not brake.)

void set_motor_pwm(int pwm, int IN1_PIN, int IN2_PIN)
{
  if (pwm < 0) {  // reverse speeds
    analogWrite(IN1_PIN, -pwm);
    digitalWrite(IN2_PIN, LOW);

  } else { // stop or forward
    digitalWrite(IN1_PIN, LOW);
    analogWrite(IN2_PIN, pwm);
  }
}

/****************************************************************/