Add FW update functionality
* refactor code
This commit is contained in:
parent
51f979f90e
commit
fc11ffdad4
14
Makefile
14
Makefile
@ -1,8 +1,18 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
#SERIAL_PORT=/dev/ttyUSB0
|
SERIAL_PORT=/dev/ttyUSB0
|
||||||
|
|
||||||
|
ifeq (,$(wildcard $(SERIAL_PORT)))
|
||||||
|
SERIAL_PORT=/dev/tty.usbserial-1410
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq (,$(wildcard $(SERIAL_PORT)))
|
||||||
SERIAL_PORT=/dev/tty.usbserial-1420
|
SERIAL_PORT=/dev/tty.usbserial-1420
|
||||||
#SERIAL_PORT=/dev/tty.SLAB_USBtoUART
|
endif
|
||||||
|
|
||||||
|
ifeq (,$(wildcard $(SERIAL_PORT)))
|
||||||
|
SERIAL_PORT=/dev/tty.SLAB_USBtoUART
|
||||||
|
endif
|
||||||
|
|
||||||
all: flash delay config update reset
|
all: flash delay config update reset
|
||||||
|
|
||||||
|
34
boot.py
34
boot.py
@ -1,5 +1,33 @@
|
|||||||
|
import os
|
||||||
|
import machine
|
||||||
from utime import sleep_ms
|
from utime import sleep_ms
|
||||||
|
|
||||||
# Give time to cancel boot script
|
# Give time to cancel this boot script
|
||||||
print("Press Ctrl-C to stop boot script...")
|
print("Press Ctrl-C to stop new boot script...")
|
||||||
sleep_ms(500)
|
sleep_ms(1000)
|
||||||
|
|
||||||
|
root_files = os.listdir()
|
||||||
|
update_files = ['boot.py.new', 'main.py.new', 'hal.py.new']
|
||||||
|
files_to_update = []
|
||||||
|
|
||||||
|
# Check for FW updates and verify new FW files
|
||||||
|
for file in update_files:
|
||||||
|
if file in root_files:
|
||||||
|
print("boot.py: trying to update " + file)
|
||||||
|
# Try to load the user code
|
||||||
|
try:
|
||||||
|
with open(file, 'r') as code:
|
||||||
|
compile(code.read(), "snippet", 'exec')
|
||||||
|
files_to_update.append(file)
|
||||||
|
except:
|
||||||
|
print("boot.py: " + file + " compilation failed")
|
||||||
|
files_to_update.clear()
|
||||||
|
break
|
||||||
|
|
||||||
|
# If valid updates replace with new FW
|
||||||
|
for file in files_to_update:
|
||||||
|
os.rename(file, file.replace('.new', ''))
|
||||||
|
|
||||||
|
# If updates, reboot to load new FW
|
||||||
|
if len(files_to_update) != 0:
|
||||||
|
machine.reset()
|
||||||
|
48
hal.py
48
hal.py
@ -34,7 +34,7 @@ class Sumorobot(object):
|
|||||||
# LED sensor feedback
|
# LED sensor feedback
|
||||||
self.sensor_feedback = True
|
self.sensor_feedback = True
|
||||||
# Bottom status LED
|
# Bottom status LED
|
||||||
self.status_led = Pin(self.config["status_led_pin"], Pin.OUT)
|
self.status_led = Pin(self.config['status_led_pin'], Pin.OUT)
|
||||||
# Bottom status LED is in reverse polarity
|
# Bottom status LED is in reverse polarity
|
||||||
self.status_led.value(1)
|
self.status_led.value(1)
|
||||||
# Sensor LEDs
|
# Sensor LEDs
|
||||||
@ -96,7 +96,7 @@ class Sumorobot(object):
|
|||||||
# When the SumoRobot is not moving
|
# When the SumoRobot is not moving
|
||||||
if self.prev_speed[LEFT] == 0 and self.prev_speed[RIGHT] == 0:
|
if self.prev_speed[LEFT] == 0 and self.prev_speed[RIGHT] == 0:
|
||||||
# Calculate battery voltage
|
# Calculate battery voltage
|
||||||
battery_voltage = round(self.config["battery_coeff"] * (self.adc_battery.read() * 3.3 / 4096), 2)
|
battery_voltage = round(self.config['battery_coeff'] * (self.adc_battery.read() * 3.3 / 4096), 2)
|
||||||
# Map battery voltage to percentage
|
# Map battery voltage to percentage
|
||||||
temp_battery_level = 0.0 + ((100.0 - 0.0) / (4.2 - 3.2)) * (battery_voltage - 3.2)
|
temp_battery_level = 0.0 + ((100.0 - 0.0) / (4.2 - 3.2)) * (battery_voltage - 3.2)
|
||||||
# When battery level changed more than 5 percent
|
# When battery level changed more than 5 percent
|
||||||
@ -122,7 +122,7 @@ class Sumorobot(object):
|
|||||||
# Get the sonar value
|
# Get the sonar value
|
||||||
self.sonar_value = self.get_sonar_value()
|
self.sonar_value = self.get_sonar_value()
|
||||||
# When the sonar value is small and the ping actually returned
|
# When the sonar value is small and the ping actually returned
|
||||||
if self.sonar_value < self.config["sonar_threshold"] and self.sonar_value > 0:
|
if self.sonar_value < self.config['sonar_threshold'] and self.sonar_value > 0:
|
||||||
# When not maximum score
|
# When not maximum score
|
||||||
if self.sonar_score < 5:
|
if self.sonar_score < 5:
|
||||||
# Increase the sonar score
|
# Increase the sonar score
|
||||||
@ -145,15 +145,15 @@ class Sumorobot(object):
|
|||||||
# Function to update the config file
|
# Function to update the config file
|
||||||
def update_config_file(self):
|
def update_config_file(self):
|
||||||
# Update the config file
|
# Update the config file
|
||||||
with open("config.part", "w") as config_file:
|
with open('config.part', 'w') as config_file:
|
||||||
config_file.write(ujson.dumps(self.config))
|
config_file.write(ujson.dumps(self.config))
|
||||||
os.rename("config.part", "config.json")
|
os.rename('config.part', 'config.json')
|
||||||
|
|
||||||
# Function to update line calibration and write it to the config file
|
# Function to update line calibration and write it to the config file
|
||||||
def calibrate_line_values(self):
|
def calibrate_line_values(self):
|
||||||
# Read the line sensor values
|
# Read the line sensor values
|
||||||
self.config["left_line_value"] = self.adc_line_left.read()
|
self.config['left_line_value'] = self.adc_line_left.read()
|
||||||
self.config["right_line_value"] = self.adc_line_right.read()
|
self.config['right_line_value'] = self.adc_line_right.read()
|
||||||
|
|
||||||
# Function to get light inensity from the phototransistors
|
# Function to get light inensity from the phototransistors
|
||||||
def get_line(self, line):
|
def get_line(self, line):
|
||||||
@ -173,9 +173,9 @@ class Sumorobot(object):
|
|||||||
# Define feedback LED
|
# Define feedback LED
|
||||||
led = LEFT_LINE if line == LEFT else RIGHT_LINE
|
led = LEFT_LINE if line == LEFT else RIGHT_LINE
|
||||||
# Define config prefix
|
# Define config prefix
|
||||||
prefix = "left" if line == LEFT else "right"
|
prefix = 'left' if line == LEFT else 'right'
|
||||||
# Check for line
|
# Check for line
|
||||||
value = abs(self.get_line(line) - self.config[prefix + "_line_value"]) > self.config[prefix + "_line_threshold"]
|
value = abs(self.get_line(line) - self.config[prefix + '_line_value']) > self.config[prefix + '_line_threshold']
|
||||||
# Show LED feedback
|
# Show LED feedback
|
||||||
self.set_led(led, value)
|
self.set_led(led, value)
|
||||||
# Update last line direction if line was detected
|
# Update last line direction if line was detected
|
||||||
@ -201,10 +201,10 @@ class Sumorobot(object):
|
|||||||
self.pwm[servo].duty(0)
|
self.pwm[servo].duty(0)
|
||||||
else:
|
else:
|
||||||
# Define config prefix
|
# Define config prefix
|
||||||
prefix = "left" if servo == LEFT else "right"
|
prefix = 'left' if servo == LEFT else 'right'
|
||||||
# -100 ... 100 to min_tuning .. max_tuning
|
# -100 ... 100 to min_tuning .. max_tuning
|
||||||
min_tuning = self.config[prefix + "_servo_min_tuning"]
|
min_tuning = self.config[prefix + '_servo_min_tuning']
|
||||||
max_tuning = self.config[prefix + "_servo_max_tuning"]
|
max_tuning = self.config[prefix + '_servo_max_tuning']
|
||||||
self.pwm[servo].duty(int((speed + 100) / 200 * (max_tuning - min_tuning) + min_tuning))
|
self.pwm[servo].duty(int((speed + 100) / 200 * (max_tuning - min_tuning) + min_tuning))
|
||||||
|
|
||||||
def move(self, dir):
|
def move(self, dir):
|
||||||
@ -251,20 +251,20 @@ class Sumorobot(object):
|
|||||||
|
|
||||||
def get_sensor_scope(self):
|
def get_sensor_scope(self):
|
||||||
# TODO: implement sensor value caching
|
# TODO: implement sensor value caching
|
||||||
return str(self.get_sonar_value()) + ',' + \
|
return str(self.get_sonar_value()) + ',' \
|
||||||
str(self.get_line(LEFT)) + ',' + \
|
+ str(self.get_line(LEFT)) + ',' \
|
||||||
str(self.get_line(RIGHT)) + ',' + \
|
+ str(self.get_line(RIGHT)) + ',' \
|
||||||
str(self.bat_charge.value()) + ',' + \
|
+ str(self.bat_charge.value()) + ',' \
|
||||||
str(self.get_battery_level())
|
+ str(self.get_battery_level())
|
||||||
|
|
||||||
def get_configuration_scope(self):
|
def get_configuration_scope(self):
|
||||||
return str(self.config["sumorobot_name"]) + ',' + \
|
return str(self.config['sumorobot_name']) + ',' \
|
||||||
str(self.config["firmware_version"]) + ',' + \
|
+ str(self.config['firmware_version']) + ',' \
|
||||||
str(self.config["left_line_value"]) + ',' + \
|
+ str(self.config['left_line_value']) + ',' \
|
||||||
str(self.config["right_line_value"]) + ',' + \
|
+ str(self.config['right_line_value']) + ',' \
|
||||||
str(self.config["left_line_threshold"]) + ',' + \
|
+ str(self.config['left_line_threshold']) + ',' \
|
||||||
str(self.config["right_line_threshold"]) + ',' + \
|
+ str(self.config['right_line_threshold']) + ',' \
|
||||||
str(self.config["sonar_threshold"])
|
+ str(self.config['sonar_threshold'])
|
||||||
|
|
||||||
def sleep(self, delay):
|
def sleep(self, delay):
|
||||||
# Check for valid delay
|
# Check for valid delay
|
||||||
|
15
main.py
15
main.py
@ -1,4 +1,3 @@
|
|||||||
import os
|
|
||||||
import ujson
|
import ujson
|
||||||
import struct
|
import struct
|
||||||
import _thread
|
import _thread
|
||||||
@ -15,7 +14,7 @@ _IRQ_CENTRAL_DISCONNECT = const(2)
|
|||||||
_IRQ_GATTS_READ_REQUEST = const(4)
|
_IRQ_GATTS_READ_REQUEST = const(4)
|
||||||
|
|
||||||
# Open and parse the config file
|
# Open and parse the config file
|
||||||
with open("config.json", "r") as config_file:
|
with open('config.json', 'r') as config_file:
|
||||||
config = ujson.load(config_file)
|
config = ujson.load(config_file)
|
||||||
|
|
||||||
# Initialize the SumoRobot object
|
# Initialize the SumoRobot object
|
||||||
@ -48,7 +47,7 @@ def process():
|
|||||||
|
|
||||||
# Try to execute the Python code
|
# Try to execute the Python code
|
||||||
try:
|
try:
|
||||||
python_code = compile(python_code, "snippet", "exec")
|
python_code = compile(python_code, "snippet", 'exec')
|
||||||
exec(python_code)
|
exec(python_code)
|
||||||
except:
|
except:
|
||||||
print("main.py: the code sent had errors")
|
print("main.py: the code sent had errors")
|
||||||
@ -108,19 +107,19 @@ def ble_handler(event, data):
|
|||||||
temp_python_code += cmd
|
temp_python_code += cmd
|
||||||
else:
|
else:
|
||||||
temp_python_code = b''
|
temp_python_code = b''
|
||||||
print('main.py: unknown cmd=', cmd)
|
print("main.py: unknown cmd=" + cmd)
|
||||||
|
|
||||||
conn_handle = None
|
conn_handle = None
|
||||||
temp_python_code = b''
|
temp_python_code = b''
|
||||||
python_code = b''
|
python_code = b''
|
||||||
|
|
||||||
# When user code (code.py) exists
|
# When user code (code.py) exists
|
||||||
if 'code.py' in os.listdir():
|
if 'code.py' in root_files:
|
||||||
print('main.py: trying to load code.py')
|
print("main.py: trying to load code.py")
|
||||||
# Try to load the user code
|
# Try to load the user code
|
||||||
try:
|
try:
|
||||||
with open("code.py", "r") as code:
|
with open('code.py', 'r') as code:
|
||||||
python_code = compile(code.read(), "snippet", "exec")
|
python_code = compile(code.read(), "snippet", 'exec')
|
||||||
except:
|
except:
|
||||||
print("main.py: code.py compilation failed")
|
print("main.py: code.py compilation failed")
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user