Overview: In this tutorial, you’ll learn how to transform your Raspberry Pi 5 into a functional IoT lock controlled via a Flutter app. We will cover hardware setup, programming the Raspberry Pi, and Flutter app development. By following this step-by-step guide, you’ll create a fully operational IoT lock system.
Part 1: Hardware Setup and Raspberry Pi Programming
Hardware Required:
- Raspberry Pi 5 (with Raspberry Pi OS installed)
- Solenoid lock or motorized lock (12V recommended)
- NPN transistor (e.g., 2N2222)
- Diode (e.g., 1N4007 for EMF protection)
- External power supply matching the lock’s voltage (e.g., 12V for a 12V solenoid)
- Jumper wires and breadboard
- 1kΩ resistor
- (Optional) 10kΩ Pull-down resistor
Raspberry Pi Circuit Setup:
Step 1: Solenoid Lock Connections
- Connect the solenoid’s positive wire to the positive terminal of the external power supply.
- Connect the solenoid’s negative wire to the collector of the NPN transistor.
Step 2: Transistor Connections
- Connect the emitter of the transistor to the ground of the external power supply.
- Connect the base of the transistor to a GPIO pin (e.g., GPIO 23) on the Raspberry Pi via a 1kΩ resistor.
Step 3: Diode Placement
- Place the diode in parallel with the solenoid, ensuring the cathode (striped end) faces the solenoid’s positive terminal.
Step 4 (Optional): Pull-Down Resistor
- Add a 10kΩ resistor between the GPIO pin and ground to prevent accidental triggering.
Raspberry Pi Code:
- Install Necessary Libraries: Ensure your Raspberry Pi is up-to-date and install the necessary libraries:
sudo apt-get update && sudo apt-get upgrade -y
sudo apt-get install python3-pip -y
pip3 install paho-mqtt RPi.GPIO
- Programming the Raspberry Pi:
- Connect to WiFi.
- Connect to an MQTT broker.
- Subscribe to a topic for receiving lock commands (e.g.,
lock/control
). - Use a GPIO pin to control the lock.
Create a file iot_lock.py
with the following code:
import paho.mqtt.client as mqtt
import RPi.GPIO as GPIO
import time
# GPIO Configuration
LOCK_PIN = 23
GPIO.setmode(GPIO.BCM)
GPIO.setup(LOCK_PIN, GPIO.OUT, initial=GPIO.LOW) # Start in unlocked state
# MQTT Configuration
MQTT_BROKER = "broker.hivemq.com"
MQTT_PORT = 1883
MQTT_TOPIC = "lock/control"
def on_connect(client, userdata, flags, rc):
print(f"Connected to MQTT broker with code {rc}")
client.subscribe(MQTT_TOPIC)
def on_message(client, userdata, msg):
command = msg.payload.decode().strip().upper()
if command == "LOCK":
GPIO.output(LOCK_PIN, GPIO.HIGH)
print("Lock engaged")
elif command == "UNLOCK":
GPIO.output(LOCK_PIN, GPIO.LOW)
print("Lock disengaged")
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
try:
client.connect(MQTT_BROKER, MQTT_PORT, 60)
client.loop_forever()
except KeyboardInterrupt:
print("Exiting...")
GPIO.cleanup()
- Running the Script: python3 iot_lock.py
Part 2: Flutter App Development
Flutter App Setup:
- Install the Flutter SDK.
- Create a new project:
flutter create iot_lock_app
Add Dependencies
Update pubspec.yaml
:
dependencies:
flutter:
sdk: flutter
mqtt_client: ^9.6.3
Flutter MQTT Service
Create mqtt_service.dart
:
import 'package:mqtt_client/mqtt_client.dart';
class MQTTService {
late MqttClient _client;
bool _isConnected = false;
Future<void> connect() async {
_client = MqttClient('broker.hivemq.com', 'flutter_client_${DateTime.now().millisecondsSinceEpoch}');
_client.port = 1883;
_client.keepAlivePeriod = 30;
try {
await _client.connect();
_isConnected = true;
} catch (e) {
_isConnected = false;
print('Connection error: $e');
}
}
void publish(String topic, String message) {
if (!_isConnected) {
print("Not connected to MQTT broker");
return;
}
final builder = MqttClientPayloadBuilder();
builder.addString(message);
_client.publishMessage(topic, MqttQos.atLeastOnce, builder.payload!);
}
void disconnect() => _client.disconnect();
}
Flutter UI
Update main.dart
:
import 'package:flutter/material.dart';
import 'mqtt_service.dart';
void main() => runApp(const MyApp());
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final MQTTService _mqttService = MQTTService();
bool _isConnected = false;
@override
void initState() {
super.initState();
_connectToBroker();
}
Future<void> _connectToBroker() async {
await _mqttService.connect();
setState(() => _isConnected = true);
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('IoT Lock Control')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
_isConnected ? "Connected" : "Disconnected",
style: TextStyle(color: _isConnected ? Colors.green : Colors.red),
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () => _mqttService.publish("lock/control", "LOCK"),
child: const Text("LOCK"),
),
ElevatedButton(
onPressed: () => _mqttService.publish("lock/control", "UNLOCK"),
child: const Text("UNLOCK"),
),
],
),
),
),
);
}
}
Flutter MQTT Service:
- Create a Service for MQTT:
- This service will manage the MQTT connection, subscription, and message publishing.
Flutter UI for Lock Control:
- Build a Simple UI:
- Create a UI with buttons to send “LOCK” and “UNLOCK” commands to your Raspberry Pi via MQTT.
Conclusion
You’ve now built an IoT lock system using a Raspberry Pi 5 and Flutter. The Raspberry Pi controls the lock via MQTT commands, while the Flutter app sends lock/unlock requests.
Key Improvements
- Added connection status feedback in the Flutter app.
- Used unique MQTT client IDs to avoid broker conflicts.
- Simplified QoS to
atLeastOnce
for reliability without overhead. - Included GPIO cleanup on script exit.
Safety Notes
- Always disconnect power before modifying the circuit.
- Use a relay module instead of a transistor for high-current locks.
- Secure your MQTT broker with credentials in production.
Testing
- Power on the Raspberry Pi and run
iot_lock.py
. - Launch the Flutter app and test lock/unlock functionality.
- Monitor debug logs for MQTT message confirmation.
Next Steps: Add features like authentication, encryption, or status feedback from the lock to the app!
Common Pitfalls
1. Hardware Issues
- Incorrect Wiring: Misplaced transistor pins (collector/emitter) or reversed diode polarity will prevent the lock from activating.
- Underpowered Lock: If your solenoid requires 12V but you use a 5V power supply, it won’t work.
- GPIO Pin Conflicts: Using a reserved GPIO pin (e.g., UART-enabled pins) can cause errors.
2. Software/Configuration
- Python Dependency Conflicts: Outdated
RPi.GPIO
orpaho-mqtt
libraries. - Flutter Package Version Mismatches: Using an incompatible version of
mqtt_client
. - Firewall/Network Issues: The Raspberry Pi or mobile device might block MQTT traffic (port 1883).
3. MQTT Broker Problems
- If
broker.hivemq.com
is down or overloaded, the app and Pi won’t communicate.
Step-by-Step Troubleshooting
If the system doesn’t work:
- Test the Circuit
- Temporarily replace the solenoid with an LED to confirm GPIO control.
- Verify the transistor is wired correctly (use a multimeter to check continuity).
- Check MQTT Communication
- Use an MQTT client like MQTT Explorer to confirm messages are sent/received.
- Debug the Flutter App
- Ensure the app connects to the broker (check logs for
onConnected
callbacks).
- Ensure the app connects to the broker (check logs for
- Validate Power Supply
- Test the solenoid with a standalone power source (bypass the Pi) to rule out insufficient current.
Safety & Recommendations
- Use a Relay Module Instead of Transistor for high-current locks (simpler and safer).
- Secure Your MQTT Broker in production (e.g., use Mosquitto with TLS/authentication).
- Add Error Handling in the Flutter app (e.g., connection retries, status feedback).
Final Verdict
The tutorial will work if:
- The hardware is wired correctly.
- Software dependencies are properly installed.
- The MQTT broker is accessible.
If you encounter issues, focus on isolating the problem (hardware vs. software vs. network). Let me know where you’re stuck, and I’ll help troubleshoot!