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.
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!
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.
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.
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)
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:
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!