This project provides a complete IoT tank control system combining embedded hardware control with cloud-based orchestration. The architecture spans from low-level motor control on ESP32/ESP8266 platforms using dual L298N H-bridges, through LoRa wireless communication with AES-256-CBC encryption, up to cloud services for real-time command distribution and telemetry streaming.
The system uses Redis Streams as the event backbone, enabling multiple services to coordinate tank control, telemetry broadcasting, and web-based monitoring through a modern microservices architecture deployed on AWS Elastic Beanstalk.
- ESP32/ESP8266 microcontroller running the tank firmware
- L298N Dual H-Bridge for motor control with PWM speed regulation
- LoRa transceiver (SX1276/SX1278) for long-range wireless communication
- TankShift C++ library providing smooth motor ramping and tank-style movement
- AES-256-CBC encryption for secure command reception
- Connects to WiFi and establishes WebSocket connection to Control Broker
- LoRa Transmitter device with physical controls or web interface
- AES-256-CBC encryption matching receiver configuration
- Optional standalone operation or integration with cloud services
- Provides REST endpoint (
/cmd) for remote command injection
WebSocket Gateway managing real-time tank connections:
- Maintains persistent WebSocket connections with tank devices
- Receives commands from Redis
tank_commandsstream - Routes commands to appropriate tank via WebSocket
- Publishes tank status updates to Redis
tank_statusstream - Accepts radar sensor feeds on
/ws/radar/source/{source_id} - Rebroadcasts radar data to listeners at
/ws/radar/listener - Stores radar sweeps to Redis
tank_radarstream - Handles connection lifecycle (registration, heartbeat, disconnection)
- Deployed on AWS Elastic Beanstalk
Web UI and REST Gateway for human operators:
- Provides interactive browser-based controller interface
- REST API for command submission (
POST /command/{tank_id}) - Writes commands to Redis
tank_commandsstream - Subscribes to Redis
tank_statusstream for telemetry - WebSocket endpoint (
/ws/ui/{tank_id}) for real-time UI updates - Deployed on AWS Elastic Beanstalk
Distributed message backbone using AWS ElastiCache (Valkey):
tank_commandsstream: Command queue from UI to tankstank_statusstream: Telemetry flow from tanks to monitoring clients- Provides durability, ordering, and fan-out capabilities
- Enables decoupled service communication
- TLS encryption (rediss://) for secure data transport
[Tank Device (RX)] ←→ WebSocket ←→ [Control Broker] ←→ Redis Streams ←→ [Visual Controller] ←→ HTTP/WS ←→ [Browser UI]
↑ ↑
LoRa (encrypted) Commands/Telemetry
↑ ↓
[LoRa Transmitter (TX)] [Redis Streams (Valkey)]
Command Path: Browser → Visual Controller → Redis tank_commands → Control Broker → WebSocket → Tank Device
Telemetry Path: Tank Device → WebSocket → Control Broker → Redis tank_status → Visual Controller → Browser
- Dual Motor Control: Independent PWM speed regulation (0-255) per motor
- Smooth Transitions: Configurable ramping between speed changes
- Tank-Style Movement: Forward, backward, pivot left/right, gradual turns
- TankShift Library: Platform-independent C++ API for ESP8266/ESP32
- Ultrasonic Radar: HC-SR04 sensor on SG90 servo for 180° environment scanning
- Real-Time Telemetry: Radar sweep data streamed via WebSocket to Control Broker
- AES-256-CBC Encryption: All LoRa commands encrypted end-to-end
- CRC32 Validation: Ensures data integrity across wireless transmission
- Sequence Tracking: Prevents replay attacks and duplicate command processing
- Magic Header & Version Control: Validates protocol compatibility
- TLS/SSL: Secure Redis connections (rediss://) for cloud communication
- Long-Range Operation: Control tanks from hundreds of meters away
- Low Latency: Fast command execution for responsive control
- Frequency Options: 433 MHz, 868 MHz, or 915 MHz regional support
- Adjustable Parameters: Configurable spread factor, bandwidth, and transmit power
- Microservices Design: Decoupled Control Broker and Visual Controller services
- Redis Streams: Durable, ordered message queues with fan-out capabilities
- WebSocket Gateway: Real-time bidirectional communication with hardware
- REST API: Simple HTTP interface for command submission
- Elastic Beanstalk Deployment: Auto-scaling, load balancing, health monitoring
- AWS ElastiCache (Valkey): Managed Redis-compatible event backbone
The ControlProtocol.h header provides a standardized communication framework:
- Platform-Independent: Works across ESP8266, ESP32, and Arduino-compatible boards
- Compact Frame Format: 16-byte encrypted packets minimize bandwidth
- Command Set: Stop, Forward, Backward, Left, Right, SetSpeed
- Easy Integration: Include once, use everywhere
The L298N exposes two identical H bridges. Each side needs:
IN1/IN2/IN3/IN4to choose directionENxto gate power (HIGH = run, LOW = stop) (can be PWM modulated for speed control)
The helper class toggles those pins directly and drives the enable lines with PWM, ramping between targets so direction changes feel smooth.
Supports common LoRa modules (SX1276/SX1278-based):
- Frequency: 433 MHz, 868 MHz, or 915 MHz depending on region
- Spread Factor: Configurable for range vs. speed tradeoff
- Bandwidth: Adjustable based on interference environment
- Output Power: Configurable transmission power
- Algorithm: AES-256 in CBC mode
- Key Size: 256-bit (32 bytes)
- IV Size: 128-bit (16 bytes)
- Block Size: 16 bytes (matches frame size)
| Signal | L298N Pin | ESP8266 Pin | ESP32 (LilyGO) Pin |
|---|---|---|---|
| Motor A PWM | ENA | D7 | 25 |
| Motor A Direction control 1 | IN1 | D2 | 22 |
| Motor A Direction control 2 | IN2 | D1 | 21 |
| Motor B PWM | ENB | D8 | 14 |
| Motor B Direction control 1 | IN3 | D5 | 13 |
| Motor B Direction control 2 | IN4 | D6 | 15 |
| LoRa Pin | ESP8266 Pin | ESP32 Pin | Description |
|---|---|---|---|
| SCK | D5 (GPIO14) | GPIO18 | SPI Clock |
| MISO | D6 (GPIO12) | GPIO19 | SPI Data In |
| MOSI | D7 (GPIO13) | GPIO23 | SPI Data Out |
| NSS/CS | D8 (GPIO15) | GPIO5 | Chip Select |
| RST | D0 (GPIO16) | GPIO14 | Reset |
| DIO0 | D1 (GPIO5) | GPIO26 | Interrupt Pin |
The ultrasonic radar system uses an HC-SR04 ultrasonic sensor mounted on an SG90 servo for scanning:
| Component | Pin | ESP32 Default | ESP8266 Default | Notes |
|---|---|---|---|---|
| HC-SR04 | VCC | 5 V (VIN) | 3V3* | Prefer a 5 V rail on ESP8266 if level shifted |
| HC-SR04 | GND | GND | GND | Common ground with MCU and servo |
| HC-SR04 | Trig | GPIO 32 | D6 | Defined by TRIG_PIN constant |
| HC-SR04 | Echo | GPIO 33 | D7 | Add voltage divider when using ESP8266 |
| SG90 | VCC | 5 V (external) | 5 V (external) | Use dedicated supply; share ground |
| SG90 | GND | GND | GND | Tie grounds together |
| SG90 | PWM | GPIO 13 | D5 | Defined by SERVO_PIN constant |
Note: HC-SR04 ECHO outputs 5 V. Use a level shifter or resistor divider when interfacing with 3.3 V-only boards such as ESP8266.
Power the logic side with 5 V, feed the motor supply (7–12 V typical) to VCC/VIN, and keep grounds common between the driver and the MCU.
On boot, the receiver firmware:
- Creates a SoftAP named
TankController(passwordtank12345) - Starts web server at
http://192.168.4.1with manual control interface - Connects to configured WiFi network (if credentials provided)
- Establishes WebSocket connection to Control Broker service
- Registers tank ID and begins heartbeat transmission
- Exposes REST endpoint at
/cmdfor local command injection
WebSocket gateway deployed on AWS Elastic Beanstalk:
- Listens for tank WebSocket connections on
/ws/tank/{tank_id} - Accepts radar sensor feeds on
/ws/radar/source/{source_id}and rebroadcasts to/ws/radar/listener - Subscribes to Redis
tank_commandsstream - Routes commands to connected tanks
- Publishes telemetry to Redis
tank_statusstream - Stores radar sweeps to Redis
tank_radarstream for downstream consumers - Health check endpoint at
/health - Environment variables:
REDIS_URL,REDIS_COMMAND_STREAM,REDIS_STATUS_STREAM,REDIS_STATUS_MAXLEN,REDIS_RADAR_STREAM,REDIS_RADAR_MAXLEN
Web UI service deployed on AWS Elastic Beanstalk:
- Provides browser interface at
/controller/{tank_id} - REST API at
POST /command/{tank_id}for command submission - WebSocket endpoint at
/ws/ui/{tank_id}for real-time telemetry - Publishes commands to Redis
tank_commandsstream - Subscribes to Redis
tank_statusstream - Environment variables:
REDIS_URL,REDIS_COMMAND_STREAM,REDIS_STATUS_STREAM
AWS ElastiCache (Valkey) provides:
- Stream-based message queuing
- Automatic message TTL and stream trimming
- TLS-encrypted connections (rediss://)
- High availability and durability
- Consumer groups for scalability
- Streams in use:
tank_commands,tank_status,tank_radar
- Install required Arduino libraries via Library Manager
- Update encryption keys in
common/ControlProtocol.h - Configure LoRa frequency and parameters for your region
- Flash receiver sketch to ESP32/ESP8266 on tank
- Flash transmitter sketch to remote LoRa controller
- Configure WiFi credentials in receiver firmware
- Test WebSocket connection to Control Broker
- Create AWS ElastiCache (Valkey) instance with TLS enabled
- Package services using
package.ps1script - Deploy
control-broker-*.zipto Elastic Beanstalk environment - Deploy
visual-controller-*.zipto separate Elastic Beanstalk environment - Configure
REDIS_URLenvironment variable withrediss://connection string - Verify health endpoints respond correctly
- Test end-to-end command flow from browser to tank
- Arduino LoRa library by Sandeep Mistry
- mbedTLS (included with ESP8266/ESP32 cores)
- ESP8266WiFi or WiFi (ESP32) for network connectivity
- WebSocketsClient for Control Broker connection
- TankShift motor control library (included)
- ArduinoJson for command parsing
- FastAPI - Async web framework
- redis.asyncio - Async Redis client
- pydantic - Data validation
- uvicorn - ASGI server
- python-dotenv - Environment configuration
- Install Arduino dependencies
- Update
ControlProtocol.hwith encryption keys - Configure WiFi credentials in receiver firmware
- Set Control Broker WebSocket URL in firmware
- Flash firmware to devices
- Power up and verify WebSocket connection
- Set up AWS ElastiCache (Valkey) with TLS
- Run
.\package.ps1to create deployment packages - Deploy both services to Elastic Beanstalk
- Configure
REDIS_URLenvironment variables - Access Visual Controller web interface
- Test command transmission to connected tanks
