From 1df647198b03774e659b7ff6f04a3a8e33c0d48e Mon Sep 17 00:00:00 2001 From: Konstantin Koslowski Date: Wed, 14 Jul 2021 00:54:27 +0200 Subject: [PATCH] rx: initial commit with udp --- .gitignore | 148 +++++++++++++++++++++++++++++++++++++++++++ .pylintrc | 22 +++++++ README.md | 3 + dev-requirements.txt | 1 + micropy.json | 14 ++++ pymakr.conf | 21 ++++++ requirements.txt | 0 src/boot.py | 1 + src/esc.py | 51 +++++++++++++++ src/main.py | 69 ++++++++++++++++++++ src/motor.py | 53 ++++++++++++++++ src/wifi.py | 31 +++++++++ 12 files changed, 414 insertions(+) create mode 100644 .gitignore create mode 100644 .pylintrc create mode 100644 README.md create mode 100644 dev-requirements.txt create mode 100644 micropy.json create mode 100644 pymakr.conf create mode 100644 requirements.txt create mode 100644 src/boot.py create mode 100644 src/esc.py create mode 100644 src/main.py create mode 100644 src/motor.py create mode 100644 src/wifi.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6f37c97 --- /dev/null +++ b/.gitignore @@ -0,0 +1,148 @@ + +# Created by https://www.gitignore.io/api/python,visualstudiocode +# Edit at https://www.gitignore.io/?templates=python,visualstudiocode + +### Python ### +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +### VisualStudioCode ### +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json + +### VisualStudioCode Patch ### +# Ignore all local history of files +.history + +# End of https://www.gitignore.io/api/python,visualstudiocode + +### Micropy Cli ### +.micropy/ +!micropy.json +!src/lib +credentials.py diff --git a/.pylintrc b/.pylintrc new file mode 100644 index 0000000..1091a21 --- /dev/null +++ b/.pylintrc @@ -0,0 +1,22 @@ +[MASTER] +# Loaded Stubs: esp8266-micropython-1.11.0 +init-hook='import sys;sys.path[1:1]=["src/lib",".micropy/BradenM-micropy-stubs-c89b5ef/frozen", ".micropy/BradenM-micropy-stubs-e1b8ce6/frozen", ".micropy/BradenM-micropy-stubs-c89b5ef/stubs", ".micropy/uc-wifi-rx-udp", ]' + +[MESSAGES CONTROL] +# Only show warnings with the listed confidence levels. Leave empty to show +# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED. +confidence= + +# Disable the message, report, category or checker with the given id(s). You +# can either give multiple identifiers separated by comma (,) or put this +# option multiple times (only on the command line, not in the configuration +# file where it should appear only once). You can also use "--disable=all" to +# disable everything first and then reenable specific checks. For example, if +# you want to run only the similarities checker, you can use "--disable=all +# --enable=similarities". If you want to run only the classes checker, but have +# no Warning level messages displayed, use "--disable=all --enable=classes +# --disable=W". + +disable = missing-docstring, line-too-long, trailing-newlines, broad-except, logging-format-interpolation, invalid-name, empty-docstring, + no-method-argument, assignment-from-no-return, too-many-function-args, unexpected-keyword-arg + # the 2nd line deals with the limited information in the generated stubs. diff --git a/README.md b/README.md new file mode 100644 index 0000000..1579fd1 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# uc-wifi-rx-udp + +control two motors with a L298N and receive commands via udp diff --git a/dev-requirements.txt b/dev-requirements.txt new file mode 100644 index 0000000..0e59408 --- /dev/null +++ b/dev-requirements.txt @@ -0,0 +1 @@ +micropy-cli diff --git a/micropy.json b/micropy.json new file mode 100644 index 0000000..2a944f6 --- /dev/null +++ b/micropy.json @@ -0,0 +1,14 @@ +{ + "name": "uc-wifi-rx-udp", + "stubs": { + "esp8266-micropython-1.11.0": "1.2.0" + }, + "dev-packages": { + "micropy-cli": "*" + }, + "packages": {}, + "config": { + "vscode": true, + "pylint": true + } +} diff --git a/pymakr.conf b/pymakr.conf new file mode 100644 index 0000000..f8780b6 --- /dev/null +++ b/pymakr.conf @@ -0,0 +1,21 @@ +{ + "address": "/dev/esp-rx", + "username": "micro", + "password": "python", + "sync_folder": "src", + "open_on_start": true, + "safe_boot_on_upload": false, + "py_ignore": [ + "pymakr.conf", + ".vscode", + ".gitignore", + ".git", + "project.pymakr", + "env", + "venv", + ".python-version", + ".micropy/", + "micropy.json" + ], + "fast_upload": true +} \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..e69de29 diff --git a/src/boot.py b/src/boot.py new file mode 100644 index 0000000..a328c7a --- /dev/null +++ b/src/boot.py @@ -0,0 +1 @@ +# boot.py - - runs on boot-up \ No newline at end of file diff --git a/src/esc.py b/src/esc.py new file mode 100644 index 0000000..4845eff --- /dev/null +++ b/src/esc.py @@ -0,0 +1,51 @@ +from motor import Motor +from time import sleep + +delta = 10 + +class Esc: + def __init__(self, pin_m1_ena, pin_m1_in1, pin_m1_in2, + pin_m2_ena, pin_m2_in1, pin_m2_in2): + self.m1 = Motor("m1", pin_m1_ena, pin_m1_in1, pin_m1_in2) + self.m2 = Motor("m2", pin_m2_ena, pin_m2_in1, pin_m2_in2) + + def fwd(self): + speed = min((self.m1.speed + self.m2.speed)/2 + delta, 100) + self.m1.set_speed(speed) + self.m2.set_speed(speed) + + def rev(self): + speed = max((self.m1.speed + self.m2.speed)/2 - delta, -100) + self.m1.set_speed(speed) + self.m2.set_speed(speed) + + def left(self): + self.m1.dec(delta) + self.m2.inc(delta) + + def right(self): + self.m1.inc(delta) + self.m2.dec(delta) + + # stop + def b1(self): + self.m1.set_speed(0) + self.m2.set_speed(0) + + def b2(self): + if self.m1.speed >= 0: + self.m1.set_speed(0) + self.m2.set_speed(0) + sleep(1) + self.m1.set_speed(-50) + self.m2.set_speed(50) + else: + self.m1.set_speed(0) + self.m2.set_speed(0) + sleep(1) + self.m1.set_speed(50) + self.m2.set_speed(-50) + + def get_status(self): + s = (self.m1.get_status(), self.m2.get_status()) + return s \ No newline at end of file diff --git a/src/main.py b/src/main.py new file mode 100644 index 0000000..2d7f3e3 --- /dev/null +++ b/src/main.py @@ -0,0 +1,69 @@ +# main.py +import machine +import usocket as socket +from time import sleep +from esc import Esc +from wifi import WifiAP +from wifi import WifiSTA +# import web + +PIN_M1_ENA = 5 # D1 +PIN_M1_IN1 = 4 # D2 +PIN_M1_IN2 = 0 # D3 +PIN_M2_IN1 = 12 # D6 +PIN_M2_IN2 = 13 # D7 +PIN_M2_ENA = 15 # D8 + +esc = None + +def main(): + print("main") + global esc + wifi_sta = WifiSTA() + # wifi_ap = WifiAP() + esc = Esc(PIN_M1_ENA, PIN_M1_IN1, PIN_M1_IN2, + PIN_M2_ENA, PIN_M2_IN1, PIN_M2_IN2) + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR, 1) + s.bind(("", 80)) + + while True: + request = "" + try: + request, addr = s.recvfrom(256) + req = request.decode() + + print("data: {}, from: {}".format(req, addr)) + if len(request) == 0: + print("no data") + continue + except: + print("error: no data") + pass + + if "fwd" in req: + print("--> fwd") + esc.fwd() + + elif "left" in req: + print("--> left") + esc.left() + + elif "rev" in req: + print("--> rev") + esc.rev() + + elif "right" in req: + print("--> right") + esc.right() + + elif "b1" in req: + print("--> b1") + esc.b1() + + elif "b2" in req: + print("--> b2") + esc.b2() + +if __name__ == "__main__": + main() diff --git a/src/motor.py b/src/motor.py new file mode 100644 index 0000000..a7192c1 --- /dev/null +++ b/src/motor.py @@ -0,0 +1,53 @@ +import machine +from time import sleep + + +class Motor: + PWM_MAX = 1023 + DIR_FWD = 1 + DIR_REV = 0 + + def __init__(self, name, ena, p1, p2): + self.name = name + self.pin1 = machine.Pin(p1, machine.Pin.OUT) + self.pin2 = machine.Pin(p2, machine.Pin.OUT) + self.pwm = machine.PWM(machine.Pin(ena, machine.Pin.OUT)) + self.pwm.freq(1000) + # state + self.dir = -1 + self.speed = -1 + sleep(1) + # initialize motors + self.set_speed(0) + print(self.get_status()) + + def get_status(self): + s = "[{}:status] pins {},{} duty {}".format(self.name, self.pin1.value(), self.pin2.value(), self.pwm.duty()) + return s + + def set_dir(self, dir): + if self.dir == dir: + return + self.dir = dir + v1 = 1 if dir == self.DIR_FWD else 0 + v2 = 0 if dir == self.DIR_FWD else 1 + self.pin1.value(v1) + self.pin2.value(v2) + + def set_speed(self, speed=100): + print("[{}:set_speed] {} [-100:100]".format(self.name, speed)) + if speed < 0: + self.set_dir(self.DIR_REV) + else: + self.set_dir(self.DIR_FWD) + self.speed = speed + s = int(self.PWM_MAX * abs(speed)/100) + self.pwm.duty(s) + + def inc(self, delta): + speed = min(self.speed + delta, 100) + self.set_speed(speed) + + def dec(self, delta): + speed = max(self.speed - delta, -100) + self.set_speed(speed) \ No newline at end of file diff --git a/src/wifi.py b/src/wifi.py new file mode 100644 index 0000000..e3a9c1f --- /dev/null +++ b/src/wifi.py @@ -0,0 +1,31 @@ +from credentials import * +import network +import time + +address = "192.168.0.1" +netmask = "255.255.255.0" +gateway = "192.168.0.1" +dns = "192.168.0.1" + +if_ap = network.WLAN(network.AP_IF) +if_sta = network.WLAN(network.STA_IF) + +class WifiAP: + def __init__(self): + global if_ap, if_sta + if_sta.active(False) + if_ap.active(True) + if_ap.ifconfig([address, netmask, gateway, dns]) + if_ap.config(essid=SSID, password=PASS) + print("network config {}".format(if_ap.ifconfig())) + +class WifiSTA: + def __init__(self): + global if_ap, if_sta + if_ap.active(False) + if_sta.active(True) + if_sta.connect(SSID, PASS) + while not if_sta.isconnected(): + pass + time.sleep(0.1) + print("network config {}".format(if_sta.ifconfig())) \ No newline at end of file