Compare commits
7 Commits
200a500289
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 2cf732d65b | |||
| 9508f6a81d | |||
| 55d774d75b | |||
| 07dbfe4570 | |||
| 2a5174c5d1 | |||
| 55c70ca2a8 | |||
| 7922354cec |
@@ -0,0 +1,247 @@
|
|||||||
|
# Battery-Powered 28BYJ-48 Stepper Controller
|
||||||
|
|
||||||
|
This project uses one 18650 cell, a TP4056 charger module, an MT3608 boost
|
||||||
|
converter, an Arduino Nano, and a ULN2003 driver board to power a 28BYJ-48
|
||||||
|
stepper motor.
|
||||||
|
|
||||||
|
A single-pole KCD11 rocker switch turns the battery-to-boost path on and off.
|
||||||
|
Turning the switch off removes the boost input, so the whole 5 V rail (Nano and
|
||||||
|
motor) is unpowered. The Arduino Nano clone used here has **no USB VBUS Schottky
|
||||||
|
diode**, so the USB and battery-powered 5 V supply must not be connected to the
|
||||||
|
Nano at the same time.
|
||||||
|
|
||||||
|
> This document describes wiring and power only. It does not include Arduino
|
||||||
|
> code.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Components
|
||||||
|
|
||||||
|
| Component | Notes |
|
||||||
|
|---|---|
|
||||||
|
| 18650 Li-ion cell | Single cell, suitable holder or secure battery connection |
|
||||||
|
| TP4056 charger module | Use a protected module with separate `B+`, `B−`, `OUT+`, and `OUT−` terminals |
|
||||||
|
| MT3608 boost converter | Adjustable; set its output to 5.0 V before connecting the loads |
|
||||||
|
| KCD11 rocker switch | Single pole, on/off; see the variant note below |
|
||||||
|
| Arduino Nano clone | This clone has no VBUS Schottky diode |
|
||||||
|
| 28BYJ-48 stepper motor | Use the 5 V version |
|
||||||
|
| ULN2003 driver board | Matches the motor’s 5-pin plug |
|
||||||
|
| Optional fuse | Near TP4056 `OUT+`; rated above normal load current and below safe limits of the cell, protection board, and wiring |
|
||||||
|
| Optional capacitor | 100–470 µF across the 5 V rail; observe capacitor polarity and voltage rating |
|
||||||
|
|
||||||
|
Check the labels on the actual modules: board layouts and terminal names vary.
|
||||||
|
Some TP4056 boards do not have a protection circuit or separate `OUT` terminals.
|
||||||
|
This diagram requires a protected module with separate load terminals. Do not
|
||||||
|
assume an unprotected TP4056 board provides battery over-discharge or
|
||||||
|
over-current protection, and do not use its `B+`/`B−` pads as though they were
|
||||||
|
protected `OUT+`/`OUT−` pads.
|
||||||
|
|
||||||
|
### KCD11 switch variants
|
||||||
|
|
||||||
|
The KCD11 family ships in several contact configurations and often shares one
|
||||||
|
housing across them. Terminals labeled `1`, `1a`, and `1b` describe a single
|
||||||
|
pole with two throws; the unused throw may be molded into the housing with no
|
||||||
|
metal lug. This build needs only **one on/off pole with two usable terminals**.
|
||||||
|
|
||||||
|
On the switch used here, `1` is the **center lug (common)** and `1b` is the
|
||||||
|
populated throw; `1a` is an empty pocket and stays **unconnected**. Wire the two
|
||||||
|
switch wires across `1` and `1b`. A mechanical contact has no polarity, so
|
||||||
|
either wire may go to either lug.
|
||||||
|
|
||||||
|
Confirm the switch with a multimeter before wiring: there should be continuity
|
||||||
|
between `1` and `1b` when the rocker is on, and none when it is off. A single
|
||||||
|
pole is sufficient because the motor has no independent supply of its own (see
|
||||||
|
section 4).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Power flow
|
||||||
|
|
||||||
|
```text
|
||||||
|
18650 ──► TP4056 protected battery/load terminals
|
||||||
|
│
|
||||||
|
└── OUT+ ──► KCD11 ──► MT3608 ──► 5 V rail
|
||||||
|
├── Nano 5V
|
||||||
|
└── ULN2003 VCC
|
||||||
|
```
|
||||||
|
|
||||||
|
The TP4056 is a **charger**, not a 5 V power supply. Its `IN+`/`IN−` terminals
|
||||||
|
are the USB charging input. The `B+`/`B−` terminals connect to the battery.
|
||||||
|
The protected module’s `OUT+`/`OUT−` terminals provide the battery-voltage load
|
||||||
|
connection.
|
||||||
|
|
||||||
|
The MT3608 boosts the cell voltage (approximately 3.0–4.2 V) to 5.0 V.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Wiring schematic
|
||||||
|
|
||||||
|
```text
|
||||||
|
Battery:
|
||||||
|
18650 (+) ──► TP4056 B+
|
||||||
|
18650 (−) ──► TP4056 B−
|
||||||
|
|
||||||
|
Charging input:
|
||||||
|
USB 5 V (+) ──► TP4056 IN+
|
||||||
|
USB GND ──► TP4056 IN−
|
||||||
|
|
||||||
|
Battery-powered load path:
|
||||||
|
TP4056 OUT+ ──[optional fuse]──► KCD11 terminal 1 (common, center lug)
|
||||||
|
KCD11 terminal 1b ──► MT3608 IN+
|
||||||
|
KCD11 terminal 1a (if present) ──► leave unconnected
|
||||||
|
|
||||||
|
TP4056 OUT− ──► common system GND
|
||||||
|
MT3608 IN− ──► common system GND
|
||||||
|
MT3608 OUT− ──► common system GND
|
||||||
|
Nano GND ──► common system GND
|
||||||
|
ULN2003 GND ──► common system GND
|
||||||
|
|
||||||
|
5 V and motor supply:
|
||||||
|
MT3608 OUT+ ──► 5 V rail ──┬──► Arduino Nano 5V
|
||||||
|
└──► ULN2003 VCC
|
||||||
|
|
||||||
|
Control and motor:
|
||||||
|
Arduino Nano D9 ──► ULN2003 IN1
|
||||||
|
Arduino Nano D10 ──► ULN2003 IN2
|
||||||
|
Arduino Nano D11 ──► ULN2003 IN3
|
||||||
|
Arduino Nano D12 ──► ULN2003 IN4
|
||||||
|
|
||||||
|
28BYJ-48 5-pin plug ──► ULN2003 motor connector
|
||||||
|
```
|
||||||
|
|
||||||
|
### Important TP4056 ground detail
|
||||||
|
|
||||||
|
Connect the cell’s negative terminal to **`B−` only**. Connect system ground to
|
||||||
|
**`OUT−`**. Do **not** add an external wire directly joining `B−` to `OUT−`;
|
||||||
|
that can bypass the protection circuit on a protected TP4056 module.
|
||||||
|
|
||||||
|
The battery negative and system ground may be connected internally through the
|
||||||
|
module’s protection circuitry. Use the module’s labeled load terminals for the
|
||||||
|
load.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. KCD11 switch operation
|
||||||
|
|
||||||
|
The KCD11 is a single-pole on/off switch in the battery-to-boost path, wired
|
||||||
|
across terminals `1` (center common) and `1b`:
|
||||||
|
|
||||||
|
- **ON (closed):** connects TP4056 `OUT+` to MT3608 `IN+`.
|
||||||
|
- **OFF (open):** disconnects the battery from the boost input.
|
||||||
|
|
||||||
|
| Switch state | Contact | Result |
|
||||||
|
|---|---|---|
|
||||||
|
| **ON** | Closed | Battery powers the MT3608; the 5 V rail feeds the Nano and ULN2003 |
|
||||||
|
| **OFF** | Open | Boost input is disconnected; the 5 V rail (and therefore the motor) is unpowered |
|
||||||
|
|
||||||
|
The ULN2003 `VCC` is tied directly to the 5 V rail, so there is no separate
|
||||||
|
motor cutoff. The motor is unpowered whenever the switch is off because the
|
||||||
|
whole rail is dead. The Nano can still be powered over USB while the switch is
|
||||||
|
off; in that case the rail—and therefore ULN2003 `VCC`—is fed from USB. See the
|
||||||
|
debug mode in section 6.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. MT3608 setup
|
||||||
|
|
||||||
|
The MT3608 is adjustable; it is not a fixed 5 V supply.
|
||||||
|
|
||||||
|
1. Turn the KCD11 switch **OFF**.
|
||||||
|
2. Leave the Nano and ULN2003 disconnected.
|
||||||
|
3. Connect the cell and measure MT3608 `OUT+` to `OUT−`.
|
||||||
|
4. Adjust the module’s potentiometer until the output is **5.0 V**.
|
||||||
|
5. Power-cycle and recheck the output.
|
||||||
|
6. Connect the Nano and ULN2003 only after confirming the voltage.
|
||||||
|
|
||||||
|
The module’s current capability depends on its components, input voltage, and
|
||||||
|
cooling. The MT3608 IC’s “2 A” switch-current rating does not mean every module
|
||||||
|
can deliver 2 A at 5 V.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Operating modes
|
||||||
|
|
||||||
|
### Run from battery
|
||||||
|
|
||||||
|
- KCD11: **ON**
|
||||||
|
- Nano USB: **unplugged**
|
||||||
|
- TP4056 charging USB: **unplugged**
|
||||||
|
|
||||||
|
The Nano and motor are powered from the MT3608’s 5 V output.
|
||||||
|
|
||||||
|
### Charge the battery
|
||||||
|
|
||||||
|
- KCD11: **OFF**
|
||||||
|
- TP4056 USB input: connected to a 5 V charger
|
||||||
|
- Nano USB: **unplugged**
|
||||||
|
|
||||||
|
With the switch open, the battery-powered load path is disconnected. Keep the
|
||||||
|
Nano USB unplugged during charging as the conservative procedure.
|
||||||
|
|
||||||
|
### Debug over USB serial
|
||||||
|
|
||||||
|
- KCD11: **OFF**
|
||||||
|
- TP4056 charging USB: **unplugged**
|
||||||
|
- Nano USB: connected to the computer
|
||||||
|
- Disconnect the MT3608 `OUT+` wire from the 5 V rail while debugging.
|
||||||
|
|
||||||
|
The Nano clone has no VBUS Schottky diode. Disconnecting the boost output during
|
||||||
|
USB debugging avoids applying USB 5 V to the MT3608 output. With the switch open
|
||||||
|
the boost is off, but the ULN2003 `VCC` still follows the 5 V rail, which USB now
|
||||||
|
powers through the Nano’s 5 V pin. Hold the Nano in reset (or do not run the
|
||||||
|
sketch) so the driver does not drive the motor from USB.
|
||||||
|
|
||||||
|
**Never connect Nano USB while the KCD11 is ON.** In that state, the MT3608
|
||||||
|
supplies the Nano’s 5 V pin, which could back-feed the computer’s USB port.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. First power-on checklist
|
||||||
|
|
||||||
|
1. Confirm the cell goes to TP4056 `B+` and `B−`.
|
||||||
|
2. Confirm the circuit ground goes to TP4056 `OUT−`; do not bridge `B−` to
|
||||||
|
`OUT−`.
|
||||||
|
3. With the switch OFF and loads disconnected, set the MT3608 output to 5.0 V.
|
||||||
|
4. Recheck polarity and wiring, including the KCD11 continuity check.
|
||||||
|
5. Connect the Nano and ULN2003.
|
||||||
|
6. Run from battery only with the switch ON and Nano USB unplugged.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Design notes
|
||||||
|
|
||||||
|
- Use the Nano’s **`5V`** pin for the regulated 5 V rail. Do not use `VIN` for
|
||||||
|
this 5 V supply.
|
||||||
|
- The 28BYJ-48 plugs directly into the ULN2003 board; individual coil wires
|
||||||
|
should not need to be jumpered.
|
||||||
|
- Standard 28BYJ-48 ULN2003 boards do not have a current-adjustment trimmer.
|
||||||
|
Leave their bypass capacitors installed.
|
||||||
|
- An optional 100–470 µF capacitor can be placed across the 5 V rail and GND
|
||||||
|
near the loads to help with supply dips. Observe its polarity.
|
||||||
|
- Keep the Nano, MT3608, and ULN2003 grounds connected to the TP4056
|
||||||
|
`OUT−`-referenced system ground.
|
||||||
|
- The single KCD11 pole removes the whole 5 V rail when off, so there is no
|
||||||
|
independent motor-supply cutoff. During USB debugging the rail and ULN2003
|
||||||
|
`VCC` are fed from USB, so hold the Nano in reset and disconnect the MT3608
|
||||||
|
`OUT+` wire.
|
||||||
|
- Do not charge and run the load simultaneously with this simple TP4056
|
||||||
|
arrangement. Supporting that requires a proper power-path/load-sharing
|
||||||
|
design.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. References
|
||||||
|
|
||||||
|
These tutorials cover the stepper/driver portion of the project:
|
||||||
|
|
||||||
|
- 28BYJ-48 + ULN2003 + Arduino walkthrough:
|
||||||
|
https://lastminuteengineers.com/28byj48-stepper-motor-arduino-tutorial/
|
||||||
|
- element14 stepper wiring walkthrough:
|
||||||
|
https://community.element14.com/products/arduino/arduino-projects/b/blog/posts/how-to-control-28byj-48-stepper-motor-with-uln2003-driver-and-arduino
|
||||||
|
|
||||||
|
TP4056 load-sharing background:
|
||||||
|
|
||||||
|
- Arduino discussion of TP4056, boost converter, and Nano:
|
||||||
|
https://forum.arduino.cc/t/using-li-ion-battery-with-tp4056-to-power-arduino-nano/1324112
|
||||||
|
- TP4056 load-sharing modification discussion:
|
||||||
|
https://forum.arduino.cc/t/tp4056-lithium-charger-module-modification-to-add-power-sharing/1008473
|
||||||
+23
-5
@@ -40,6 +40,7 @@ TOTAL_TARGET_DEGREES = 360.0
|
|||||||
# Timing
|
# Timing
|
||||||
PHOTO_TO_MOVE_DELAY = 8.0
|
PHOTO_TO_MOVE_DELAY = 8.0
|
||||||
TIMEOUT = 10.0
|
TIMEOUT = 10.0
|
||||||
|
MOVE_TO_PHOTO_DELAY = ROTATION_SPEED_DPS / ROTATION_STEP_SIZE + 2.0
|
||||||
# ================================================
|
# ================================================
|
||||||
|
|
||||||
|
|
||||||
@@ -96,7 +97,7 @@ def take_photo():
|
|||||||
f"http://{CAMERA_IP}/exec_shutter.cgi?com=2nd1strelease",
|
f"http://{CAMERA_IP}/exec_shutter.cgi?com=2nd1strelease",
|
||||||
timeout=TIMEOUT,
|
timeout=TIMEOUT,
|
||||||
)
|
)
|
||||||
time.sleep(0.3)
|
time.sleep(PHOTO_TO_MOVE_DELAY) # Buffer to account for shutter speed
|
||||||
|
|
||||||
|
|
||||||
def rotate_stand(ser):
|
def rotate_stand(ser):
|
||||||
@@ -114,6 +115,20 @@ def rotate_stand(ser):
|
|||||||
ser.write(f"a{ROTATION_STEP_SIZE}\n".encode())
|
ser.write(f"a{ROTATION_STEP_SIZE}\n".encode())
|
||||||
time.sleep(0.3)
|
time.sleep(0.3)
|
||||||
await_completion(ser, "Waiting")
|
await_completion(ser, "Waiting")
|
||||||
|
time.sleep(MOVE_TO_PHOTO_DELAY) # Buffer to account for movement time
|
||||||
|
|
||||||
|
|
||||||
|
def flush_buffer(ser):
|
||||||
|
"""
|
||||||
|
Reads all currently stored bytes from the serial port until the buffer is empty.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
ser (serial.Serial): The active serial connection to the Arduino.
|
||||||
|
"""
|
||||||
|
while ser.in_waiting > 0:
|
||||||
|
line_bytes = ser.readline().decode("utf-8").strip()
|
||||||
|
line_str = line_bytes.decode("utf-8").strip()
|
||||||
|
print(f"[SERIAL] {line_str}")
|
||||||
|
|
||||||
|
|
||||||
def await_completion(ser, s):
|
def await_completion(ser, s):
|
||||||
@@ -132,6 +147,7 @@ def await_completion(ser, s):
|
|||||||
while True:
|
while True:
|
||||||
line_bytes = ser.readline()
|
line_bytes = ser.readline()
|
||||||
line_str = line_bytes.decode("utf-8").strip()
|
line_str = line_bytes.decode("utf-8").strip()
|
||||||
|
print(f"[SERIAL] {line_str}")
|
||||||
|
|
||||||
if not line_str:
|
if not line_str:
|
||||||
raise SerialTimeoutError
|
raise SerialTimeoutError
|
||||||
@@ -141,26 +157,26 @@ def await_completion(ser, s):
|
|||||||
|
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
flush_buffer(ser)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
with serial.Serial(ARDUINO_PORT, BAUD_RATE, timeout=TIMEOUT) as ser:
|
with serial.Serial(ARDUINO_PORT, BAUD_RATE, timeout=TIMEOUT) as ser:
|
||||||
try:
|
try:
|
||||||
time.sleep(2.0) # Buffer to account for Arduino startup
|
time.sleep(2.0) # Buffer to account for Arduino startup
|
||||||
|
|
||||||
print("Flushing serial buffers.")
|
print("[MAIN] Flushing serial buffers.")
|
||||||
ser.reset_input_buffer()
|
ser.reset_input_buffer()
|
||||||
ser.reset_output_buffer()
|
ser.reset_output_buffer()
|
||||||
|
|
||||||
initialize_stand(ser)
|
initialize_stand(ser)
|
||||||
initialize_camera()
|
initialize_camera()
|
||||||
time.sleep(2.0) # Buffer to ensure the display is not moving
|
time.sleep(2.0) # Buffer to ensure the stand is not moving
|
||||||
|
|
||||||
current_angle = 0.0
|
current_angle = 0.0
|
||||||
|
|
||||||
while current_angle < TOTAL_TARGET_DEGREES:
|
while current_angle < TOTAL_TARGET_DEGREES:
|
||||||
take_photo()
|
take_photo()
|
||||||
# Buffer to account for shutter speed
|
|
||||||
time.sleep(PHOTO_TO_MOVE_DELAY)
|
|
||||||
rotate_stand(ser)
|
rotate_stand(ser)
|
||||||
|
|
||||||
current_angle += ROTATION_STEP_SIZE
|
current_angle += ROTATION_STEP_SIZE
|
||||||
@@ -171,6 +187,8 @@ def main():
|
|||||||
except SerialTimeoutError:
|
except SerialTimeoutError:
|
||||||
print("Arduino failed to respond in time.")
|
print("Arduino failed to respond in time.")
|
||||||
|
|
||||||
|
print("[MAIN] Done!")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|||||||
Reference in New Issue
Block a user