Output Devices

Choosing Stepper Motors

In the final project, I want to have an interactive clock with two hands that can move independently, which means I need two motors that can rotate at different speeds.

The stepper motors that were projected in the shop were too big. Noticing that we don't have any smaller ones, I purchased them myself.

I chose 28BYJ-48, a 5V stepper motor that is cheap and small. I purchased 5 in case I break some of them.

Running Stepper Motor Without Library

At first, I used the AccelStepper.h (link) library that runs the motor beautifully on ESP32-CAM.

While I think it must be the same to run on D11C, I noticed it always failed the compile.

Then I realized maybe the header file was too big, so I commented out it, and yeah, it was able to compile. That means the memory of D11C is too small to hold a stepper motor library. Feeling depressed, I encountered this article that talks about controlling the stepper motor without the library. This is exactly what I need!

I happily copied the code but....id didn't work! I looked closely and noticed that I needed to set the pins according to how the wire goes, so I pull up the sheet.

And notice I should put PIN1 and 3 as A and A-bar, 2 and 4 as B and B-bar accordingly. And yes, it runs very well!

Testing Speed

Because I want to be able to change the speed of the motor, I want to know the limit, so I did some simple tests (the smaller the number, the faster). I used bisection method. Here the value indicates the x in the code. The code is provided in the article that I mentioned in the previous section.

  • 1000, no
  • 5000, yes but too slow
  • 2500, yes
  • 2250, yes
  • 2125, Y
  • 2062, N
  • 2090, Y
  • 2075, barely Yes
  • 2070, Yes
  • 2065, Yes

So the fastest it can go is 2065. As for the slowest, I tried 10000, still noticeable movement. I tried 100000, but it was not very responsive. So the upper limit could be somewhere between 10000 and 100000.

Multithreading? No

In the beginning, I thought it would be great to have both motors (each takes 4 pins) connected to the D11C. But then I realized if I do that, I would need Multithreading to do it. Otherwise, the delay of one motor will cause the delay of the other.

So I ended up connecting one motor to D11C and one to ESP32-CAM. Not very beautiful, but it worked (with some delay that I wasn't able to figure out)

Programming

The OpenCV on python will send the number of faces it detects, so what the ESP32-CAM needs to do is to adjust the speed of the motor accordingly, more specifically:

  • Interaction 1:
    • If the user is looking -> Slow
    • If not ->Fast
  • Interaction 2:
    • If one person -> Slow
    • If two people -> Stop

Therefore I wrote a switch statement that adjusts speeds according to those cases

					
void loop() {
	int num_faces = 0;
	// On the server side (python), we only send info
	// when there is changes. I tried to handle that on this side
	// but for some reason, whenever the board receive data
	// it stop spinning, so it makes the board very lagg
	if (Serial.available() > 0)
	{
		num_faces = Serial.parseInt();
		switch (num_faces)
		{
		case 0:
			update_motor2_speed(speed_3);
			curr_speed = speed_3;
			shouldRun = true;
			delay(500);
		break;
		case 1:
			update_motor2_speed(speed_2);
			curr_speed = speed_2;
			shouldRun = true;
			delay(500);
		break;
		case 2:
		// do nothing for motor 1
		update_motor2_speed(speed_1);
		shouldRun = false;
		delay(500);
		break;
		}
	}
	if (shouldRun) {
	run_motor1(curr_speed);
	}
}

void run_motor1 (int new_speed){

	if (x != new_speed)
	{
		x = new_speed;
	}
	for (int i = 0; i < (stepsPerRevolution / 4); i++) {
	digitalWrite(A, HIGH);
	digitalWrite(A_bar, LOW);
	digitalWrite(B, LOW);
	digitalWrite(B_bar, LOW);
	delayMicroseconds(x);

	digitalWrite(A, LOW);
	digitalWrite(A_bar, LOW);
	digitalWrite(B, HIGH);
	digitalWrite(B_bar, LOW);
	delayMicroseconds(x);

	digitalWrite(A, LOW);
	digitalWrite(A_bar, HIGH);
	digitalWrite(B, LOW);
	digitalWrite(B_bar, LOW);
	delayMicroseconds(x);

	digitalWrite(A, LOW);
	digitalWrite(A_bar, LOW);
	digitalWrite(B, LOW);
	digitalWrite(B_bar, HIGH);
	delayMicroseconds(x);
	}
}

void update_motor2_speed(int new_speed)
{
	itoa(new_speed * 12,mystr,10);
	mySerial.write(mystr,10); //Write the serial data
}
					
				  

I was able to change the speeds of both motors based on the information (number of faces) sent from the computer!