from machine import UART, Pin, SPI, I2C
import time, random
import network, urequests
# ==============================
# MODE
# ==============================
SIMULATION = True # True = Wokwi, False = matériel réel
# --- Configuration Wi-Fi ---
SSID = "Wokwi-GUEST"
PASSWORD = ""
API_KEY = "DSS1GWB1MWJTJNDP"
URL = "https://api.thingspeak.com/update"
# ==============================
# CLASS Virtual GPS
# ==============================
class VirtualGPS:
def __init__(self):
self.lat = 33.8889
self.lon = 10.1036
def decimal_to_nmea(self, value, is_lat=True):
deg = int(value)
minutes = (value - deg) * 60
return f"{deg:02d}{minutes:06.3f}" if is_lat else f"{deg:03d}{minutes:06.3f}"
def read_nmea(self):
self.lat += random.uniform(-0.0005, 0.0005)
self.lon += random.uniform(-0.0005, 0.0005)
speed = random.uniform(0, 50)
date = "160426"
time_utc = "123519"
lat_nmea = self.decimal_to_nmea(abs(self.lat), True)
lon_nmea = self.decimal_to_nmea(abs(self.lon), False)
lat_dir = "N" if self.lat >= 0 else "S"
lon_dir = "E" if self.lon >= 0 else "W"
return f"$GPRMC,{time_utc},A,{lat_nmea},{lat_dir},{lon_nmea},{lon_dir},{speed:.1f},0.0,{date},,,A*00"
def convert_to_decimal(coord, direction):
if not coord: return None
try:
deg = int(coord[:2]) if direction in ['N','S'] else int(coord[:3])
minutes = float(coord[2:]) if direction in ['N','S'] else float(coord[3:])
decimal = deg + minutes/60
if direction in ['S','W']: decimal = -decimal
return decimal
except: return None
def format_time(t): return f"{t[0:2]}:{t[2:4]}:{t[4:6]}" if len(t)>=6 else t
def format_date(d): return f"{d[0:2]}/{d[2:4]}/20{d[4:6]}" if len(d)>=6 else d
# ==============================
# CLASS Virtual SIM800
# ==============================
class VirtualSIM800:
def send_cmd(self, cmd):
print(">>", cmd)
if cmd=="AT": return "OK"
elif cmd=="AT+CMGF=1": return "OK"
elif cmd.startswith("AT+CMGS"): return "> "
elif cmd.endswith(chr(26)): return "+CMGS: 123\nOK"
else: return "OK"
# ==============================
# MCP2515 (SPI)
# ==============================
class MCP2515:
def __init__(self, spi, cs):
self.spi = spi
self.cs = cs
self.cs.value(1)
def reset(self):
self.cs.value(0)
self.spi.write(bytes([0xC0])) # RESET
self.cs.value(1)
def read(self, reg):
self.cs.value(0)
self.spi.write(bytes([0x03, reg]))
val = self.spi.read(1)
self.cs.value(1)
return val[0]
def write(self, reg, val):
self.cs.value(0)
self.spi.write(bytes([0x02, reg, val]))
self.cs.value(1)
# ==============================
# MPU6050 (I2C)
# ==============================
i2c = I2C(0, scl=Pin(22), sda=Pin(21), freq=400000)
MPU_ADDR = 0x68
i2c.writeto_mem(MPU_ADDR, 0x6B, b'\x00') # sortir du mode sleep
def read_word(reg):
high = i2c.readfrom_mem(MPU_ADDR, reg, 1)[0]
low = i2c.readfrom_mem(MPU_ADDR, reg+1, 1)[0]
val = (high << 8) | low
if val >= 0x8000:
val = -((65535 - val) + 1)
return val
def read_accel():
ax = read_word(0x3B) / 16384.0
ay = read_word(0x3D) / 16384.0
az = read_word(0x3F) / 16384.0
return ax, ay, az
def read_gyro():
gx = read_word(0x43) / 131.0
gy = read_word(0x45) / 131.0
gz = read_word(0x47) / 131.0
return gx, gy, gz
# ==============================
# Initialisation
# ==============================
print("GPS + SIM800L + MCP2515 + MPU6050...")
gps = VirtualGPS() if SIMULATION else UART(2, baudrate=9600, tx=17, rx=16)
sim800 = VirtualSIM800() if SIMULATION else UART(1, baudrate=9600, tx=27, rx=26)
spi = SPI(1, baudrate=1000000, polarity=0, phase=0,
sck=Pin(18), mosi=Pin(23), miso=Pin(19))
cs = Pin(5, Pin.OUT)
mcp = MCP2515(spi, cs)
mcp.reset()
def send_command(cmd):
if SIMULATION:
resp = sim800.send_cmd(cmd)
print("<<", resp)
else:
sim800.write(cmd + "\r\n")
time.sleep(1)
if sim800.any():
print(sim800.read().decode())
# --- Connexion Wi-Fi ---
wifi = network.WLAN(network.STA_IF)
wifi.active(True)
wifi.connect(SSID, PASSWORD)
while not wifi.isconnected():
print("Connexion Wi-Fi en cours...")
time.sleep(1)
print("Connecté au Wi-Fi:", wifi.ifconfig())
# --- Fonction envoi vers ThingSpeak ---
def send_to_thingspeak(lat, lon, speed, ax, ay, az, gx, gy, gz):
try:
url = "https://api.thingspeak.com/update?api_key={}&field1={}&field2={}&field3={}&field4={}&field5={}&field6={}&field7={}&field8={}&field9={}".format(
API_KEY, lat, lon, speed, ax, ay, az, gx, gy, gz
)
response = urequests.get(url)
print("Réponse ThingSpeak:", response.text)
response.close()
except Exception as e:
print("Erreur envoi:", e)
# ==============================
# Boucle principale
# ==============================
while True:
line = gps.read_nmea() if SIMULATION else gps.readline().decode('utf-8')
if "$GPRMC" in line:
parts = line.split(',')
if len(parts)>9 and parts[2]=='A':
lat = convert_to_decimal(parts[3], parts[4])
lon = convert_to_decimal(parts[5], parts[6])
speed = float(parts[7])*1.852
date = format_date(parts[9])
time_utc = format_time(parts[1])
ax, ay, az = read_accel()
gx, gy, gz = read_gyro()
print("Latitude:", lat)
print("Longitude:", lon)
print("Vitesse (km/h):", round(speed,2))
print("Date:", date)
print("Heure UTC:", time_utc)
print("Accélération (g): ax=%.2f ay=%.2f az=%.2f" % (ax, ay, az))
print("Gyroscope (°/s): gx=%.2f gy=%.2f gz=%.2f" % (gx, gy, gz))
print("-------------------")
# --- Envoi SMS via SIM800 ---
send_command("AT")
send_command("AT+CMGF=1")
send_command('AT+CMGS="+21612345678"')
msg = f"GPS: {lat},{lon} | {round(speed,2)} km/h | {date} {time_utc} | Accel: {ax:.2f},{ay:.2f},{az:.2f} | Gyro: {gx:.2f},{gy:.2f},{gz:.2f}"
print(">>", msg)
send_command(msg + chr(26))
# --- Exemple d’écriture CAN ---
mcp.write(0x2A, 0x55) # écrire dans CANCTRL
val = mcp.read(0x0E) # lire CANSTAT
print("CANSTAT:", hex(val))
# --- Envoi vers ThingSpeak ---
# --- Envoi vers ThingSpeak ---
send_to_thingspeak(lat, lon, round(speed,2), ax, ay, az, gx, gy, gz)
time.sleep(15)