From bea1220d8aab84fb672bc5222d702c06d183c850 Mon Sep 17 00:00:00 2001 From: Silver Kuusik Date: Sun, 10 Feb 2019 21:07:38 +0100 Subject: [PATCH] add code loading feature --- config.json | 2 +- hal.py | 58 ++++++++++++++++++++++++++++++++-- main.py | 89 +++++++++++++++++++++++++---------------------------- 3 files changed, 99 insertions(+), 50 deletions(-) diff --git a/config.json b/config.json index 4e95649..61dbd7f 100755 --- a/config.json +++ b/config.json @@ -2,7 +2,7 @@ "status_led_pin": 22, "battery_coeff": 2.25, "sumo_id": "xxxxxxxx", - "firmware_version": "0.3.3", + "firmware_version": "0.4.0", "left_servo_tuning": 33, "right_servo_tuning": 33, "ultrasonic_distance": 40, diff --git a/hal.py b/hal.py index 6210bb6..7164228 100755 --- a/hal.py +++ b/hal.py @@ -31,6 +31,8 @@ class Sumorobot(object): self.pwm_left = PWM(Pin(15), freq=50, duty=0) self.pwm_right = PWM(Pin(4), freq=50, duty=0) + # LED sensor feedback + self.sensor_feedback = True # Bottom status LED self.status_led = Pin(self.config["status_led_pin"], Pin.OUT) # Bottom status LED is in reverse polarity @@ -40,6 +42,17 @@ class Sumorobot(object): self.left_line_led = Pin(17, Pin.OUT) self.right_line_led = Pin(12, Pin.OUT) + # Scope with sensor data + self.sensor_scope = dict() + + # WiFi connection + self.is_wifi_connected = False + + # Python and Blockly code + self.python_code = "" + self.blockly_code = "" + self.compiled_python_code = "" + # Battery gauge self.bat_status = 4.3 self.move_counter = 0 @@ -151,9 +164,9 @@ class Sumorobot(object): with open("config.part", "w") as config_file: config_file.write(ujson.dumps(self.config)) os.rename("config.part", "config.json") - + # Function to update line threshold calibration and write it to the config file - def calibrate_line_threshold(self, value): + def set_line_threshold(self, value): # Read the line sensor values self.config["left_line_threshold"] = value self.config["right_line_threshold"] = value @@ -257,6 +270,47 @@ class Sumorobot(object): self.set_servo(LEFT, -100) self.set_servo(RIGHT, 100) + def update_sensor_feedback(self): + if self.sensor_feedback: + # Execute to see LED feedback for sensors + self.is_opponent() + self.is_line(LEFT) + self.is_line(RIGHT) + + def update_sensor_scope(self): + self.sensor_scope = dict( + left_line = self.get_line(LEFT), + right_line = self.get_line(RIGHT), + opponent = self.get_opponent_distance(), + battery_voltage = self.get_battery_voltage() + ) + + def get_python_code(self): + return dict( + type = "python_code", + val = self.python_code + ) + + def get_blockly_code(self): + return dict( + type = "blockly_code", + val = self.blockly_code + ) + + def get_sensor_scope(self): + temp = self.sensor_scope + temp['type'] = "sensor_scope" + return temp + + def get_line_scope(self): + return dict( + type = "line_scope", + left_line_value = self.config["left_line_value"], + right_line_value = self.config["right_line_value"], + left_line_threshold = self.config["left_line_threshold"], + right_line_threshold = self.config["right_line_threshold"] + ) + def sleep(self, delay): # Check for valid delay assert delay > 0 diff --git a/main.py b/main.py index 27ca974..eb26461 100755 --- a/main.py +++ b/main.py @@ -2,33 +2,15 @@ import _thread import ubinascii import uwebsockets -# Code to execute -ast = "" -# Scope, info to be sent to the client -scope = dict() - def step(): - global scope - while True: # Execute to see LED feedback for sensors - sumorobot.is_opponent() - sumorobot.is_line(LEFT) - sumorobot.is_line(RIGHT) - # Update scope - scope = dict( - left_line = sumorobot.get_line(LEFT), - right_line = sumorobot.get_line(RIGHT), - opponent = sumorobot.get_opponent_distance(), - battery_voltage = sumorobot.get_battery_voltage(), - left_line_value = sumorobot.config["left_line_value"], - right_line_value = sumorobot.config["right_line_value"], - left_line_threshold = sumorobot.config["left_line_threshold"], - right_line_threshold = sumorobot.config["right_line_threshold"] - ) - # Execute code + sumorobot.update_sensor_feedback() + # Update sensor scope + sumorobot.update_sensor_scope() + # Try to execute the Python code try: - exec(ast) + exec(sumorobot.compiled_python_code) except: pass # When robot was stopped @@ -41,19 +23,16 @@ def step(): sleep_ms(50) def ws_handler(): - global ast - global has_wifi_connection - while True: # When WiFi has just been reconnected - if wlan.isconnected() and not has_wifi_connection: + if wlan.isconnected() and not sumorobot.is_wifi_connected: #conn = uwebsockets.connect(url) sumorobot.set_led(STATUS, True) - has_wifi_connection = True + sumorobot.is_wifi_connected = True # When WiFi has just been disconnected - elif not wlan.isconnected() and has_wifi_connection: + elif not wlan.isconnected() and sumorobot.is_wifi_connected: sumorobot.set_led(STATUS, False) - has_wifi_connection = False + sumorobot.is_wifi_connected = False elif not wlan.isconnected(): # Continue to wait for a WiFi connection continue @@ -69,36 +48,50 @@ def ws_handler(): # Continue to receive data continue elif b'forward' in data: - ast = "" + sumorobot.compiled_python_code = "" sumorobot.move(FORWARD) elif b'backward' in data: - ast = "" + sumorobot.compiled_python_code = "" sumorobot.move(BACKWARD) elif b'right' in data: - ast = "" + sumorobot.compiled_python_code = "" sumorobot.move(RIGHT) elif b'left' in data: - ast = "" + sumorobot.compiled_python_code = "" sumorobot.move(LEFT) - elif b'ping' in data: - conn.send(repr(scope).replace("'", '"')) - elif b'code' in data: - data = ujson.loads(data) - data['val'] = data['val'].replace(";;", "\n") - #print("main.py code=", data['val']) - ast = compile(data['val'], "snippet", "exec") elif b'stop' in data: - ast = "" + sumorobot.compiled_python_code = "" sumorobot.move(STOP) # for terminating delays in code sumorobot.terminate = True + elif b'get_line_scope' in data: + conn.send(ujson.dumps(sumorobot.get_line_scope())) + elif b'get_sensor_scope' in data: + conn.send(ujson.dumps(sumorobot.get_sensor_scope())) + elif b'get_python_code' in data: + print(sumorobot.get_python_code()) + conn.send(ujson.dumps(sumorobot.get_python_code())) + elif b'get_blockly_code' in data: + print(sumorobot.get_blockly_code()) + conn.send(ujson.dumps(sumorobot.get_blockly_code())) + elif b'set_blockly_code' in data: + data = ujson.loads(data) + print(data) + sumorobot.blockly_code = data['val'] + elif b'set_python_code' in data: + data = ujson.loads(data) + print(data) + sumorobot.python_code = data['val'] + data['val'] = data['val'].replace(";;", "\n") + #print("main.py code=", data['val']) + sumorobot.compiled_python_code = compile(data['val'], "snippet", "exec") elif b'calibrate_line_value' in data: sumorobot.calibrate_line_value() #print('main.py: calibrate_line_value') - elif b'calibrate_line_threshold' in data: + elif b'set_line_threshold' in data: data = ujson.loads(data) - sumorobot.calibrate_line_threshold(int(data['val'])) - #print('main.py: calibrate_line_threshold') + sumorobot.set_line_threshold(int(data['val'])) + #print('main.py: set_line_threshold') elif b'Gone' in data: print("main.py: server said 410 Gone, attempting to reconnect...") #conn = uwebsockets.connect(url) @@ -108,7 +101,9 @@ def ws_handler(): # Try to load the user code try: with open("code.py", "r") as code: - ast = compile(code.read(), "snippet", "exec") + temp = code.read() + sumorobot.python_code = temp + sumorobot.compiled_python_code = compile(temp, "snippet", "exec") except: print("main.py: error loading code.py file") @@ -130,7 +125,7 @@ conn.settimeout(1) timer.deinit() # WiFi is connected -has_wifi_connection = True +sumorobot.is_wifi_connected = True # Indicate that the WebSocket is connected sumorobot.set_led(STATUS, True)