Skip to content

12. Input devices

Group Assignment

  • Probe an input device(s)’s analog levels and digital signals
  • Document your work on the group work page and reflect on your individual page what you learned

Individual Assignment

  • Measure something: add a sensor to a microcontroller board that you have designed and read it

Learning about stepper motors (and drivers)

This week, I worked with a potentiometer, a Xiao RP2040, a custom designed PCB, an A4988 stepper motor driver, and a nema 17 stepper motor. My goal this week was to use the potentiometer to change the speed that a motor could spin at. In order to do this, I had to first research stepper motors. A few of the questions I had at the beginning of this week included the following:

  • What pins do bipolar stepper motors (like the nema 17) have?
  • What driver would be best to use for my purposes (I plan on using the nema 17 for my final project)?
  • How can I turn a stepper motor through code from a chip like the RP2040?

After a few hours of researching and preparing the components I needed, I felt like I had the answers to most of my questions. First, the nema 17 that I was using has 4 pins that form 2 coils. Each coil turns the motor either clockwise or counterclockwise, with 2 pins per coil. Then, I found 2 possible drivers that I could use for my purposes: the L293D or the A4993. In the end, I decided to go with the A4993. This was mainly because I felt that it would be easier to use as well as the fact that it had a smaller footprint. The L293D can control 2 stepper motors simultaneously, but I didn’t need that for what I was trying to do with my nema 17. Finally, I found that. the simplest way to turn a stepper motor through a RP2040 was by connecting one of the RP2040’s pins to the step pin and pulsing high/low signals with specific delays between them. The shorter the delay between high/low pulses, the faster the motor spins. I plan to also connect the analog output pin of my potentiometer to the RP2040 in order to change that delay in real time. I have attached an image ofthe A4988’s pinout below for reference.

Testing the stepper motor and driver

Before trying to incorporate the potentiometer into this week’s assignment, I decided to try turning the nema 17 with just an RP2040 and an A4988. To do this, I set up a breadboard with the Xiao and motor driver on it, as well as a 12V power supply (because the motor requires 8-35V and our lab has a lot of 12V power supplies around). Then, I referenced the pinout of the A4988 to see which pins I would need to connect to where. After doing this, I found that I only needed 4 pins of the Xiao to be connected to the driver. These included 2 digital pins (1 connected to step, 1 to direction) as well as power and ground. As for the A4988, a bit of research showed that the enable pin does not need to be connected for the board to function (because the driver is enabled when the pin recieves low signals, not high), and neither do the 3 microstep pins (this is because I am using the driver in full step mode). Finally, although sleep and reset do not need to be connected to the Xiao, reset is a floating pin (not high or low by default) and therefore needs to be conneceted to sleep for the driver to work. The following link was very helpful when researching the A4988 and helped me greatly when getting this assignment to work.

Now that I knew how to breadboard the Xiao and, all I needed to do was put it into practice. First, I found this photo from the link above which was very helpful in setting up connections:

The difference between my circuit and the one in the picture above is that I connected the step and direction pins of the A4988 to pins 1 and 2 (in Arduino IDE) of the Xiao, respectively. Additionally, I found that, although a 100 uf capacitor between the 12V power and ground is recommended, it is not required to turn the nema 17. With all of this in mind, I wrote some simple code in Arduino IDE.

const int stepPin = 1;
const int dirPin = 2;

void setup() {
  pinMode(stepPin, OUTPUT);
  pinMode(dirPin, OUTPUT);
  digitalWrite(dirPin, HIGH);
}

void loop() {
  digitalWrite(stepPin, HIGH);
  delayMicroseconds(3000);
  digitalWrite(stepPin, LOW);
  delayMicroseconds(3000);
}

The code shown above sets pins 1 and 2 of the Xiao as output pins, with pin 1 being connected to the step pin of the motor driver and pin 2 being connected to the direction pin. The direction pin is sent a high signal which makes the stepper motor turn clockwise, and high/low signals are then repeatedly pulsed to the step pin every 3000 microseconds to make the motor turn. Once I had everything connected on the breadboard, I ran this code through the RP2040, connected the power supply, and it worked! The video below shows this.

