了解如何将 A7672S 4G LTE GNSS 模块与 Arduino 连接,以构建完全连接的 GPS 跟踪器。发送短信、获取 GPS 坐标并连接到互联网。所有这一切都可以在没有 Wi-Fi 的情况下远程实现。
将显示缩放图像
为什么在您的物联网项目中使用 A7672S?
移动互联网无处不在
Wi-Fi 不适用于远程设置。有了这个模块,您的物联网项目将拥有手机的超能力。它可以连接到4G网络!
内置 GNSS(GPS + 更多)
不需要单独的 GPS 模块。该模块可以使用 GPS、北斗、伽利略或 GLONASS 卫星跟踪位置。
发送短信、拨打电话、连接到服务器
通过Arduino的串行命令控制这一切。非常适合智能汽车、资产跟踪和警报系统。
您将学到什么
使用 Arduino 为 A7672S 接线和供电
对蜂窝和GNSS功能很重要的AT命令
如何测试连接、获取 GPS 坐标、发送消息等
你需要什么
必填
A7672S-FASE 模块(支持 GNSS 的版本)
Arduino UNO(或任何兼容板)
4G LTE天线
GNSS 天线(有源,带 SMA 转 IPEX 适配器)
电源(5V–12V,推荐 3A)
Micro SIM 卡(Airtel、Jio、VI — 全部支持)
自选
USB 转串行适配器(用于直接 AT 命令测试)
长 SMA 延长线(用于更好的室内 GPS 定位)
电路连接
TX(模块)→引脚 10(Arduino RX)
TX(模块)→ 引脚 10(Arduino RX)
RX(模块)→引脚 11(Arduino TX)
RX(模块)→ 引脚 11(Arduino TX)
VCC → 5V (Arduino)
GND → GND (Arduino)
RST(可选)→ 可拉低以复位模块
还连接:
4G 天线至 U.FL1
GNSS天线到U.FL2
为什么这个模块脱颖而出
适用于印度任何地方:支持 Airtel、Jio、VI
内置电平转换器:使用 5V Arduino 安全
处理 GPS + 4G + 短信 + 音频 — 全部集成在一个模块中
使用电池 (3.4–4.2V) 或外部 5–12V 电源工作
下一步是什么?
使用 MQTT 或 HTTP 将数据推送到云仪表板
为移动部署添加备用电池
使用语音呼叫支持进行音频警报或远程麦克风监控
扩展到 ESP32 或 STM32 以实现高级控制
总结
A7672S 在一个模块中为 Arduino 提供蜂窝和 GPS 电源,使现实世界的物联网部署比以往任何时候都更容易、更经济。无论您是跟踪资产、发送警报还是收集远程数据,这款紧凑型板子都是完美的选择。








