Hello! I'm working on an easy, that hasn't been that easy for me, project. It basically is an Arduino Uno, a DRV8825, a XL6009 DC-DC boost converter, and a stepper motor.
The project is a Barn Door Star Tracker, a device that counters the earth rotation movement so you can take long exposure pictures with a DSLR camera (And have stunning photos of deep space objects
)
Here is a picture of it:
The camera goes on the ball head mount. The stepper is on the left side of the hinge
The device is supposed to rotate the stepper very slowly, +/- 1.09RPM and when you press a button it will move fast so you can adjust the position of the camera.
The stepper motor I'm using is a 17HS4023 NEMA 17 which works at 12v so I use a XL6009 Buck to boost 5V to 12V.
I mounted everything on a breadboard, powered it with a 5V 2.1Amp USB Power Bank and IT WORKED flawlessly. Then I decided to take the next step and design a custom made PCB to mount it nicely and in a smaller space. In the PCB I opted for just an Atmega A328P and the minimun components it needs to work properly.
Here is the schematic I made in Easy EDA
Yes, I know. It ain't nice or properly aligned. I'm a lawyer who has never studied anything related to mechatronics before
After I received and mounted the components on the PCB I noticed a weird behavior in the stepper motor.
The problem is that it won't spin at a slow speed, it just makes weird noises BUT when I press the buttons to move it faster it spins normally!
Things I've tried:
- Mounted everything back to a bread board. The motor works again.
- Tried different stepping configurations (1/4, 1/8, 1/16, 1/32) and none of them will make the motor spin slow (mounted on my PCB)
- Re adjusting the potentiometer in the DRV8825 following this steps but the problem persists.
- Using a 5V 3A power source connected to the PCB instead of the Power Bank. Doesn't fix the issue.
- Checked Every trace of the PCB with a multimeter but everything seems ok to me.
- Checked the code I'm using but it seems to me that there ain't anything wrong.
- Googled the problem I'm having but I haven't find an answer so far.
The code I'm using:
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Control box for Astrophotohraphy barn door tracker
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// By Nicolas Dupont https://www.thingiverse.com/ndupont/about
//
// Based on https://www.thingiverse.com/thing:1133193 by fermunoz https://www.thingiverse.com/fermunoz/about
//
// Release history
// v0 Original code by fermunoz
// v1 Added button control
// v2 Added tracking ON/OFF control
// v2.1 Solved the motor disable that was not working properly
// SOME MATH :
// radius of the barn door tracker = 200mm (hinge to threaded rod)
// full revolution is 2 * radius * PI = 2 * 200 * 3.141592 = 1256.6368mm
// a full day is 23:56 = 23 * 60 + 56 = 1436 minutes
// movement speed (of the hinge) = 1256.6368 / 1436 = 0.87509 mm/min at threaded rod level
// the M5 stdandard picth is 0.8mm
// Rotation speed of the large gear = 0.85509 / 0.8 = 1.0939 RPM
// Larger gear has 43 teeth, the small one has 10 teeth, gear ratio = 43 / 10 = 4.3
// Small gear (and motor) speed has to be 1.0939 * 4.3 = 4.7036 RPM
// That's 60 / 4.7036 = 12.76 sec/turn ==> useful value to check is all is ok.
// NEMA17 motor usually have 200 steps/rotation
// Stepper pulses = 4.7036 * 200 = 940.72 steps/min or 15.679 pulses/sec
// with 16x microstepping = 250.86 pulses/sec --> 3.986ms delay between pulses = 3986ยตs
// with 32x microstepping = 501.72 pulses/sec --> 1.993ms delay between pulses = 1993ยตs
#define DELAY 3997 //3997 = 1.09 RPM of the large gear ==> WITH 1/16 microstepping (original value from fermunoz
// Setting the variables
const int motor_dir = 8; // Output pin for DIR control of the driver
const int motor_step = 9; // Output pin for STEP control of the driver
const int motor_enable = 10; // Output pin for ENABLE control of the driver
const int led = 13; // Output pin for the LED
int ledState = LOW; // Will store the current ON/OFF state of the LED
unsigned long previousMillis = 0; // used for timing
const long interval = 500; // interval for the blinking LED
int tracking=1; // Tracking ON/OFF state
const int btn_up = 2; // Input pin for the UP/FORWARD push button
const int btn_down = 3; // Input pin for the DOWN/REWIND push button
int btnreadup=0; // Will store the UP button status
int btnreaddown=0; // Will store the DOWN button status
int fastratio=1; // variable containing the ratio that will be applied to the delay between motor pulses
// the setup routine runs once when you press reset:
void setup() {
pinMode(motor_step, OUTPUT); // The 3 motor control line are set as OUTPUT
pinMode(motor_dir, OUTPUT);
pinMode(motor_enable, OUTPUT);
pinMode(led, OUTPUT); // The LED pin is also an OUTPUT...
pinMode(btn_up, INPUT_PULLUP); // Push button input are set as INPUT with PULLUP enable (+5V is applied with an internal resistor)
pinMode(btn_down, INPUT_PULLUP);// And the switches will have an inverted logic = ACTIVE_LOW (the button will apply the ground to the inputs)
}
// the loop routine runs over and over again forever:
void loop() {
if(tracking==0) { // If tracking is disabled...
digitalWrite(motor_enable,HIGH); // disable the motor (inverted logic on the driver)
while(digitalRead(btn_up)+digitalRead(btn_down)==2) {delay(50); // wait until a button is pressed
toggle_led();} // and blink fast
tracking=1;
}
else // IF tracking is not disabled
{
digitalWrite(motor_enable,LOW); // enable the motor (inverted logic on the driver)
unsigned long currentMillis = millis(); // read current timer
if(currentMillis - previousMillis >= interval) { // if time has passed more than the specified interval
// save the last time you blinked the LED
previousMillis = currentMillis; // store the current timer
toggle_led(); // call the toggle_led() function, that will invert the LED output
}
btnreadup=digitalRead(btn_up); // read the button UP status, will return 0 if pressed and 1 if not (inverted logic)
btnreaddown=digitalRead(btn_down); // read the button DOWN status, will return 0 if presses, and 1 if not (inverted logic)
if(btnreadup+btnreaddown==0) {tracking=0; delay(2000);} // if both the buttons are pressed (0+0=0), stop the tracking and wait for 2 sec
if(btnreadup+btnreaddown==2) {fastratio=1;} // if no button is pressed (1+1=2), set the ratio to 1
else {fastratio=800;} // if any button was pressed, set the ratio to 800
if(btnreaddown==1) {digitalWrite(motor_dir,LOW);} // if the button DOWN was pressed, invert the motor DIRECTION
else {digitalWrite(motor_dir,HIGH);} // else setp the motor to the FORWARD direction
digitalWrite(motor_step, LOW); // pulse the motor ouput LOW
digitalWrite(motor_step, HIGH); // set the motor ouput HIGH again
delayMicroseconds(DELAY/fastratio/2); // /2 for 1/32 microstepping // pause the defined time, with ratio applied
} //else
}
void toggle_led() // function that inverts the LED status
{
// if the LED is off turn it on and vice-versa:
if (ledState == LOW) // logic that reads and invert the LED status variable
ledState = HIGH;
else
ledState = LOW;
// set the LED with the ledState of the variable:
digitalWrite(led, ledState); // actual toggle of the LED ouput
}
What could be causing the issue I'm having? Thanks in advance for your opinions.
I have to apologize if my writing isn't that clear, English is not my first language and everything I know about Arduino and electronics comes from YouTube and forums like this.