Yay! Now I can move onto incorporating the potentiometer with a custom pcb board as well.

Minor Problems Encountered

I encountered one minor problem when testing the breadboard, and that problem was that the motor would spin erratically with little torque after plugging everything in. However, this problem was quickly solved when I realized that there was a small current-limiting potentiometer on the A4988. After spinning it clockwise slightly, the motor began turning correctly (as shown in the video above).

Designing Custom PCB

After getting the breadboard to work, I began to work on creating a custom PCB for the Xiao and A4988 motor driver. However, after spending a LOT of time on this (and even milling the board out twice), I just couldn’t get this initial concept to work. The closest I got was getting the motor to vibrate back and forth, but it would never spin smoothly. Because of this, I shifted to instead just creating a PCB solely for the A4988 and then connecting this board to the Xiao using jumper wires (I think the problem in my board for both the Xiao AND A4988 might have had to do with soldering, not sure though).

This board would be rather simple, as I planned to include the A4988, three 4-pin vertical male headers, one 6-pin vertical male header, and 3 holes for the potentiometer on it. I spent around an hour designing this board, and images of its schematic and PCB layout are shown below.

I then proceeded to mill this board out and solder on all of the components, which took around 30 minutes. Importantly, instead of soldering the A4988 directly into the through-holes, I soldered 2 sets of vertical female headers, allowing me to plug in the driver into them and take it out if needed.

Now that I had my PCB board made, I inserted the A4988, made all of the required wire connections with jumpers (important: I connected the potentiometer to pin 26 on the Xiao, so that is the pin I will reference in the final code). First, though, I decided to test the new PCB board without the potentiometer, and it worked! The video below shows this.

Testing with the Potentiometer

To make the potentiometer work with this PCB board, I had to connect it to power, ground, and I had to connect its analog output pin to a pin (pin 26 in this case) on the Xiao. Since I came back to this week’s assignment during the final parts of my final project’s development, I decided to test it with my final project, a turntable! The code I used is shown below.

const int stepPin = 1;
const int dirPin = 2;
const int potPin = 26;

const int stepsPerRevolution = 200;  // Number of steps per revolution for NEMA 17 motor

void setup() {
  pinMode(stepPin, OUTPUT);
  pinMode(dirPin, OUTPUT);
  pinMode(potPin, INPUT);
  digitalWrite(dirPin, HIGH);  // Sets direction
}

void loop() {
  int potValue = analogRead(potPin);

  // Map the potentiometer value to a speed range (RPM)
  float minRPM = 10.0;
  float maxRPM = 30.0;
  float rpm = map(potValue, 0, 1023, minRPM * 100, maxRPM * 100) / 100.0;

  // Calculate the delay between steps in microseconds
  float stepsPerMinute = rpm * stepsPerRevolution;
  float stepsPerSecond = stepsPerMinute / 60.0;
  float delayBetweenSteps = 1000000.0 / stepsPerSecond;

  // Calculates movement
  digitalWrite(stepPin, HIGH);
  delayMicroseconds(delayBetweenSteps / 2);
  digitalWrite(stepPin, LOW);
  delayMicroseconds(delayBetweenSteps / 2);
}

In the code above, I have mapped the values of the potentiometer from 0 to 1023. The reason for this is that the analogRead function itself always returns a value between 0 and 1023 dependent on the amount of voltage being applied to the pin (see here). That is what I am actually reading with analogRead, the amount of voltage being applied to “potPin”, or pin 26 on the Xiao.

This code makes it so that the motor can spin at a minimum of 10 RPM and a maximum of 30 RPM by using analogRead on the potentiometer’s analog output pin. The video below shows this code working properly with the nema 17 spinning my final project’s turntable.

Group Assignment

This week’s group assignment was to probe the signals of an input device. I was partnered with Kabir, another student from our lab, and we used his input device step-response to do this. Our group documentation is linked here.

Reflection

Overall, I felt good about how I integrated my input device, a potentiometer, into my board, as well as how well it controlled the motor’s speed. I also feel confident about how I will use this in my final project, as the final video on this page showcases. My files for this week can be found here.


Last update: June 26, 2024