# L298N Motor Driver Library
[](https://hex.pm/packages/l298n)
[](https://hexdocs.pm/l298n/)
An Elixir library for controlling L298N dual H-bridge motor driver via GPIO. This library provides a high-level interface for motor control with PWM speed control and direction management using the Pigpiox library.
## Features
- ✅ Control up to 2 DC motors independently
- ✅ PWM speed control (0-100% in both directions)
- ✅ Safe motor stopping with graceful shutdown
- ✅ GenServer-based process for reliable state management
- ✅ Comprehensive error handling and validation
- ✅ Extensive documentation and examples
## Hardware Requirements
- Raspberry Pi (or compatible GPIO device)
- L298N dual H-bridge motor driver module
- DC motors (up to 2)
- Proper power supply for motors
## Hardware Wiring
Connect your L298N module to your Raspberry Pi GPIO pins:
| L298N Pin | Function | Raspberry Pi GPIO | Description |
|-----------|----------|------------------|-------------|
| IN1 | Motor A Dir 1 | Any GPIO pin | Motor A direction control |
| IN2 | Motor A Dir 2 | Any GPIO pin | Motor A direction control |
| ENA | Motor A Enable | PWM capable GPIO | Motor A speed control (PWM) |
| IN3 | Motor B Dir 1 | Any GPIO pin | Motor B direction control |
| IN4 | Motor B Dir 2 | Any GPIO pin | Motor B direction control |
| ENB | Motor B Enable | PWM capable GPIO | Motor B speed control (PWM) |
### Example Wiring
```
L298N -> Raspberry Pi
IN1 -> GPIO 21
IN2 -> GPIO 20
ENA -> GPIO 18 (PWM)
IN3 -> GPIO 16
IN4 -> GPIO 12
ENB -> GPIO 13 (PWM)
```
## Installation
Add `l298n` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[
{:l298n, "~> 0.1.0"}
]
end
```
## Usage
### Basic Setup
```elixir
# Start the L298N driver with your pin configuration
{:ok, pid} = L298n.start_link([
motor_a: %{in1: 21, in2: 20, en: 18},
motor_b: %{in1: 16, in2: 12, en: 13}
])
```
### Motor Control
```elixir
# Move both motors forward at 50% speed
L298n.set_motors(50, 50)
# Turn left (motor A forward, motor B backward)
L298n.set_motors(30, -30)
# Control motors individually
L298n.set_motor_a(75) # Motor A forward at 75%
L298n.set_motor_b(-60) # Motor B backward at 60%
# Stop all motors
L298n.stop_all()
# Check current motor speeds
speeds = L298n.get_motor_speeds()
# => %{motor_a: 0, motor_b: 0}
```
### Speed Values
Motor speed is specified as a percentage from **-100 to 100**:
- **Positive values (1 to 100)**: Forward direction
- **Negative values (-1 to -100)**: Backward direction
- **0**: Stop motor
- **±100**: Full speed
### Single Motor Configuration
You can configure only one motor if needed:
```elixir
# Configure only Motor A
{:ok, pid} = L298n.start_link([
motor_a: %{in1: 21, in2: 20, en: 18}
])
L298n.set_motor_a(50) # Only Motor A will move
L298n.set_motors(30, 75) # Motor A: 30%, Motor B: ignored (not configured)
```
### Supervision
For production use, add L298n to your supervision tree:
```elixir
defmodule MyApp.Application do
use Application
def start(_type, _args) do
children = [
{L298n, [
motor_a: %{in1: 21, in2: 20, en: 18},
motor_b: %{in1: 16, in2: 12, en: 13},
name: MyApp.MotorDriver
]}
]
opts = [strategy: :one_for_one, name: MyApp.Supervisor]
Supervisor.start_link(children, opts)
end
end
```
## API Reference
### Core Functions
- `L298n.start_link/1` - Start the motor driver process
- `L298n.set_motors/2` - Control both motors simultaneously
- `L298n.set_motor_a/1` - Control motor A only
- `L298n.set_motor_b/1` - Control motor B only
- `L298n.stop_all/0` - Stop all motors immediately
- `L298n.get_motor_speeds/0` - Get current motor speed settings
### Error Handling
The library includes comprehensive input validation:
```elixir
# These will raise FunctionClauseError
L298n.set_motors(101, 0) # Speed > 100
L298n.set_motors(0, -101) # Speed < -100
L298n.set_motor_a("fast") # Non-integer speed
```
## Dependencies
- `pigpiox` - GPIO control for Raspberry Pi
- `ex_doc` - Documentation generation (dev only)
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
## Contributing
1. Fork the repository
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request
## Troubleshooting
### Common Issues
**Motors not responding:**
- Check wiring connections
- Verify GPIO pin numbers in configuration
- Ensure adequate power supply for motors
- Check that pigpiod daemon is running
**Permission errors:**
- Ensure your user has GPIO access permissions
- Run with appropriate privileges if needed
**PWM not working:**
- Verify EN pins are connected to PWM-capable GPIO pins
- Check that pins aren't already in use by other processes
### Debug Mode
Enable debug logging to troubleshoot issues:
```elixir
# In config/config.exs
config :logger, level: :debug
```