项目代码
import requests
import json
from datetime import datetime, timedelta
import time
import random
import math
# Configuration
API_KEY = "xxxxxxxxxxxx"
DEVICE_ID = "My Bike"
API_URL = "https://www.circuitdigest.cloud/geolinker"
def send_gps_data(device_id, timestamp, lat, lng, battery, speed=None):
"""
Send GPS data to the API endpoint and display full response
Args:
device_id: Unique identifier for the GPS device
timestamp: Current timestamp for the GPS reading
lat: Latitude coordinate
lng: Longitude coordinate
battery: Battery level percentage
speed: Speed in km/h (optional)
Returns:
API response or None if error occurs
"""
# Prepare payload with sensor data
payload_data = {
"temperature": random.uniform(24.0, 32.0), # Random temperature between 24-32°C
"humidity": random.uniform(60, 80) # Random humidity between 60-80%
}
if speed is not None:
payload_data["speed"] = speed
# Prepare main data structure for API
data = {
"device_id": device_id,
"timestamp": [timestamp],
"lat": [lat],
"long": [lng],
# "battery": [battery], # Commented out as per original
# "payload": [payload_data] # Commented out as per original
}
headers = {
"Authorization": API_KEY,
"Content-Type": "application/json"
}
try:
# Display the data being sent
print(f"📤 Sending data:")
print(f" 📄 Request Headers: {headers}")
print(f" 📦 Request Body: {json.dumps(data, indent=2)}")
response = requests.post(API_URL, json=data, headers=headers)
status_icon = "✓" if response.status_code == 200 else "✗"
# Display the response details
print(f"{status_icon} {timestamp} | Lat: {lat:.6f} | Lng: {lng:.6f} | Speed: {speed or 0:2.0f} km/h | Battery: {battery}%")
print(f" 📡 Response Status: {response.status_code}")
print(f" 📄 Response Headers: {dict(response.headers)}")
try:
response_json = response.json()
print(f" 📋 Response Body: {json.dumps(response_json, indent=2)}")
return response_json
except:
print(f" 📋 Response Text: {response.text}")
return response.text
except Exception as e:
print(f"✗ Error sending data: {e}")
return None
def send_bulk_gps_data(device_id, timestamps, latitudes, longitudes, batteries, payloads):
"""
Send all GPS data in one bulk POST request and display full response
Args:
device_id: Unique identifier for the GPS device
timestamps: List of timestamps
latitudes: List of latitude coordinates
longitudes: List of longitude coordinates
batteries: List of battery levels
payloads: List of payload data
Returns:
API response or None if error occurs
"""
data = {
"device_id": device_id,
"timestamp": timestamps,
"lat": latitudes,
"long": longitudes,
"battery": batteries,
"payload": payloads
}
headers = {
"Authorization": API_KEY,
"Content-Type": "application/json"
}
try:
print(f"\n📦 Sending bulk data with {len(timestamps)} points...")
print(f"📊 Data size: {len(json.dumps(data))} characters")
# Display the data being sent
print(f"\n📤 Sending bulk data:")
print(f" 📄 Request Headers: {headers}")
print(f" 📦 Request Body (first 3 points):")
sample_data = {
"device_id": device_id,
"timestamp": timestamps[:3],
"lat": latitudes[:3],
"long": longitudes[:3],
"battery": batteries[:3],
"payload": payloads[:3]
}
print(json.dumps(sample_data, indent=2))
print(f" (Showing first 3 of {len(timestamps)} points)")
response = requests.post(API_URL, json=data, headers=headers)
print(f"\n📡 Bulk Upload Response:")
print(f" Status Code: {response.status_code}")
print(f" Response Headers: {dict(response.headers)}")
try:
response_json = response.json()
print(f" Response Body: {json.dumps(response_json, indent=2)}")
if response.status_code == 200:
print("✅ Bulk data sent successfully!")
else:
print(f"❌ Error in bulk upload: Status {response.status_code}")
return response_json
except:
print(f" Response Text: {response.text}")
if response.status_code == 200:
print("✅ Bulk data sent successfully!")
else:
print(f"❌ Error in bulk upload: Status {response.status_code}")
return response.text
except Exception as e:
print(f"❌ Exception during bulk upload: {e}")
return None
def calculate_speed_between_points(lat1, lng1, lat2, lng2, time_diff_minutes):
"""
Calculate speed between two GPS coordinates using Haversine formula
"""
if time_diff_minutes <= 0:
return 0
# Earth's radius in kilometers
R = 6371
# Convert latitude and longitude from degrees to radians
lat1_rad = math.radians(lat1)
lat2_rad = math.radians(lat2)
dlat = math.radians(lat2 - lat1)
dlng = math.radians(lng2 - lng1)
# Haversine formula for great-circle distance
a = math.sin(dlat/2)**2 + math.cos(lat1_rad) * math.cos(lat2_rad) * math.sin(dlng/2)**2
c = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a))
distance_km = R * c
# Calculate speed and cap at 80 km/h for realistic city driving
speed_kmh = (distance_km / time_diff_minutes) * 60
return min(speed_kmh, 80)
def get_traffic_delay(hour, is_main_road=False):
"""Simulate traffic-based delays"""
base_delay = 1.0
if 8 <= hour <= 10:
base_delay = 1.8 if is_main_road else 2.2
elif 18 <= hour <= 20:
base_delay = 2.0 if is_main_road else 2.5
elif 15 <= hour <= 16:
base_delay = 1.4 if is_main_road else 1.6
elif 12 <= hour <= 14:
base_delay = 1.2
elif 22 <= hour or hour <= 6:
base_delay = 0.7
return base_delay * random.uniform(0.8, 1.3)
def get_journey_data():
"""
Define the complete journey with GPS coordinates and context information
"""
return [
# Starting location and initial movement
(11.010915301164033, 77.0132087643678, "Home - Journey Start", False),
(11.010852113196895, 77.01297272998573, "Leaving home area", False),
(11.011368147865086, 77.01284398395916, "Local road - heading to main road", False),
# Connecting to main roads
(11.012895183932189, 77.01271523793258, "Approaching main road connection", True),
(11.013400683781928, 77.0126508649193, "Main road junction", True),
(11.013432277493726, 77.01226462683955, "Main road - steady progress", True),
# Main journey on primary roads
(11.012768808834144, 77.00907816268172, "Major road section - good speed", True),
(11.012831996389947, 77.00888504364185, "Continuing on main road", True),
(11.01294784020703, 77.00871338227309, "Main road - approaching junction", True),
(11.01306368397854, 77.00850953439766, "Junction area - slower traffic", True),
# Navigating through complex areas
(11.013253246415422, 77.0082305846734, "Navigating through junction", True),
(11.013379621305521, 77.00788726193586, "Post-junction - picking up speed", True),
(11.013400683781928, 77.00755466803386, "Main road - good traffic flow", True),
(11.013116340223256, 77.0073830066651, "Approaching destination area", True),
# Arriving at destination
(11.012789871354238, 77.00712551461193, "Destination area - slower speeds", False),
(11.012084276110311, 77.00710405694085, "Near destination - parking search", False),
(11.011483992258128, 77.00720061646078, "Destination reached - parking", False),
# Activity at destination
(11.010567767176969, 77.007361548994, "Parked - short walk/activity", False),
(11.010188638723273, 77.00772632940264, "Activity at destination", False),
# Starting return journey
(11.009999074313392, 77.0082949576867, "Preparing to leave destination", False),
(11.009588351006704, 77.0090996203528, "Starting return journey", False),
(11.009630476500412, 77.00924982405049, "Return route - local roads", False),
(11.009641007872897, 77.00934638357042, "Return route progress", False),
(11.009672601988104, 77.0094107565837, "Return route - slow section", False),
(11.009672601988104, 77.0094965872681, "Traffic light/stop", False),
# Return journey main sections
(11.009806413371894, 77.01042480446029, "Return route - main road access", True),
(11.009668649605482, 77.00984427871586, "Return via alternate route", True),
(11.009574719727805, 77.00914254429954, "Return journey - main section", True),
(11.009317977909296, 77.0091935795298, "Return journey continues", True),
(11.009023663841996, 77.00925737356766, "Return - steady progress", True),
# Return journey through different areas
(11.007991322505761, 77.00951042346873, "Return route - different path", True),
(11.007640648812478, 77.00985491127311, "Return journey - avoiding traffic", True),
(11.007302498784261, 77.01039078119103, "Return route - side roads", False),
(11.007026968844638, 77.01119458606792, "Return - residential area approach", False),
(11.00680779711771, 77.01218339365457, "Return - navigating local roads", False),
# Final approach to home
(11.00703323089158, 77.01391221208027, "Return - longer route taken", False),
(11.007678221013876, 77.01345927441155, "Return - heading towards home area", False),
(11.008417140020423, 77.01333168636238, "Return - approaching home locality", False),
(11.009037079096183, 77.01320409828668, "Return - familiar roads", False),
(11.009368965151896, 77.01313392485663, "Return - almost home", False),
(11.009857400529931, 77.01313392485663, "Return - final approach", False),
(11.009882448476192, 77.01332530697017, "Return - entering home area", False),
(11.010045260075, 77.01359962133293, "Return - home locality", False),
(11.010427240780418, 77.01384203867676, "Return - very close to home", False),
(11.010665195723483, 77.01434601157575, "Return - final street", False),
(11.010871840649608, 77.01433325276818, "Return - parking area", False),
(11.011084747391523, 77.01421842350005, "Return - almost parked", False),
(11.010959508150215, 77.01355496550643, "Return - final positioning", False),
(11.01092819833156, 77.01342737743073, "Return - parking maneuver", False),
(11.010890626544791, 77.0132678923361, "Home - Journey Complete", False)
]
def send_bulk_journey_data():
"""
Prepare all journey data and send in one bulk API call (based on second code)
"""
print("📤 BULK DATA UPLOAD MODE")
print("=" * 60)
journey_data = get_journey_data()
start_time = datetime.now().replace(hour=14, minute=30, second=0, microsecond=0)
current_time = start_time
battery_level = 87
timestamps, latitudes, longitudes, batteries, payloads = [], [], [], [], []
print(f"📊 Preparing {len(journey_data)} GPS points for bulk upload...")
for i, (lat, lng, description, is_main_road) in enumerate(journey_data):
if i == 0:
interval = 0
speed = 0
else:
# Calculate realistic time intervals
traffic_factor = get_traffic_delay(current_time.hour, is_main_road)
base_time = random.uniform(45, 120) if not is_main_road else random.uniform(40, 90)
interval = int(base_time * traffic_factor)
current_time += timedelta(seconds=interval)
# Calculate speed between points
time_diff = interval / 60.0
prev_lat, prev_lng = journey_data[i - 1][0], journey_data[i - 1][1]
speed = calculate_speed_between_points(prev_lat, prev_lng, lat, lng, time_diff)
# Apply traffic conditions
if 8 <= current_time.hour <= 10 or 18 <= current_time.hour <= 20:
speed *= random.uniform(0.3, 0.6) # Rush hour traffic
elif is_main_road:
speed *= random.uniform(0.7, 1.0)
else:
speed *= random.uniform(0.4, 0.8)
# Battery drain simulation
battery_drain = random.randint(0, 2) if i % 3 == 0 else 0
battery_level = max(10, battery_level - battery_drain)
# Collect data for bulk send
timestamps.append(current_time.strftime("%Y-%m-%d %H:%M:%S"))
latitudes.append(lat)
longitudes.append(lng)
batteries.append(battery_level)
payloads.append({
"temperature": round(random.uniform(25.0, 32.0), 2),
"humidity": round(random.uniform(60.0, 80.0), 2),
"speed": round(speed, 1)
})
print(f" {i+1:2d}. {description[:50]:<50} | Speed: {speed:4.1f} km/h | Battery: {battery_level:2d}%")
print(f"\n🚀 Sending all {len(timestamps)} points in one request...")
# Send bulk data
response = send_bulk_gps_data(DEVICE_ID, timestamps, latitudes, longitudes, batteries, payloads)
# Summary
print("\n" + "=" * 60)
print("📊 BULK UPLOAD SUMMARY:")
print(f"📍 Total Points: {len(timestamps)}")
print(f"🕐 Journey Time: {start_time.strftime('%H:%M')} - {current_time.strftime('%H:%M')}")
print(f"🔋 Final Battery: {battery_level}%")
print("=" * 60)
def send_single_gps_data():
"""
Send a single GPS data point manually with full response display
"""
print("📍 Send Single GPS Data Point")
print("-" * 40)
try:
# Get user input for GPS data
lat = float(input("Enter Latitude: "))
lng = float(input("Enter Longitude: "))
speed = float(input("Enter Speed (km/h, or 0 if stationary): "))
battery = int(input("Enter Battery Level (0-100): "))
# Generate current timestamp
current_time = datetime.now()
timestamp = current_time.strftime("%Y-%m-%d %H:%M:%S")
print(f"\n🚀 Sending GPS data...")
print(f"📍 Location: {lat}, {lng}")
print(f"🚗 Speed: {speed} km/h")
print(f"🔋 Battery: {battery}%")
print(f"🕐 Time: {timestamp}")
print("-" * 60)
# Send the data and display full response
response = send_gps_data(DEVICE_ID, timestamp, lat, lng, battery, speed)
print("-" * 60)
if response:
print("✅ Single data point sent successfully!")
else:
print("❌ Failed to send data")
except ValueError:
print("❌ Invalid input. Please enter valid numbers.")
except KeyboardInterrupt:
print("\n❌ Operation cancelled by user.")
def run_realistic_journey_simulation():
"""
Run individual GPS point simulation with delays and full response display
"""
journey_data = get_journey_data()
current_time = datetime.now().replace(hour=14, minute=30, second=0, microsecond=0)
battery_level = 87
print("=" * 100)
print("🚗 REALISTIC GPS JOURNEY SIMULATION WITH RESPONSE DISPLAY")
print("=" * 100)
print(f"📍 Total Points: {len(journey_data)}")
print(f"🕐 Start Time: {current_time.strftime('%Y-%m-%d %H:%M:%S')}")
print(f"🔋 Initial Battery: {battery_level}%")
print("=" * 100)
for i, (lat, lng, description, is_main_road) in enumerate(journey_data):
if i == 0:
timestamp = current_time.strftime("%Y-%m-%d %H:%M:%S")
speed = 0
delay_seconds = 0
else:
# Calculate realistic delay
traffic_factor = get_traffic_delay(current_time.hour, is_main_road)
base_time = random.uniform(45, 120) if not is_main_road else random.uniform(40, 90)
delay_seconds = int(base_time * traffic_factor)
current_time += timedelta(seconds=delay_seconds)
timestamp = current_time.strftime("%Y-%m-%d %H:%M:%S")
# Calculate speed
time_diff = delay_seconds / 60.0
prev_lat, prev_lng = journey_data[i - 1][0], journey_data[i - 1][1]
speed = calculate_speed_between_points(prev_lat, prev_lng, lat, lng, time_diff)
# Apply traffic conditions
if 8 <= current_time.hour <= 10 or 18 <= current_time.hour <= 20:
speed *= random.uniform(0.3, 0.6)
# Battery drain
battery_drain = random.randint(0, 2) if i % 3 == 0 else 0
battery_level = max(10, battery_level - battery_drain)
print(f"\n{i+1:2d}. {description}")
print(f" ⏱️ Delay: {delay_seconds:3d}s | 🚗 Speed: {speed:4.1f} km/h | 🔋 Battery: {battery_level:2d}%")
print(" " + "-" * 80)
# Send GPS data with full response display
response = send_gps_data(DEVICE_ID, timestamp, lat, lng, battery_level, speed)
# Short delay for demo
time.sleep(1)
print("\n" + "=" * 100)
print("✅ REALISTIC JOURNEY SIMULATION COMPLETED!")
print("=" * 100)
def main():
"""
Main program entry point with user interface
"""
print("🚗 Enhanced GPS Tracker Simulator with Response Display")
print("=" * 65)
print("Options:")
print("1. Send single GPS data manually (with response display)")
print("2. Run realistic journey simulation (individual points with responses)")
print("3. Send all journey data at once (bulk upload with response)")
choice = input("\nEnter your choice (1, 2, or 3): ").strip()
if choice == "1":
send_single_gps_data()
elif choice == "2":
print("\n🚀 Starting realistic journey simulation...")
run_realistic_journey_simulation()
elif choice == "3":
send_bulk_journey_data()
else:
print("Invalid choice. Please run the program again and select 1, 2, or 3.")
# Run the program when executed directly
if __name__ == "__main__":
main()
【Arduino 动手做】A7672S Arduino 教程:将 4G LTE & GPS 添加到您的项目中
项目链接:https://circuitdigest.medium.com/give-your-arduino-a-sim-card-with-the-a7672s-modules-e8572ab1f6ae
项目参考: https://circuitdigest.com/tutorial/gps-visualizer-for-iot-based-gps-tracking-projects
项目作者:Rithik Krisna
项目代码:
https://github.com/Circuit-Digest/GeoLinker_Tutorial/tree/main
https://github.com/Circuit-Digest/GeoLinker_Tutorial/blob/main/code/GeoLinkerV2_TestCode.py

评论