├── GUI
├── IP.txt
├── requirements.txt
├── Instruction.txt
└── logo.png
├── .gitignore
├── client
├── IP.txt
├── requirements.txt
├── Instruction.txt
└── logo.png
├── config.json
├── server
├── dist
│ ├── robots.txt
│ ├── img
│ │ ├── bg.jpg
│ │ └── icons
│ │ │ ├── logo.png
│ │ │ ├── favicon.ico
│ │ │ ├── favicon-32x32 .png
│ │ │ └── safari-pinned-tab.svg
│ ├── favicon.ico
│ ├── fonts
│ │ ├── roboto-latin-100.5cb7edfc.woff
│ │ ├── roboto-latin-100.7370c367.woff2
│ │ ├── roboto-latin-300.b00849e0.woff
│ │ ├── roboto-latin-300.ef7c6637.woff2
│ │ ├── roboto-latin-400.479970ff.woff2
│ │ ├── roboto-latin-400.60fa3c06.woff
│ │ ├── roboto-latin-500.020c97dc.woff2
│ │ ├── roboto-latin-500.87284894.woff
│ │ ├── roboto-latin-700.2735a3a6.woff2
│ │ ├── roboto-latin-700.adcde98f.woff
│ │ ├── roboto-latin-900.9b3766ef.woff2
│ │ ├── roboto-latin-900.bb1e4dc6.woff
│ │ ├── roboto-latin-100italic.f8b1df51.woff2
│ │ ├── roboto-latin-100italic.f9e8e590.woff
│ │ ├── roboto-latin-300italic.14286f3b.woff2
│ │ ├── roboto-latin-300italic.4df32891.woff
│ │ ├── roboto-latin-400italic.51521a2a.woff2
│ │ ├── roboto-latin-400italic.fe65b833.woff
│ │ ├── roboto-latin-500italic.288ad9c6.woff
│ │ ├── roboto-latin-500italic.db4a2a23.woff2
│ │ ├── roboto-latin-700italic.81f57861.woff
│ │ ├── roboto-latin-700italic.da0e7178.woff2
│ │ ├── roboto-latin-900italic.28f91510.woff
│ │ ├── roboto-latin-900italic.ebf6d164.woff2
│ │ ├── materialdesignicons-webfont.2d0a0d8f.eot
│ │ ├── materialdesignicons-webfont.b4917be2.woff
│ │ ├── materialdesignicons-webfont.d0066537.woff2
│ │ └── materialdesignicons-webfont.f5111234.ttf
│ ├── manifest.json
│ ├── service-worker.js
│ ├── index.html
│ ├── precache-manifest.a14d08d959aeaa21de5cdb2a57fec282.js
│ └── css
│ │ └── app.5a950261.css
├── requirements.txt
├── ultra.py
├── trackingMoudle.py
├── switch.py
├── info.py
├── Kalman_filter.py
├── PID.py
├── findline.py
├── LEDapp.py
├── app.py
├── OLED.py
├── Instruction.txt
├── LED.py
├── config.txt
├── base_camera.py
├── move.py
├── functions.py
├── servo.py
├── appserverAP.py
├── FPV.py
├── appserver.py
├── RPIservo.py
├── server.py
├── webServer.py
├── raspi-config.py
└── robotLight.py
├── images
├── App1.jpg
├── App2.jpg
├── putty.png
├── winSSH.png
├── configSSH.png
├── imagerUse.png
├── mermaid.png
├── RPiDownload.png
├── configWIFI.png
├── webControl.png
└── imagerDownload.png
├── initPosServos.py
├── LICENSE
├── autorun.py
├── wifi_hotspot_manager.sh
├── instruction.txt
└── setup.py
/GUI/IP.txt:
--------------------------------------------------------------------------------
1 | IP:192.168.3.242
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | venv
2 | .idea
3 |
--------------------------------------------------------------------------------
/client/IP.txt:
--------------------------------------------------------------------------------
1 | IP:192.168.3.242
--------------------------------------------------------------------------------
/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "production": true
3 | }
4 |
--------------------------------------------------------------------------------
/GUI/requirements.txt:
--------------------------------------------------------------------------------
1 | opencv-python
2 | zmq
3 | numpy
--------------------------------------------------------------------------------
/client/requirements.txt:
--------------------------------------------------------------------------------
1 | opencv-python
2 | zmq
3 | numpy
--------------------------------------------------------------------------------
/server/dist/robots.txt:
--------------------------------------------------------------------------------
1 | User-agent: *
2 | Disallow:
3 |
--------------------------------------------------------------------------------
/GUI/Instruction.txt:
--------------------------------------------------------------------------------
1 | for more information:
2 | www.adeept.com
3 |
--------------------------------------------------------------------------------
/client/Instruction.txt:
--------------------------------------------------------------------------------
1 | for more information:
2 | www.adeept.com
3 |
--------------------------------------------------------------------------------
/GUI/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adeept/Adeept_RaspTank/HEAD/GUI/logo.png
--------------------------------------------------------------------------------
/client/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adeept/Adeept_RaspTank/HEAD/client/logo.png
--------------------------------------------------------------------------------
/images/App1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adeept/Adeept_RaspTank/HEAD/images/App1.jpg
--------------------------------------------------------------------------------
/images/App2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adeept/Adeept_RaspTank/HEAD/images/App2.jpg
--------------------------------------------------------------------------------
/images/putty.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adeept/Adeept_RaspTank/HEAD/images/putty.png
--------------------------------------------------------------------------------
/images/winSSH.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adeept/Adeept_RaspTank/HEAD/images/winSSH.png
--------------------------------------------------------------------------------
/images/configSSH.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adeept/Adeept_RaspTank/HEAD/images/configSSH.png
--------------------------------------------------------------------------------
/images/imagerUse.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adeept/Adeept_RaspTank/HEAD/images/imagerUse.png
--------------------------------------------------------------------------------
/images/mermaid.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adeept/Adeept_RaspTank/HEAD/images/mermaid.png
--------------------------------------------------------------------------------
/images/RPiDownload.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adeept/Adeept_RaspTank/HEAD/images/RPiDownload.png
--------------------------------------------------------------------------------
/images/configWIFI.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adeept/Adeept_RaspTank/HEAD/images/configWIFI.png
--------------------------------------------------------------------------------
/images/webControl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adeept/Adeept_RaspTank/HEAD/images/webControl.png
--------------------------------------------------------------------------------
/server/dist/img/bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adeept/Adeept_RaspTank/HEAD/server/dist/img/bg.jpg
--------------------------------------------------------------------------------
/images/imagerDownload.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adeept/Adeept_RaspTank/HEAD/images/imagerDownload.png
--------------------------------------------------------------------------------
/server/dist/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adeept/Adeept_RaspTank/HEAD/server/dist/favicon.ico
--------------------------------------------------------------------------------
/server/dist/img/icons/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adeept/Adeept_RaspTank/HEAD/server/dist/img/icons/logo.png
--------------------------------------------------------------------------------
/server/dist/img/icons/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adeept/Adeept_RaspTank/HEAD/server/dist/img/icons/favicon.ico
--------------------------------------------------------------------------------
/server/dist/img/icons/favicon-32x32 .png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adeept/Adeept_RaspTank/HEAD/server/dist/img/icons/favicon-32x32 .png
--------------------------------------------------------------------------------
/server/dist/fonts/roboto-latin-100.5cb7edfc.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adeept/Adeept_RaspTank/HEAD/server/dist/fonts/roboto-latin-100.5cb7edfc.woff
--------------------------------------------------------------------------------
/server/dist/fonts/roboto-latin-100.7370c367.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adeept/Adeept_RaspTank/HEAD/server/dist/fonts/roboto-latin-100.7370c367.woff2
--------------------------------------------------------------------------------
/server/dist/fonts/roboto-latin-300.b00849e0.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adeept/Adeept_RaspTank/HEAD/server/dist/fonts/roboto-latin-300.b00849e0.woff
--------------------------------------------------------------------------------
/server/dist/fonts/roboto-latin-300.ef7c6637.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adeept/Adeept_RaspTank/HEAD/server/dist/fonts/roboto-latin-300.ef7c6637.woff2
--------------------------------------------------------------------------------
/server/dist/fonts/roboto-latin-400.479970ff.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adeept/Adeept_RaspTank/HEAD/server/dist/fonts/roboto-latin-400.479970ff.woff2
--------------------------------------------------------------------------------
/server/dist/fonts/roboto-latin-400.60fa3c06.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adeept/Adeept_RaspTank/HEAD/server/dist/fonts/roboto-latin-400.60fa3c06.woff
--------------------------------------------------------------------------------
/server/dist/fonts/roboto-latin-500.020c97dc.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adeept/Adeept_RaspTank/HEAD/server/dist/fonts/roboto-latin-500.020c97dc.woff2
--------------------------------------------------------------------------------
/server/dist/fonts/roboto-latin-500.87284894.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adeept/Adeept_RaspTank/HEAD/server/dist/fonts/roboto-latin-500.87284894.woff
--------------------------------------------------------------------------------
/server/dist/fonts/roboto-latin-700.2735a3a6.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adeept/Adeept_RaspTank/HEAD/server/dist/fonts/roboto-latin-700.2735a3a6.woff2
--------------------------------------------------------------------------------
/server/dist/fonts/roboto-latin-700.adcde98f.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adeept/Adeept_RaspTank/HEAD/server/dist/fonts/roboto-latin-700.adcde98f.woff
--------------------------------------------------------------------------------
/server/dist/fonts/roboto-latin-900.9b3766ef.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adeept/Adeept_RaspTank/HEAD/server/dist/fonts/roboto-latin-900.9b3766ef.woff2
--------------------------------------------------------------------------------
/server/dist/fonts/roboto-latin-900.bb1e4dc6.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adeept/Adeept_RaspTank/HEAD/server/dist/fonts/roboto-latin-900.bb1e4dc6.woff
--------------------------------------------------------------------------------
/server/dist/fonts/roboto-latin-100italic.f8b1df51.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adeept/Adeept_RaspTank/HEAD/server/dist/fonts/roboto-latin-100italic.f8b1df51.woff2
--------------------------------------------------------------------------------
/server/dist/fonts/roboto-latin-100italic.f9e8e590.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adeept/Adeept_RaspTank/HEAD/server/dist/fonts/roboto-latin-100italic.f9e8e590.woff
--------------------------------------------------------------------------------
/server/dist/fonts/roboto-latin-300italic.14286f3b.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adeept/Adeept_RaspTank/HEAD/server/dist/fonts/roboto-latin-300italic.14286f3b.woff2
--------------------------------------------------------------------------------
/server/dist/fonts/roboto-latin-300italic.4df32891.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adeept/Adeept_RaspTank/HEAD/server/dist/fonts/roboto-latin-300italic.4df32891.woff
--------------------------------------------------------------------------------
/server/dist/fonts/roboto-latin-400italic.51521a2a.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adeept/Adeept_RaspTank/HEAD/server/dist/fonts/roboto-latin-400italic.51521a2a.woff2
--------------------------------------------------------------------------------
/server/dist/fonts/roboto-latin-400italic.fe65b833.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adeept/Adeept_RaspTank/HEAD/server/dist/fonts/roboto-latin-400italic.fe65b833.woff
--------------------------------------------------------------------------------
/server/dist/fonts/roboto-latin-500italic.288ad9c6.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adeept/Adeept_RaspTank/HEAD/server/dist/fonts/roboto-latin-500italic.288ad9c6.woff
--------------------------------------------------------------------------------
/server/dist/fonts/roboto-latin-500italic.db4a2a23.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adeept/Adeept_RaspTank/HEAD/server/dist/fonts/roboto-latin-500italic.db4a2a23.woff2
--------------------------------------------------------------------------------
/server/dist/fonts/roboto-latin-700italic.81f57861.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adeept/Adeept_RaspTank/HEAD/server/dist/fonts/roboto-latin-700italic.81f57861.woff
--------------------------------------------------------------------------------
/server/dist/fonts/roboto-latin-700italic.da0e7178.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adeept/Adeept_RaspTank/HEAD/server/dist/fonts/roboto-latin-700italic.da0e7178.woff2
--------------------------------------------------------------------------------
/server/dist/fonts/roboto-latin-900italic.28f91510.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adeept/Adeept_RaspTank/HEAD/server/dist/fonts/roboto-latin-900italic.28f91510.woff
--------------------------------------------------------------------------------
/server/dist/fonts/roboto-latin-900italic.ebf6d164.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adeept/Adeept_RaspTank/HEAD/server/dist/fonts/roboto-latin-900italic.ebf6d164.woff2
--------------------------------------------------------------------------------
/server/dist/fonts/materialdesignicons-webfont.2d0a0d8f.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adeept/Adeept_RaspTank/HEAD/server/dist/fonts/materialdesignicons-webfont.2d0a0d8f.eot
--------------------------------------------------------------------------------
/server/dist/fonts/materialdesignicons-webfont.b4917be2.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adeept/Adeept_RaspTank/HEAD/server/dist/fonts/materialdesignicons-webfont.b4917be2.woff
--------------------------------------------------------------------------------
/server/dist/fonts/materialdesignicons-webfont.d0066537.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adeept/Adeept_RaspTank/HEAD/server/dist/fonts/materialdesignicons-webfont.d0066537.woff2
--------------------------------------------------------------------------------
/server/dist/fonts/materialdesignicons-webfont.f5111234.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adeept/Adeept_RaspTank/HEAD/server/dist/fonts/materialdesignicons-webfont.f5111234.ttf
--------------------------------------------------------------------------------
/server/requirements.txt:
--------------------------------------------------------------------------------
1 | adafruit-pca9685
2 | rpi_ws281x
3 | mpu6050-raspberrypi
4 | flask
5 | flask_cors
6 | websockets
7 | numpy
8 | opencv-contrib-python==3.4.3.18
9 | imutils
10 | zmq
11 | pybase64
12 | psutil
13 | luma.oled
14 |
--------------------------------------------------------------------------------
/initPosServos.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # File name : init
3 | # Description : Control Servos
4 | # Author : William
5 | # Date : 2019/02/23
6 | import time
7 | import Adafruit_PCA9685
8 |
9 | pwm = Adafruit_PCA9685.PCA9685()
10 | pwm.set_pwm_freq(50)
11 |
12 | while 1:
13 | pwm.set_all_pwm(0, 300)
14 | time.sleep(1)
--------------------------------------------------------------------------------
/server/dist/manifest.json:
--------------------------------------------------------------------------------
1 | {"name":"adeept_bot_controller_web","short_name":"adeept_bot_controller_web","theme_color":"#4DBA87","icons":[{"src":"./img/icons/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"./img/icons/android-chrome-512x512.png","sizes":"512x512","type":"image/png"},{"src":"./img/icons/android-chrome-maskable-192x192.png","sizes":"192x192","type":"image/png","purpose":"maskable"},{"src":"./img/icons/android-chrome-maskable-512x512.png","sizes":"512x512","type":"image/png","purpose":"maskable"}],"start_url":".","display":"standalone","background_color":"#000000"}
--------------------------------------------------------------------------------
/server/ultra.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python3
2 | # File name : Ultrasonic.py
3 | # Description : Detection distance and tracking with ultrasonic
4 | # Website : www.gewbot.com
5 | # Author : William
6 | # Date : 2019/02/23
7 | from gpiozero import DistanceSensor
8 | from time import sleep
9 | Tr = 23
10 | Ec = 24
11 |
12 |
13 | sensor = DistanceSensor(echo=Ec, trigger=Tr, max_distance=2) # Maximum detection distance 2m.
14 |
15 | def checkdist():
16 | return (sensor.distance) *100 # Unit: cm
17 |
18 | if __name__ == '__main__':
19 | while True:
20 | distance = checkdist()*100
21 | print("%.2f cm" %distance)
22 | sleep(0.05)
23 |
--------------------------------------------------------------------------------
/server/trackingMoudle.py:
--------------------------------------------------------------------------------
1 | import time
2 | import RPi.GPIO as GPIO
3 |
4 |
5 | line_pin_right = 19
6 | line_pin_middle = 16
7 | line_pin_left = 20
8 |
9 | def setup():
10 | GPIO.setwarnings(False)
11 | GPIO.setmode(GPIO.BCM)
12 | GPIO.setup(line_pin_right,GPIO.IN)
13 | GPIO.setup(line_pin_middle,GPIO.IN)
14 | GPIO.setup(line_pin_left,GPIO.IN)
15 | #motor.setup()
16 |
17 |
18 | def run():
19 | status_right = GPIO.input(line_pin_right)
20 | status_middle = GPIO.input(line_pin_middle)
21 | status_left = GPIO.input(line_pin_left)
22 | print('LF3: %d LF2: %d LF1: %d\n'%(status_right,status_middle,status_left))
23 | time.sleep(0.2)
24 | if __name__ == '__main__':
25 | try:
26 | setup()
27 | while True:
28 | run()
29 | except KeyboardInterrupt:
30 | pass
31 |
32 |
33 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Adeept
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/server/dist/service-worker.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Welcome to your Workbox-powered service worker!
3 | *
4 | * You'll need to register this file in your web app and you should
5 | * disable HTTP caching for this file too.
6 | * See https://goo.gl/nhQhGp
7 | *
8 | * The rest of the code is auto-generated. Please don't update this file
9 | * directly; instead, make changes to your Workbox build configuration
10 | * and re-run your build process.
11 | * See https://goo.gl/2aRDsh
12 | */
13 |
14 | importScripts("https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js");
15 |
16 | importScripts(
17 | "/precache-manifest.a14d08d959aeaa21de5cdb2a57fec282.js"
18 | );
19 |
20 | workbox.core.setCacheNameDetails({prefix: "adeept_bot_controller_web"});
21 |
22 | self.addEventListener('message', (event) => {
23 | if (event.data && event.data.type === 'SKIP_WAITING') {
24 | self.skipWaiting();
25 | }
26 | });
27 |
28 | /**
29 | * The workboxSW.precacheAndRoute() method efficiently caches and responds to
30 | * requests for URLs in the manifest.
31 | * See https://goo.gl/S9QRab
32 | */
33 | self.__precacheManifest = [].concat(self.__precacheManifest || []);
34 | workbox.precaching.precacheAndRoute(self.__precacheManifest, {});
35 |
--------------------------------------------------------------------------------
/server/switch.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env/python
2 | # File name : switch.py
3 | # Website : www.adeept.com
4 | # Author : Adeept
5 | # Date : 2025/05/15
6 |
7 | import time
8 |
9 | from gpiozero import LED
10 |
11 |
12 | def switchSetup():
13 | global led1,led2,led3
14 | led1 = LED(9)
15 | led2 = LED(25)
16 | led3 = LED(11)
17 |
18 | def switch(port, status):
19 | if port == 1:
20 | if status == 1:
21 | led1.on()
22 | elif status == 0:
23 | led1.off()
24 | elif port == 2:
25 | if status == 1:
26 | led2.on()
27 | elif status == 0:
28 | led2.off()
29 | elif port == 3:
30 | if status == 1:
31 | led3.on()
32 | elif status == 0:
33 | led3.off()
34 | else:
35 | print('Wrong Command: Example--switch(3, 1)->to switch on port3')
36 |
37 | def set_all_switch_off():
38 | switch(1,0)
39 | switch(2,0)
40 | switch(3,0)
41 |
42 |
43 | if __name__ == "__main__":
44 | switchSetup()
45 | while True:
46 | switch(1,1)
47 | time.sleep(1)
48 | switch(2,1)
49 | time.sleep(1)
50 | switch(3,1)
51 | time.sleep(1)
52 | set_all_switch_off()
53 | time.sleep(1)
--------------------------------------------------------------------------------
/server/info.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python3
2 | # File name : Ultrasonic.py
3 | # Description : Detection distance and tracking with ultrasonic
4 | # Website : www.gewbot.com
5 | # Author : William
6 | # Date : 2019/08/28
7 | import psutil
8 |
9 | def get_cpu_tempfunc():
10 | """ Return CPU temperature """
11 | result = 0
12 | mypath = "/sys/class/thermal/thermal_zone0/temp"
13 | with open(mypath, 'r') as mytmpfile:
14 | for line in mytmpfile:
15 | result = line
16 |
17 | result = float(result)/1000
18 | result = round(result, 1)
19 | return str(result)
20 |
21 |
22 | def get_gpu_tempfunc():
23 | """ Return GPU temperature as a character string"""
24 | res = os.popen('/opt/vc/bin/vcgencmd measure_temp').readline()
25 | return res.replace("temp=", "")
26 |
27 |
28 | def get_cpu_use():
29 | """ Return CPU usage using psutil"""
30 | cpu_cent = psutil.cpu_percent()
31 | return str(cpu_cent)
32 |
33 |
34 | def get_ram_info():
35 | """ Return RAM usage using psutil """
36 | ram_cent = psutil.virtual_memory()[2]
37 | return str(ram_cent)
38 |
39 |
40 | def get_swap_info():
41 | """ Return swap memory usage using psutil """
42 | swap_cent = psutil.swap_memory()[3]
43 | return str(swap_cent)
44 |
--------------------------------------------------------------------------------
/server/Kalman_filter.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/python
2 | # File name : car_dir.py
3 | # Description : By controlling Servo,thecamera can move Up and down,left and right and the Ultrasonic wave can move to left and right.
4 | # Website : www.gewbot.com
5 | # Author : William
6 | # Date : 2018/08/22
7 | import time
8 |
9 |
10 | class Kalman_filter:
11 | def __init__(self,Q,R):
12 | self.Q = Q
13 | self.R = R
14 |
15 | self.P_k_k1 = 1
16 | self.Kg = 0
17 | self.P_k1_k1 = 1
18 | self.x_k_k1 = 0
19 | self.ADC_OLD_Value = 0
20 | self.Z_k = 0
21 | self.kalman_adc_old=0
22 |
23 | def kalman(self,ADC_Value):
24 |
25 | self.Z_k = ADC_Value
26 |
27 | if (abs(self.kalman_adc_old-ADC_Value)>=60):
28 | self.x_k1_k1= ADC_Value*0.382 + self.kalman_adc_old*0.618
29 | else:
30 | self.x_k1_k1 = self.kalman_adc_old;
31 |
32 | self.x_k_k1 = self.x_k1_k1
33 | self.P_k_k1 = self.P_k1_k1 + self.Q
34 |
35 | self.Kg = self.P_k_k1/(self.P_k_k1 + self.R)
36 |
37 | kalman_adc = self.x_k_k1 + self.Kg * (self.Z_k - self.kalman_adc_old)
38 | self.P_k1_k1 = (1 - self.Kg)*self.P_k_k1
39 | self.P_k_k1 = self.P_k1_k1
40 |
41 | self.kalman_adc_old = kalman_adc
42 |
43 | return kalman_adc
--------------------------------------------------------------------------------
/server/dist/index.html:
--------------------------------------------------------------------------------
1 |
adeept_bot_controller_web
--------------------------------------------------------------------------------
/server/PID.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/python
2 | # File name : car_dir.py
3 | # Description : By controlling Servo,thecamera can move Up and down,left and right and the Ultrasonic wave can move to left and right.
4 | # Website : www.gewbot.com
5 | # Author : William
6 | # Date : 2018/08/22
7 | import time
8 |
9 |
10 | class PID:
11 | def __init__(self):
12 | self.Kp = 0
13 | self.Kd = 0
14 | self.Ki = 0
15 | self.Initialize()
16 |
17 | def SetKp(self,invar):
18 | self.Kp = invar
19 |
20 | def SetKi(self,invar):
21 | self.Ki = invar
22 |
23 | def SetKd(self,invar):
24 | self.Kd = invar
25 |
26 | def SetPrevError(self,preverror):
27 | self.prev_error = preverror
28 |
29 | def Initialize(self):
30 | self.currtime = time.time()
31 | self.prevtime = self.currtime
32 |
33 | self.prev_error = 0
34 |
35 | self.Cp = 0
36 | self.Ci = 0
37 | self.Cd = 0
38 |
39 | def GenOut(self,error):
40 | self.currtime = time.time()
41 | dt = self.currtime - self.prevtime
42 | de = error - self.prev_error
43 |
44 | self.Cp = self.Kp*error
45 | self.Ci += error*dt
46 |
47 | self.Cd = 0
48 | if dt > 0:
49 | self.Cd = de/dt
50 |
51 | self.prevtime = self.currtime
52 | self.prev_error = error
53 |
54 | return self.Cp + (self.Ki*self.Ci) + (self.Kd*self.Cd)
55 | '''
56 | pid = PID()
57 | pid.SetKp(Kp)
58 | pid.SetKd(Kd)
59 | pid.SetKi(Ki)
60 |
61 | fb = 0
62 | outv = 0
63 |
64 | PID_loop = True
65 |
66 | while PID_loop:
67 | error = Sp - fb
68 |
69 | outv = pid.GenOut(error)
70 | AnalogOut(outv)
71 |
72 | time.sleep(0.05)
73 |
74 | fb = AnalogIn(fb_input)
75 | pass
76 | '''
--------------------------------------------------------------------------------
/server/findline.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python3
2 | # File name : findline.py
3 | # Description : line tracking
4 | # Website : www.gewbot.com
5 | # Author : William
6 | # Date : 2019/08/28
7 | import RPi.GPIO as GPIO
8 | import time
9 | import move
10 | '''
11 | status = 1 #Motor rotation
12 | forward = 1 #Motor forward
13 | backward = 0 #Motor backward
14 |
15 | left_spd = num_import_int('E_M1:') #Speed of the car
16 | right_spd = num_import_int('E_M2:') #Speed of the car
17 | left = num_import_int('E_T1:') #Motor Left
18 | right = num_import_int('E_T2:') #Motor Right
19 | '''
20 | line_pin_right = 19
21 | line_pin_middle = 16
22 | line_pin_left = 20
23 | '''
24 | left_R = 15
25 | left_G = 16
26 | left_B = 18
27 |
28 | right_R = 19
29 | right_G = 21
30 | right_B = 22
31 |
32 | on = GPIO.LOW
33 | off = GPIO.HIGH
34 |
35 | spd_ad_1 = 1
36 | spd_ad_2 = 1
37 | '''
38 | def setup():
39 | GPIO.setwarnings(False)
40 | GPIO.setmode(GPIO.BCM)
41 | GPIO.setup(line_pin_right,GPIO.IN)
42 | GPIO.setup(line_pin_middle,GPIO.IN)
43 | GPIO.setup(line_pin_left,GPIO.IN)
44 | #motor.setup()
45 |
46 | def run():
47 | status_right = GPIO.input(line_pin_right)
48 | status_middle = GPIO.input(line_pin_middle)
49 | status_left = GPIO.input(line_pin_left)
50 | #print('R%d M%d L%d'%(status_right,status_middle,status_left))
51 | if status_middle == 1:
52 | move.move(100, 'forward', 'no', 1)
53 | elif status_left == 1:
54 | move.move(100, 'forward', 'right', 0.6)
55 | elif status_right == 1:
56 | move.move(100, 'forward', 'left', 0.6)
57 | else:
58 | move.move(100, 'backward', 'no', 1)
59 |
60 | if __name__ == '__main__':
61 | try:
62 | setup()
63 | move.setup()
64 | while 1:
65 | run()
66 | pass
67 | except KeyboardInterrupt:
68 | move.destroy()
69 |
--------------------------------------------------------------------------------
/server/LEDapp.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python3
2 | # File name : LED.py
3 | # Description : WS_2812
4 | # Website : based on the code from https://github.com/rpi-ws281x/rpi-ws281x-python/blob/master/examples/strandtest.py
5 | # Author : original code by Tony DiCola (tony@tonydicola.com)
6 | # Date : 2019/02/23
7 | import time
8 | from rpi_ws281x import *
9 | import argparse
10 |
11 | # LED strip configuration:
12 | LED_COUNT = 3 # Number of LED pixels.
13 | LED_PIN = 12 # GPIO pin connected to the pixels (18 uses PWM!).
14 | #LED_PIN = 10 # GPIO pin connected to the pixels (10 uses SPI /dev/spidev0.0).
15 | LED_FREQ_HZ = 800000 # LED signal frequency in hertz (usually 800khz)
16 | LED_DMA = 10 # DMA channel to use for generating signal (try 10)
17 | LED_BRIGHTNESS = 255 # Set to 0 for darkest and 255 for brightest
18 | LED_INVERT = False # True to invert the signal (when using NPN transistor level shift)
19 | LED_CHANNEL = 0 # set to '1' for GPIOs 13, 19, 41, 45 or 53
20 |
21 | class LED:
22 | def __init__(self):
23 | self.LED_COUNT = 16 # Number of LED pixels.
24 | self.LED_PIN = 12 # GPIO pin connected to the pixels (18 uses PWM!).
25 | self.LED_FREQ_HZ = 800000 # LED signal frequency in hertz (usually 800khz)
26 | self.LED_DMA = 10 # DMA channel to use for generating signal (try 10)
27 | self.LED_BRIGHTNESS = 255 # Set to 0 for darkest and 255 for brightest
28 | self.LED_INVERT = False # True to invert the signal (when using NPN transistor level shift)
29 | self.LED_CHANNEL = 0 # set to '1' for GPIOs 13, 19, 41, 45 or 53
30 | parser = argparse.ArgumentParser()
31 | parser.add_argument('-c', '--clear', action='store_true', help='clear the display on exit')
32 | args = parser.parse_args()
33 |
34 | # Create NeoPixel object with appropriate configuration.
35 | self.strip = Adafruit_NeoPixel(self.LED_COUNT, self.LED_PIN, self.LED_FREQ_HZ, self.LED_DMA, self.LED_INVERT, self.LED_BRIGHTNESS, self.LED_CHANNEL)
36 | # Intialize the library (must be called once before other functions).
37 | self.strip.begin()
38 |
39 | # Define functions which animate LEDs in various ways.
40 | def colorWipe(self, R, G, B):
41 | """Wipe color across display a pixel at a time."""
42 | color = Color(R,G,B)
43 | for i in range(self.strip.numPixels()):
44 | self.strip.setPixelColor(i, color)
45 | self.strip.show()
46 |
47 | if __name__ == '__main__':
48 | led = LED()
49 | led.colorWipe(0,0,255)
--------------------------------------------------------------------------------
/server/app.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | from importlib import import_module
3 | import os
4 | from flask import Flask, render_template, Response, send_from_directory
5 | from flask_cors import *
6 | # import camera driver
7 |
8 | from camera_opencv import Camera
9 | import threading
10 |
11 | # Raspberry Pi camera module (requires picamera package)
12 | # from camera_pi import Camera
13 |
14 | app = Flask(__name__)
15 | CORS(app, supports_credentials=True)
16 | camera = Camera()
17 |
18 | def gen(camera):
19 | """Video streaming generator function."""
20 | while True:
21 | frame = camera.get_frame()
22 | yield (b'--frame\r\n'
23 | b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')
24 |
25 | @app.route('/video_feed')
26 | def video_feed():
27 | """Video streaming route. Put this in the src attribute of an img tag."""
28 | return Response(gen(camera),
29 | mimetype='multipart/x-mixed-replace; boundary=frame')
30 |
31 | dir_path = os.path.dirname(os.path.realpath(__file__))
32 |
33 | @app.route('/api/img/')
34 | def sendimg(filename):
35 | return send_from_directory(dir_path+'/dist/img', filename)
36 |
37 | @app.route('/js/')
38 | def sendjs(filename):
39 | return send_from_directory(dir_path+'/dist/js', filename)
40 |
41 | @app.route('/css/')
42 | def sendcss(filename):
43 | return send_from_directory(dir_path+'/dist/css', filename)
44 |
45 | @app.route('/api/img/icon/')
46 | def sendicon(filename):
47 | return send_from_directory(dir_path+'/dist/img/icon', filename)
48 |
49 | @app.route('/fonts/')
50 | def sendfonts(filename):
51 | return send_from_directory(dir_path+'/dist/fonts', filename)
52 |
53 | @app.route('/')
54 | def sendgen(filename):
55 | return send_from_directory(dir_path+'/dist', filename)
56 |
57 | @app.route('/')
58 | def index():
59 | return send_from_directory(dir_path+'/dist', 'index.html')
60 |
61 | class webapp:
62 | def __init__(self):
63 | self.camera = camera
64 |
65 | def modeselect(self, modeInput):
66 | Camera.modeSelect = modeInput
67 |
68 | def colorFindSet(self, H, S, V):
69 | camera.colorFindSet(H, S, V)
70 |
71 | def thread(self):
72 | app.run(host='0.0.0.0', threaded=True)
73 |
74 | def startthread(self):
75 | fps_threading=threading.Thread(target=self.thread) #Define a thread for FPV and OpenCV
76 | fps_threading.setDaemon(False) #'True' means it is a front thread,it would close when the mainloop() closes
77 | fps_threading.start() #Thread starts
78 |
79 |
80 |
--------------------------------------------------------------------------------
/autorun.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python3
2 | # File name : motor.py
3 | # Description : Control Motors
4 | # Website : www.adeept.com
5 | # E-mail : support@adeept.com
6 | # Author : William
7 | # Date : 2018/10/12
8 |
9 | import os
10 | import sys
11 |
12 | def search(path,name):
13 | for root, dirs, files in os.walk(path):
14 | if name in dirs or name in files:
15 | flag = 1
16 | root = str(root)
17 | dirs = str(dirs)
18 | return os.path.join(root, dirs)
19 | return -1
20 |
21 | def replace_num(file,initial,new_num):
22 | newline=""
23 | str_num=str(new_num)
24 | with open(file,"r") as f:
25 | for line in f.readlines():
26 | if(line.find(initial) == 0):
27 | line = (str_num+'\n')
28 | newline += line
29 | with open(file,"w") as f:
30 | f.writelines(newline)
31 |
32 | path_get = str(search('//home/pi/','server.py'))
33 | path_get=path_get[:-15]
34 |
35 | if path_get != -1:
36 | while 1:
37 | command_select = input('Do you want to autostart the sound version or the Test version(without OpenCV)?\nInput "1" to select sound version.\nInput "2" to select Test version(without OpenCV).')
38 | if command_select == '1' or command_select == '2':
39 | break
40 | else:
41 | continue
42 | else:
43 | print('Cannot find the programe for this robot, you need to setup the programe first.')
44 |
45 |
46 | if command_select == '1':
47 | try:
48 | try:
49 | os.system('sudo rm -rf //home/pi/.config/autostart')
50 | except:
51 | pass
52 | os.system('sudo mkdir //home/pi/.config/autostart')
53 | os.system('sudo touch //home/pi/.config/autostart/car.desktop')
54 | with open("//home/pi/.config/autostart/car.desktop",'w') as file_to_write:
55 | file_to_write.write("[Desktop Entry]\n Name=Car\n Comment=Car\n Exec=sudo python3 %sserver.py\n Icon=false\n Terminal=false\n MutipleArgs=false\n Type=Application\n Catagories=Application;Development;\n StartupNotify=true"%path_get)
56 | print('The sound version will start when boot')
57 | except:
58 | pass
59 | elif command_select == '2':
60 | try:
61 | try:
62 | os.system('sudo rm -rf //home/pi/.config/autostart')
63 | except:
64 | pass
65 | os.system('sudo mkdir //home/pi/.config/autostart')
66 | os.system('sudo touch //home/pi/.config/autostart/car.desktop')
67 | with open("//home/pi/.config/autostart/car.desktop",'w') as file_to_write:
68 | file_to_write.write("[Desktop Entry]\n Name=Car\n Comment=Car\n Exec=sudo python3 %sserverTest.py\n Icon=false\n Terminal=false\n MutipleArgs=false\n Type=Application\n Catagories=Application;Development;\n StartupNotify=true"%path_get)
69 | print('The Test version(without OpenCV) will start when boot')
70 | except:
71 | pass
72 |
73 | #path_get=str(path_get)
74 | #print(path_get[:-15])
--------------------------------------------------------------------------------
/server/OLED.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env/python3
2 | # File name : server.py
3 | # Description : for OLED functions
4 | # Website : www.gewbot.com
5 | # Author : William(Based on Adrian Rosebrock's OpenCV code on pyimagesearch.com)
6 | # Date : 2019/08/28
7 |
8 | from luma.core.interface.serial import i2c
9 | from luma.core.render import canvas
10 | from luma.oled.device import ssd1306, ssd1325, ssd1331, sh1106
11 | import time
12 | import threading
13 |
14 | try:
15 | serial = i2c(port=1, address=0x3C)
16 | device = ssd1306(serial, rotate=0)
17 | except:
18 | print('OLED disconnected\nOLED没有连接')
19 |
20 | # Box and text rendered in portrait mode
21 | # with canvas(device) as draw:
22 | # draw.text((0, 0), "WWW.CODELECTRON.COM", fill="white")
23 | # draw.text((0, 10), "WWW.CODELECTRON.COM", fill="white")
24 | # draw.text((0, 20), "WWW.CODELECTRON.COM", fill="white")
25 | # draw.text((0, 30), "WWW.CODELECTRON.COM", fill="white")
26 | # draw.text((0, 40), "WWW.CODELECTRON.COM", fill="white")
27 | # draw.text((0, 50), "WWW.CODELECTRON.COM", fill="white")
28 | # while 1:
29 | # time.sleep(1)
30 |
31 | text_1 = 'GEWBOT.COM'
32 | text_2 = 'IP:CONNECTING'
33 | text_3 = ' OR MODE'
34 | text_4 = 'MPU6050 DETECTING'
35 | text_5 = 'FUNCTION OFF'
36 | text_6 = 'Message:None'
37 |
38 | class OLED_ctrl(threading.Thread):
39 | def __init__(self, *args, **kwargs):
40 | super(OLED_ctrl, self).__init__(*args, **kwargs)
41 | self.__flag = threading.Event() # 用于暂停线程的标识
42 | self.__flag.set() # 设置为True
43 | self.__running = threading.Event() # 用于停止线程的标识
44 | self.__running.set() # 将running设置为True
45 |
46 | def run(self):
47 | while self.__running.isSet():
48 | self.__flag.wait() # 为True时立即返回, 为False时阻塞直到内部的标识位为True后返回
49 | with canvas(device) as draw:
50 | draw.text((0, 0), text_1, fill="white")
51 | draw.text((0, 10), text_2, fill="white")
52 | draw.text((0, 20), text_3, fill="white")
53 | draw.text((0, 30), text_4, fill="white")
54 | draw.text((0, 40), text_5, fill="white")
55 | draw.text((0, 50), text_6, fill="white")
56 | print('loop')
57 | self.pause()
58 |
59 | def pause(self):
60 | self.__flag.clear() # 设置为False, 让线程阻塞
61 |
62 | def resume(self):
63 | self.__flag.set() # 设置为True, 让线程停止阻塞
64 |
65 | def stop(self):
66 | self.__flag.set() # 将线程从暂停状态恢复, 如何已经暂停的话
67 | self.__running.clear() # 设置为False
68 |
69 | def screen_show(self, position, text):
70 | global text_1, text_2, text_3, text_4, text_5, text_6
71 | if position == 1:
72 | text_1 = text
73 | elif position == 2:
74 | text_2 = text
75 | elif position == 3:
76 | text_3 = text
77 | elif position == 4:
78 | text_4 = text
79 | elif position == 5:
80 | text_5 = text
81 | elif position == 6:
82 | text_6 = text
83 | self.resume()
84 |
85 | if __name__ == '__main__':
86 | screen = OLED_ctrl()
87 | screen.start()
88 | screen.screen_show(1, 'GEWBOT.COM')
89 | while 1:
90 | time.sleep(10)
91 | pass
--------------------------------------------------------------------------------
/server/Instruction.txt:
--------------------------------------------------------------------------------
1 | First of all, thank you for purchasing Adeept's product.
2 |
3 | The .py program in the folder client is the program required on the PC.
4 | The .py program in the folder server is the program required on the robot.
5 |
6 | This instruction focuses on the programs in the folder server. When you encounter problems, you can refer to this description to solve the problem.
7 |
8 |
9 | 1.What should I do if the robot does not automatically run the program when I turn it on?
10 | First cause: the program is not installed completely, probably because the server connection of the dependent libraries needed is unstable, resulting in incomplete download of the dependent libraries.The full version of the program needs to install the appropriate dependencies to run properly.
11 | Second cause: Linux is case sensitive.The case sensitvity of the name when you clone from Github is different from the one of the autostart file of the default path.
12 |
13 | Solution: try the beta program - a program named serverTest.py in the folder server.
14 | If you need the beta program to run automatically every time you boot, execute autorun.py - enter "2" to select the autorun beta - enter.
15 | If you need to change to the full version of the autorun program every time you boot, execute autorun.py - enter "1" to select the full version of autorun - enter.
16 |
17 |
18 | 2.What should I do if the servo is moving in the opposite direction?
19 | Cause: the servos were produced in different batches, the moving direction of them may be different.
20 |
21 | Solution: We have reserved an interface for adjusting the direction of the servo in the program, which makes it much more easier to debug.
22 | All motion-related code is written in the program server/move.py.
23 | Enter the following command to open (note that it is not to execute) move.py and edit:
24 | sudo nano (path)/move.py
25 | (The path varies depending on the product you bought. Take RaspTank as an example. The path of move.py is //home/pi/adeept_rasptank/server/move.py)
26 | After opening move.py, change the value of set_direction to 0 (the default is 1), then press ctrl+x to exit, press Y to save change, and press Enter to confirm.
27 |
28 |
29 | 3. What should I do if the it fails to realize good self-stabilization?
30 | Cause: The IPD controler is used for self-stabilization. You need to input the appropriate PID parameters to achieve perfect stabilization. The PID parameters of each robot are different.
31 |
32 | Solution: If the reaction is slow, you can increase the P value appropriately (the line75 of move.py). If the reaction is too fast (or swing back and forth), you can reduce the P value appropriately.
33 | If the reaction speed is normal but there is overshoot, you need to increase the I value appropriately.
34 | The D value is differential and usually does not need to be changed for this product.
35 |
36 | The fun of creation lies in solving problems
37 | If you have any other questions, please e-mail us at support@adeept.com
--------------------------------------------------------------------------------
/server/LED.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python3
2 | # File name : LED.py
3 | # Description : WS_2812
4 | # Website : based on the code from https://github.com/rpi-ws281x/rpi-ws281x-python/blob/master/examples/strandtest.py
5 | # Author : original code by Tony DiCola (tony@tonydicola.com)
6 | # Date : 2019/02/23
7 | import time
8 | from rpi_ws281x import *
9 | import argparse
10 |
11 | # LED strip configuration:
12 | LED_COUNT = 12 # Number of LED pixels.
13 | LED_PIN = 12 # GPIO pin connected to the pixels (18 uses PWM!).
14 | #LED_PIN = 10 # GPIO pin connected to the pixels (10 uses SPI /dev/spidev0.0).
15 | LED_FREQ_HZ = 800000 # LED signal frequency in hertz (usually 800khz)
16 | LED_DMA = 10 # DMA channel to use for generating signal (try 10)
17 | LED_BRIGHTNESS = 255 # Set to 0 for darkest and 255 for brightest
18 | LED_INVERT = False # True to invert the signal (when using NPN transistor level shift)
19 | LED_CHANNEL = 0 # set to '1' for GPIOs 13, 19, 41, 45 or 53
20 |
21 | class LED:
22 | def __init__(self):
23 | self.LED_COUNT = 16 # Number of LED pixels.
24 | self.LED_PIN = 12 # GPIO pin connected to the pixels (18 uses PWM!).
25 | self.LED_FREQ_HZ = 800000 # LED signal frequency in hertz (usually 800khz)
26 | self.LED_DMA = 10 # DMA channel to use for generating signal (try 10)
27 | self.LED_BRIGHTNESS = 255 # Set to 0 for darkest and 255 for brightest
28 | self.LED_INVERT = False # True to invert the signal (when using NPN transistor level shift)
29 | self.LED_CHANNEL = 0 # set to '1' for GPIOs 13, 19, 41, 45 or 53
30 | parser = argparse.ArgumentParser()
31 | parser.add_argument('-c', '--clear', action='store_true', help='clear the display on exit')
32 | args = parser.parse_args()
33 |
34 | # Create NeoPixel object with appropriate configuration.
35 | self.strip = Adafruit_NeoPixel(self.LED_COUNT, self.LED_PIN, self.LED_FREQ_HZ, self.LED_DMA, self.LED_INVERT, self.LED_BRIGHTNESS, self.LED_CHANNEL)
36 | # Intialize the library (must be called once before other functions).
37 | self.strip.begin()
38 |
39 | # Define functions which animate LEDs in various ways.
40 | # def colorWipe(self, R, G, B):
41 | # def colorWipe(self, color, wait_ms=0):
42 | # """Wipe color across display a pixel at a time."""
43 | # for i in range(self.strip.numPixels()):
44 | # self.strip.setPixelColor(i, color)
45 | # self.strip.show()
46 | # time.sleep(wait_ms / 1000.0)
47 |
48 | def colorWipe(self, R, G, B):
49 | color = Color(R,G,B)
50 | for i in range(self.strip.numPixels()):
51 | self.strip.setPixelColor(i, color)
52 | self.strip.show()
53 |
54 | if __name__ == '__main__':
55 | led = LED()
56 | try:
57 | while True:
58 | led.colorWipe(255, 0, 0) # red
59 | time.sleep(1)
60 | led.colorWipe(0, 255, 0) # green
61 | time.sleep(1)
62 | led.colorWipe(0, 0, 255) # blue
63 | time.sleep(1)
64 | except:
65 | led.colorWipe(0,0,0) # Lights out
66 |
--------------------------------------------------------------------------------
/server/config.txt:
--------------------------------------------------------------------------------
1 | #L0
2 | L0_MAX:450
3 | L0_MIN:225
4 | L0_ST1:373
5 | L0_ST2:368
6 | L0_ST3:368
7 | L0_ST4:373
8 | L0_ST5:307
9 | L0_ST6:263
10 | L0_ST7:200
11 | L0_ST8:475
12 | L0_ST9:217
13 | L0_ST10:504
14 | #L1
15 | L1_MAX:500
16 | L1_MIN:100
17 | L1_ST1:158
18 | L1_ST2:200
19 | L1_ST3:250
20 | L1_ST4:325
21 | L1_ST5:523
22 | L1_ST6:321
23 | L1_ST7:360
24 | L1_ST8:360
25 | L1_ST9:360
26 | L1_ST10:360
27 | #L2
28 | L2_MAX:500
29 | L2_MIN:156
30 | L2_ST1:100
31 | L2_ST2:500
32 | L2_ST3:300
33 | L2_ST4:110
34 | L2_ST5:420
35 | L2_ST6:303
36 | L2_ST7:360
37 | L2_ST8:430
38 | L2_ST9:360
39 | L2_ST10:360
40 | #L3
41 | L3_MAX:500
42 | L3_MIN:280
43 | L3_ST1:285
44 | L3_ST2:367
45 | L3_ST3:367
46 | L3_ST4:285
47 | L3_ST5:350
48 | L3_ST6:414
49 | L3_ST7:360
50 | L3_ST8:360
51 | L3_ST9:360
52 | L3_ST10:360
53 | #L4
54 | L4_MAX:489
55 | L4_MIN:130
56 | L4_ST1:500
57 | L4_ST2:280
58 | L4_ST3:280
59 | L4_ST4:338
60 | L4_ST5:590
61 | L4_ST6:363
62 | L4_ST7:360
63 | L4_ST8:360
64 | L4_ST9:360
65 | L4_ST10:360
66 | #L5
67 | L5_MAX:500
68 | L5_MIN:120
69 | L5_ST1:104
70 | L5_ST2:121
71 | L5_ST3:300
72 | L5_ST4:500
73 | L5_ST5:165
74 | L5_ST6:300
75 | L5_ST7:360
76 | L5_ST8:360
77 | L5_ST9:360
78 | L5_ST10:360
79 | #L6
80 | L6_MAX:453
81 | L6_MIN:270
82 | L6_ST1:339
83 | L6_ST2:320
84 | L6_ST3:320
85 | L6_ST4:340
86 | L6_ST5:350
87 | L6_ST6:360
88 | L6_ST7:360
89 | L6_ST8:360
90 | L6_ST9:360
91 | L6_ST10:360
92 | #L7
93 | L7_MAX:500
94 | L7_MIN:123
95 | L7_ST1:193
96 | L7_ST2:314
97 | L7_ST3:340
98 | L7_ST4:340
99 | L7_ST5:350
100 | L7_ST6:360
101 | L7_ST7:360
102 | L7_ST8:360
103 | L7_ST9:360
104 | L7_ST10:360
105 | #L8
106 | L8_MAX:500
107 | L8_MIN:120
108 | L8_ST1:485
109 | L8_ST2:497
110 | L8_ST3:300
111 | L8_ST4:108
112 | L8_ST5:350
113 | L8_ST6:360
114 | L8_ST7:360
115 | L8_ST8:360
116 | L8_ST9:360
117 | L8_ST10:360
118 | #L9
119 | L9_MAX:380
120 | L9_MIN:174
121 | L9_ST1:342
122 | L9_ST2:320
123 | L9_ST3:320
124 | L9_ST4:343
125 | L9_ST5:350
126 | L9_ST6:360
127 | L9_ST7:360
128 | L9_ST8:360
129 | L9_ST9:360
130 | L9_ST10:360
131 | #L10
132 | L10_MAX:501
133 | L10_MIN:136
134 | L10_ST1:486
135 | L10_ST2:350
136 | L10_ST3:307
137 | L10_ST4:379
138 | L10_ST5:350
139 | L10_ST6:360
140 | L10_ST7:360
141 | L10_ST8:360
142 | L10_ST9:360
143 | L10_ST10:360
144 | #L11
145 | L11_MAX:300
146 | L11_MIN:201
147 | L11_ST1:138
148 | L11_ST2:115
149 | L11_ST3:300
150 | L11_ST4:493
151 | L11_ST5:350
152 | L11_ST6:360
153 | L11_ST7:360
154 | L11_ST8:360
155 | L11_ST9:360
156 | L11_ST10:360
157 | #L12
158 | L12_MAX:430
159 | L12_MIN:300
160 | L12_ST1:430
161 | L12_ST2:131
162 | L12_ST3:298
163 | L12_ST4:120
164 | L12_ST5:350
165 | L12_ST6:360
166 | L12_ST7:360
167 | L12_ST8:360
168 | L12_ST9:360
169 | L12_ST10:360
170 | #L13
171 | L13_MAX:443
172 | L13_MIN:139
173 | L13_ST1:429
174 | L13_ST2:227
175 | L13_ST3:298
176 | L13_ST4:340
177 | L13_ST5:350
178 | L13_ST6:360
179 | L13_ST7:360
180 | L13_ST8:360
181 | L13_ST9:360
182 | L13_ST10:360
183 | #L14
184 | L14_MAX:500
185 | L14_MIN:300
186 | L14_ST1:316
187 | L14_ST2:108
188 | L14_ST3:487
189 | L14_ST4:340
190 | L14_ST5:350
191 | L14_ST6:360
192 | L14_ST7:360
193 | L14_ST8:360
194 | L14_ST9:360
195 | L14_ST10:360
196 | #L15
197 | L15_MAX:500
198 | L15_MIN:300
199 | L15_ST1:339
200 | L15_ST2:194
201 | L15_ST3:330
202 | L15_ST4:340
203 | L15_ST5:350
204 | L15_ST6:360
205 | L15_ST7:360
206 | L15_ST8:360
207 | L15_ST9:360
208 | L15_ST10:360
--------------------------------------------------------------------------------
/wifi_hotspot_manager.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Configuration parameters - modify these values according to your needs
4 | SYSTEM_WIFI_CONN="preconfigured" # Default connection name for Bookworm system
5 | HOTSPOT_SSID="Adeept_Robot"
6 | HOTSPOT_PASSWORD="12345678" # At least 8 characters
7 | HOTSPOT_INTERFACE="wlan0"
8 | WIFI_AP_GATEWAY="192.168.4.1"
9 |
10 | # Wait for network service to be ready
11 | echo "Waiting for network service to start..."
12 | while ! nmcli general status > /dev/null 2>&1; do
13 | sleep 1
14 | done
15 |
16 | # Check WiFi connection status (for preconfigured connection)
17 | check_wifi_connection() {
18 | # Check if preconfigured connection is active
19 | nmcli connection show --active | grep -q "$SYSTEM_WIFI_CONN"
20 | return $?
21 | }
22 |
23 | # Get SSID of system preconfigured connection
24 | get_preconfigured_ssid() {
25 | nmcli connection show "$SYSTEM_WIFI_CONN" | grep "ssid" | awk '{print $2}'
26 | }
27 |
28 | # Connect to system preconfigured WiFi
29 | connect_wifi() {
30 | local ssid=$(get_preconfigured_ssid)
31 | echo "Attempting to connect to system preconfigured WiFi: $ssid (connection name: $SYSTEM_WIFI_CONN)"
32 |
33 | # Check if connection exists
34 | if ! nmcli connection show | grep -q "$SYSTEM_WIFI_CONN"; then
35 | echo "Error: System preconfigured connection $SYSTEM_WIFI_CONN does not exist"
36 | return 1
37 | fi
38 |
39 | # Attempt connection
40 | nmcli connection up "$SYSTEM_WIFI_CONN" ifname "$HOTSPOT_INTERFACE"
41 |
42 | # Wait for connection to complete
43 | sleep 10
44 |
45 | # Check if connection was successful
46 | if check_wifi_connection; then
47 | echo "System preconfigured WiFi connected successfully"
48 | return 0
49 | else
50 | echo "Failed to connect to system preconfigured WiFi"
51 | return 1
52 | fi
53 | }
54 |
55 | # Start hotspot
56 | start_hotspot() {
57 | echo "Starting hotspot: $HOTSPOT_SSID"
58 |
59 | # First shut down any existing hotspot connection
60 | if nmcli connection show | grep -q "$HOTSPOT_SSID"; then
61 | nmcli connection down "$HOTSPOT_SSID"
62 | fi
63 |
64 | # Create or modify hotspot configuration
65 | if ! nmcli connection show | grep -q "$HOTSPOT_SSID"; then
66 | nmcli connection add type wifi con-name "$HOTSPOT_SSID" ifname "$HOTSPOT_INTERFACE" ssid "$HOTSPOT_SSID"
67 | fi
68 |
69 | # Configure hotspot parameters
70 | nmcli connection modify "$HOTSPOT_SSID" connection.autoconnect no
71 | nmcli connection modify "$HOTSPOT_SSID" wifi.mode ap
72 | nmcli connection modify "$HOTSPOT_SSID" wifi-sec.key-mgmt wpa-psk
73 | nmcli connection modify "$HOTSPOT_SSID" wifi-sec.psk "$HOTSPOT_PASSWORD"
74 | nmcli connection modify "$HOTSPOT_SSID" ipv4.addresses "$WIFI_AP_GATEWAY/24"
75 | nmcli connection modify "$HOTSPOT_SSID" ipv4.method shared
76 | nmcli connection modify "$HOTSPOT_SSID" ipv6.method ignore
77 |
78 | # Start the hotspot
79 | nmcli connection up "$HOTSPOT_SSID" ifname "$HOTSPOT_INTERFACE"
80 |
81 | echo "Hotspot started successfully"
82 | }
83 |
84 | # Main logic
85 | main() {
86 | # First disconnect all possible connections
87 | nmcli connection down id "$SYSTEM_WIFI_CONN" > /dev/null 2>&1
88 | nmcli connection down id "$HOTSPOT_SSID" > /dev/null 2>&1
89 |
90 | # Attempt to connect to system preconfigured WiFi
91 | if connect_wifi; then
92 | exit 0
93 | fi
94 |
95 | # If WiFi connection fails, start hotspot
96 | start_hotspot
97 | }
98 |
99 | # Execute main logic
100 | main
101 |
--------------------------------------------------------------------------------
/instruction.txt:
--------------------------------------------------------------------------------
1 | First of all, the program should be done in the SD card, including writing the Raspberry Pi system,
2 | downloading and installing the Rasptank program.
3 |
4 | Pay attention to the case sensitivity during process of git clone . The specific operation process
5 | is in the document and manual. It will automatically start up at boot after the program is successfully installed.
6 |
7 | You need to connect the driver board and the Raspberry Pi, and before turn it on, connect the servo with the driver board.
8 | Wait until the servo rotates to specified position to assemble.
9 |
10 | The servo is 20 teeth and will have an error of less than 9° during the installation process, which is normal.
11 |
12 | ---------------------------------------------------------------------------------------------------------------------------
13 |
14 | The .py program in the folder client is the program required on the PC.
15 | The .py program in the folder server is the program required on the robot.
16 |
17 | This instruction focuses on the programs in the folder server. When you encounter problems, you can refer to this description to solve the problem.
18 |
19 |
20 | 1.What should I do if the robot does not automatically run the program when I turn it on?
21 | First cause: the program is not installed completely, probably because the server connection of the dependent libraries needed is unstable, resulting in incomplete download of the dependent libraries.The full version of the program needs to install the appropriate dependencies to run properly.
22 | Second cause: Linux is case sensitive.The case sensitvity of the name when you clone from Github is different from the one of the autostart file of the default path.
23 |
24 | Solution: try the beta program - a program named serverTest.py in the folder server.
25 | If you need the beta program to run automatically every time you boot, execute autorun.py - enter "2" to select the autorun beta - enter.
26 | If you need to change to the full version of the autorun program every time you boot, execute autorun.py - enter "1" to select the full version of autorun - enter.
27 |
28 |
29 | 2.What should I do if the servo is moving in the opposite direction?
30 | Cause: the servos were produced in different batches, the moving direction of them may be different.
31 |
32 | Solution: We have reserved an interface for adjusting the direction of the servo in the program, which makes it much more easier to debug.
33 | All motion-related code is written in the program server/move.py.
34 | Enter the following command to open (note that it is not to execute) move.py and edit:
35 | sudo nano (path)/move.py
36 | (The path varies depending on the product you bought. Take RaspClaws as an example. The path of move.py is //home/pi/adeept_raspclaws/server/move.py)
37 | After opening move.py, change the value of Set_Direction to 0 (the default is 1), then press ctrl+x to exit, press Y to save change, and press Enter to confirm.
38 |
39 |
40 | 3. What should I do if the it fails to realize good self-stabilization?
41 | Cause: The IPD controler is used for self-stabilization. You need to input the appropriate PID parameters to achieve perfect stabilization. The PID parameters of each robot are different.
42 |
43 | Solution: If the reaction is slow, you can increase the P value appropriately (the line75 of move.py). If the reaction is too fast (or swing back and forth), you can reduce the P value appropriately.
44 | If the reaction speed is normal but there is overshoot, you need to increase the I value appropriately.
45 | The D value is differential and usually does not need to be changed for this product.
46 |
47 | The fun of creation lies in solving problems
48 | If you have any other questions, please e-mail us at support@adeept.com
49 |
--------------------------------------------------------------------------------
/server/base_camera.py:
--------------------------------------------------------------------------------
1 | import time
2 | import threading
3 | import cv2
4 | try:
5 | from greenlet import getcurrent as get_ident
6 | except ImportError:
7 | try:
8 | from thread import get_ident
9 | except ImportError:
10 | from _thread import get_ident
11 |
12 |
13 | class CameraEvent(object):
14 | """An Event-like class that signals all active clients when a new frame is
15 | available.
16 | """
17 | def __init__(self):
18 | self.events = {}
19 |
20 | def wait(self):
21 | """Invoked from each client's thread to wait for the next frame."""
22 | ident = get_ident()
23 | if ident not in self.events:
24 | # this is a new client
25 | # add an entry for it in the self.events dict
26 | # each entry has two elements, a threading.Event() and a timestamp
27 | self.events[ident] = [threading.Event(), time.time()]
28 | return self.events[ident][0].wait()
29 |
30 | def set(self):
31 | """Invoked by the camera thread when a new frame is available."""
32 | now = time.time()
33 | remove = None
34 | for ident, event in self.events.items():
35 | if not event[0].isSet():
36 | # if this client's event is not set, then set it
37 | # also update the last set timestamp to now
38 | event[0].set()
39 | event[1] = now
40 | else:
41 | # if the client's event is already set, it means the client
42 | # did not process a previous frame
43 | # if the event stays set for more than 5 seconds, then assume
44 | # the client is gone and remove it
45 | if now - event[1] > 5:
46 | remove = ident
47 | if remove:
48 | del self.events[remove]
49 |
50 | def clear(self):
51 | """Invoked from each client's thread after a frame was processed."""
52 | self.events[get_ident()][0].clear()
53 |
54 |
55 | class BaseCamera(object):
56 | thread = None # background thread that reads frames from camera
57 | frame = None # current frame is stored here by background thread
58 | last_access = 0 # time of last client access to the camera
59 | event = CameraEvent()
60 |
61 | def __init__(self):
62 | """Start the background camera thread if it isn't running yet."""
63 | if BaseCamera.thread is None:
64 | BaseCamera.last_access = time.time()
65 |
66 | # start background frame thread
67 | BaseCamera.thread = threading.Thread(target=self._thread)
68 | BaseCamera.thread.start()
69 |
70 | # wait until frames are available
71 | while self.get_frame() is None:
72 | time.sleep(0)
73 |
74 | def get_frame(self):
75 | """Return the current camera frame."""
76 | BaseCamera.last_access = time.time()
77 |
78 | # wait for a signal from the camera thread
79 | BaseCamera.event.wait()
80 | BaseCamera.event.clear()
81 |
82 | return BaseCamera.frame
83 |
84 | @staticmethod
85 | def frames():
86 | """"Generator that returns frames from the camera."""
87 | raise RuntimeError('Must be implemented by subclasses.')
88 |
89 | @classmethod
90 | def _thread(cls):
91 | """Camera background thread."""
92 | print('Starting camera thread.')
93 | frames_iterator = cls.frames()
94 | for frame in frames_iterator:
95 | BaseCamera.frame = frame
96 | BaseCamera.event.set() # send signal to clients
97 | time.sleep(0)
98 |
99 | # if there hasn't been any clients asking for frames in
100 | # the last 10 seconds then stop the thread
101 | # if time.time() - BaseCamera.last_access > 10:
102 | # frames_iterator.close()
103 | # print('Stopping camera thread due to inactivity.')
104 | # break
105 | BaseCamera.thread = None
106 |
--------------------------------------------------------------------------------
/server/move.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # File name : move.py
3 | # Description : Control Motor
4 | # Product : GWR
5 | # Website : www.gewbot.com
6 | # Author : William
7 | # Date : 2019/07/24
8 | import time
9 | from board import SCL, SDA
10 | import busio
11 | from adafruit_pca9685 import PCA9685
12 | from adafruit_motor import motor
13 |
14 | # motor_EN_A: Pin7 | motor_EN_B: Pin11
15 | # motor_A: Pin8,Pin10 | motor_B: Pin13,Pin12
16 |
17 | MOTOR_M1_IN1 = 15 #Define the positive pole of M1
18 | MOTOR_M1_IN2 = 14 #Define the negative pole of M1
19 | MOTOR_M2_IN1 = 12 #Define the positive pole of M2
20 | MOTOR_M2_IN2 = 13 #Define the negative pole of M2
21 |
22 | Dir_forward = 0
23 | Dir_backward = 1
24 |
25 | left_forward = 0
26 | left_backward = 1
27 |
28 | right_forward = 0
29 | right_backward= 1
30 |
31 | pwn_A = 0
32 | pwm_B = 0
33 | FREQ = 50
34 |
35 |
36 |
37 | def map(x,in_min,in_max,out_min,out_max):
38 | return (x - in_min)/(in_max - in_min) *(out_max - out_min) +out_min
39 |
40 | def setup():#Motor initialization
41 | global motor1,motor2,motor3,motor4,pwm_motor,pwm_motor
42 | i2c = busio.I2C(SCL, SDA)
43 | pwm_motor = PCA9685(i2c, address=0x40) #default 0x40
44 |
45 | pwm_motor.frequency = FREQ
46 |
47 | motor1 = motor.DCMotor(pwm_motor.channels[MOTOR_M1_IN1],pwm_motor.channels[MOTOR_M1_IN2] )
48 | motor1.decay_mode = (motor.SLOW_DECAY)
49 | motor2 = motor.DCMotor(pwm_motor.channels[MOTOR_M2_IN1],pwm_motor.channels[MOTOR_M2_IN2] )
50 | motor2.decay_mode = (motor.SLOW_DECAY)
51 |
52 |
53 |
54 | def motorStop():#Motor stops
55 | global motor1,motor2
56 | motor1.throttle = 0
57 | motor2.throttle = 0
58 |
59 |
60 | def Motor(channel,direction,motor_speed):
61 | # channel,1~4:M1~M4
62 | if motor_speed > 100:
63 | motor_speed = 100
64 | elif motor_speed < 0:
65 | motor_speed = 0
66 |
67 | speed = map(motor_speed, 0, 100, 0, 1.0)
68 |
69 | pwm_motor.frequency = FREQ
70 | # Prevent the servo from affecting the frequency of the motor
71 | if direction == 1:
72 | speed = -speed
73 | if channel == 1:
74 | motor1.throttle = speed
75 | elif channel == 2:
76 | motor2.throttle = speed
77 |
78 |
79 |
80 |
81 | def motor_left(status, direction, speed):#Motor 2 positive and negative rotation
82 | if status == 0: # stop
83 | motorStop()
84 | else:
85 | if direction == Dir_backward:
86 | Motor(1, Dir_forward, speed)
87 | Motor(2, Dir_backward, speed)
88 | elif direction == Dir_forward:
89 | Motor(1, Dir_backward, speed)
90 | Motor(2, Dir_forward, speed)
91 |
92 | def motor_right(status, direction, speed):#Motor 1 positive and negative rotation
93 | if status == 0: # stop
94 | motorStop()
95 | else:
96 | if direction == Dir_backward:
97 | Motor(1, Dir_backward, speed)
98 | Motor(2, Dir_forward, speed)
99 | elif direction == Dir_forward:
100 | Motor(1, Dir_forward, speed)
101 | Motor(2, Dir_backward, speed)
102 |
103 |
104 | def move(speed, direction, turn, radius=0.6): # 0 < radius <= 1
105 | #speed = 100
106 | if direction == 'forward':
107 | if turn == 'right':
108 | motor_left(0, left_forward, int(speed*radius))
109 | motor_right(1, right_backward, speed)
110 | elif turn == 'left':
111 | motor_left(1, left_backward, speed)
112 | motor_right(0, right_forward, int(speed*radius))
113 | else:
114 | motor_left(1, left_backward, speed)
115 | motor_right(1, right_backward, speed)
116 | elif direction == 'backward':
117 | if turn == 'right':
118 | motor_left(0, left_backward, int(speed*radius))
119 | motor_right(1, right_forward, speed)
120 | elif turn == 'left':
121 | motor_left(1, left_forward, speed)
122 | motor_right(0, right_backward, int(speed*radius))
123 | else:
124 | motor_left(1, left_forward, speed)
125 | motor_right(1, right_forward, speed)
126 | elif direction == 'no':
127 | if turn == 'right':
128 | motor_left(1, left_backward, speed)
129 | motor_right(1, right_forward, speed)
130 | elif turn == 'left':
131 | motor_left(1, left_forward, speed)
132 | motor_right(1, right_backward, speed)
133 | else:
134 | motorStop()
135 | else:
136 | pass
137 |
138 |
139 |
140 |
141 | def destroy():
142 | motorStop()
143 | pwm_motor.deinit()
144 |
145 | if __name__ == '__main__':
146 | try:
147 | speed_set = 60
148 | setup()
149 | move(speed_set, 'forward', 'no', 0.8)
150 | time.sleep(1.3)
151 | motorStop()
152 | destroy()
153 | except KeyboardInterrupt:
154 | destroy()
155 |
156 |
--------------------------------------------------------------------------------
/server/dist/precache-manifest.a14d08d959aeaa21de5cdb2a57fec282.js:
--------------------------------------------------------------------------------
1 | self.__precacheManifest = (self.__precacheManifest || []).concat([
2 | {
3 | "revision": "953e3d9f8e140d7d21be",
4 | "url": "/css/app.5a950261.css"
5 | },
6 | {
7 | "revision": "8d733f44c3bf8783b8f7",
8 | "url": "/css/chunk-vendors.a6374dcc.css"
9 | },
10 | {
11 | "revision": "2d0a0d8f5f173be15a67aa084db94fe6",
12 | "url": "/fonts/materialdesignicons-webfont.2d0a0d8f.eot"
13 | },
14 | {
15 | "revision": "b4917be25082eb793b5363f2fdb5f282",
16 | "url": "/fonts/materialdesignicons-webfont.b4917be2.woff"
17 | },
18 | {
19 | "revision": "d0066537ab6a4c6f8285a5aeb3ba5f09",
20 | "url": "/fonts/materialdesignicons-webfont.d0066537.woff2"
21 | },
22 | {
23 | "revision": "f51112347be6b44f9ef46151a971430d",
24 | "url": "/fonts/materialdesignicons-webfont.f5111234.ttf"
25 | },
26 | {
27 | "revision": "5cb7edfceb233100075dc9a1e12e8da3",
28 | "url": "/fonts/roboto-latin-100.5cb7edfc.woff"
29 | },
30 | {
31 | "revision": "7370c3679472e9560965ff48a4399d0b",
32 | "url": "/fonts/roboto-latin-100.7370c367.woff2"
33 | },
34 | {
35 | "revision": "f8b1df51ba843179fa1cc9b53d58127a",
36 | "url": "/fonts/roboto-latin-100italic.f8b1df51.woff2"
37 | },
38 | {
39 | "revision": "f9e8e590b4e0f1ff83469bb2a55b8488",
40 | "url": "/fonts/roboto-latin-100italic.f9e8e590.woff"
41 | },
42 | {
43 | "revision": "b00849e00f4c2331cddd8ffb44a6720b",
44 | "url": "/fonts/roboto-latin-300.b00849e0.woff"
45 | },
46 | {
47 | "revision": "ef7c6637c68f269a882e73bcb57a7f6a",
48 | "url": "/fonts/roboto-latin-300.ef7c6637.woff2"
49 | },
50 | {
51 | "revision": "14286f3ba79c6627433572dfa925202e",
52 | "url": "/fonts/roboto-latin-300italic.14286f3b.woff2"
53 | },
54 | {
55 | "revision": "4df32891a5f2f98a363314f595482e08",
56 | "url": "/fonts/roboto-latin-300italic.4df32891.woff"
57 | },
58 | {
59 | "revision": "479970ffb74f2117317f9d24d9e317fe",
60 | "url": "/fonts/roboto-latin-400.479970ff.woff2"
61 | },
62 | {
63 | "revision": "60fa3c0614b8fb2f394fa29944c21540",
64 | "url": "/fonts/roboto-latin-400.60fa3c06.woff"
65 | },
66 | {
67 | "revision": "51521a2a8da71e50d871ac6fd2187e87",
68 | "url": "/fonts/roboto-latin-400italic.51521a2a.woff2"
69 | },
70 | {
71 | "revision": "fe65b8335ee19dd944289f9ed3178c78",
72 | "url": "/fonts/roboto-latin-400italic.fe65b833.woff"
73 | },
74 | {
75 | "revision": "020c97dc8e0463259c2f9df929bb0c69",
76 | "url": "/fonts/roboto-latin-500.020c97dc.woff2"
77 | },
78 | {
79 | "revision": "87284894879f5b1c229cb49c8ff6decc",
80 | "url": "/fonts/roboto-latin-500.87284894.woff"
81 | },
82 | {
83 | "revision": "288ad9c6e8b43cf02443a1f499bdf67e",
84 | "url": "/fonts/roboto-latin-500italic.288ad9c6.woff"
85 | },
86 | {
87 | "revision": "db4a2a231f52e497c0191e8966b0ee58",
88 | "url": "/fonts/roboto-latin-500italic.db4a2a23.woff2"
89 | },
90 | {
91 | "revision": "2735a3a69b509faf3577afd25bdf552e",
92 | "url": "/fonts/roboto-latin-700.2735a3a6.woff2"
93 | },
94 | {
95 | "revision": "adcde98f1d584de52060ad7b16373da3",
96 | "url": "/fonts/roboto-latin-700.adcde98f.woff"
97 | },
98 | {
99 | "revision": "81f57861ed4ac74741f5671e1dff2fd9",
100 | "url": "/fonts/roboto-latin-700italic.81f57861.woff"
101 | },
102 | {
103 | "revision": "da0e717829e033a69dec97f1e155ae42",
104 | "url": "/fonts/roboto-latin-700italic.da0e7178.woff2"
105 | },
106 | {
107 | "revision": "9b3766ef4a402ad3fdeef7501a456512",
108 | "url": "/fonts/roboto-latin-900.9b3766ef.woff2"
109 | },
110 | {
111 | "revision": "bb1e4dc6333675d11ada2e857e7f95d7",
112 | "url": "/fonts/roboto-latin-900.bb1e4dc6.woff"
113 | },
114 | {
115 | "revision": "28f9151055c950874d2c6803a39b425b",
116 | "url": "/fonts/roboto-latin-900italic.28f91510.woff"
117 | },
118 | {
119 | "revision": "ebf6d1640ccddb99fb49f73c052c55a8",
120 | "url": "/fonts/roboto-latin-900italic.ebf6d164.woff2"
121 | },
122 | {
123 | "revision": "2b2cbdd767cfdd25ff1d67efa6c6d44f",
124 | "url": "/img/bg.jpg"
125 | },
126 | {
127 | "revision": "15e494011ee2dfd636a304a6a4656bfc",
128 | "url": "/index.html"
129 | },
130 | {
131 | "revision": "953e3d9f8e140d7d21be",
132 | "url": "/js/app.0ea6d772.js"
133 | },
134 | {
135 | "revision": "8d733f44c3bf8783b8f7",
136 | "url": "/js/chunk-vendors.217ac283.js"
137 | },
138 | {
139 | "revision": "3a7172e1d88475e22caf9c660a7e700d",
140 | "url": "/manifest.json"
141 | },
142 | {
143 | "revision": "b6216d61c03e6ce0c9aea6ca7808f7ca",
144 | "url": "/robots.txt"
145 | }
146 | ]);
--------------------------------------------------------------------------------
/server/functions.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # File name : servo.py
3 | # Description : Control Functions
4 | # Author : William
5 | # Date : 2020/03/17
6 | import time
7 | from gpiozero import InputDevice
8 | import threading
9 | import Adafruit_PCA9685
10 | import os
11 | import json
12 | import ultra
13 | import Kalman_filter
14 | import move
15 |
16 | move.setup()
17 |
18 | kalman_filter_X = Kalman_filter.Kalman_filter(0.01,0.1)
19 |
20 | pwm = Adafruit_PCA9685.PCA9685(address=0x40, busnum=1)
21 | pwm.set_pwm_freq(50)
22 |
23 | # MPU_connection = 1
24 | # try:
25 | # sensor = mpu6050(0x68)
26 | # print('mpu6050 connected, PT MODE ON')
27 | # except:
28 | # MPU_connection = 0
29 | # print('mpu6050 disconnected, ARM MODE ON')
30 |
31 | curpath = os.path.realpath(__file__)
32 | thisPath = "/" + os.path.dirname(curpath)
33 |
34 | def num_import_int(initial): #Call this function to import data from '.txt' file
35 | global r
36 | with open(thisPath+"/RPIservo.py") as f:
37 | for line in f.readlines():
38 | if(line.find(initial) == 0):
39 | r=line
40 | begin=len(list(initial))
41 | snum=r[begin:]
42 | n=int(snum)
43 | return n
44 |
45 | pwm0_direction = 1
46 | pwm0_init = num_import_int('init_pwm0 = ')
47 | pwm0_max = 520
48 | pwm0_min = 100
49 | pwm0_pos = pwm0_init
50 |
51 | pwm1_direction = 1
52 | pwm1_init = num_import_int('init_pwm1 = ')
53 | pwm1_max = 520
54 | pwm1_min = 100
55 | pwm1_pos = pwm1_init
56 |
57 | pwm2_direction = 1
58 | pwm2_init = num_import_int('init_pwm2 = ')
59 | pwm2_max = 520
60 | pwm2_min = 100
61 | pwm2_pos = pwm2_init
62 |
63 | line_pin_right = 19
64 | line_pin_middle = 16
65 | line_pin_left = 20
66 |
67 | def pwmGenOut(angleInput):
68 | return int(round(23/9*angleInput))
69 |
70 |
71 | def setup():
72 | global track_line_left, track_line_middle,track_line_right
73 | track_line_left = InputDevice(pin=line_pin_left)
74 | track_line_middle = InputDevice(pin=line_pin_middle)
75 | track_line_right = InputDevice(pin=line_pin_right)
76 |
77 |
78 | class Functions(threading.Thread):
79 | def __init__(self, *args, **kwargs):
80 | self.functionMode = 'none'
81 | self.steadyGoal = 0
82 |
83 | self.scanNum = 3
84 | self.scanList = [0,0,0]
85 | self.scanPos = 1
86 | self.scanDir = 1
87 | self.rangeKeep = 0.7
88 | self.scanRange = 100
89 | self.scanServo = 1
90 | self.turnServo = 0
91 | self.turnWiggle = 200
92 |
93 | setup()
94 |
95 | super(Functions, self).__init__(*args, **kwargs)
96 | self.__flag = threading.Event()
97 | self.__flag.clear()
98 |
99 | def radarScan(self):
100 | global pwm0_pos
101 | scan_speed = 3
102 | result = []
103 |
104 | if pwm0_direction:
105 | pwm0_pos = pwm0_max
106 | pwm.set_pwm(1, 0, pwm0_pos)
107 | time.sleep(0.8)
108 |
109 | while pwm0_pos>pwm0_min:
110 | pwm0_pos-=scan_speed
111 | pwm.set_pwm(1, 0, pwm0_pos)
112 | dist = ultra.checkdist()
113 | if dist > 20:
114 | continue
115 | theta = 180 - (pwm0_pos-100)/2.55 # +30 deviation
116 | result.append([dist, theta])
117 | else:
118 | pwm0_pos = pwm0_min
119 | pwm.set_pwm(1, 0, pwm0_pos)
120 | time.sleep(0.8)
121 |
122 | while pwm0_pos 20:
127 | continue
128 | theta = (pwm0_pos-100)/2.55
129 | result.append([dist, theta])
130 | pwm.set_pwm(1, 0, pwm0_init)
131 | return result
132 |
133 |
134 | def pause(self):
135 | self.functionMode = 'none'
136 | move.move(80, 'no', 'no', 0.5)
137 | self.__flag.clear()
138 |
139 |
140 | def resume(self):
141 | self.__flag.set()
142 |
143 |
144 | def automatic(self):
145 | self.functionMode = 'Automatic'
146 | self.resume()
147 |
148 |
149 | def trackLine(self):
150 | self.functionMode = 'trackLine'
151 | self.resume()
152 |
153 |
154 | def steady(self,goalPos):
155 | self.functionMode = 'Steady'
156 | self.steadyGoal = goalPos
157 | self.resume()
158 |
159 |
160 | def trackLineProcessing(self):
161 | status_right = track_line_right.value
162 | status_middle = track_line_middle.value
163 | status_left = track_line_left.value
164 | #print('R%d M%d L%d'%(status_right,status_middle,status_left))
165 | if status_middle == 1:
166 | move.move(100, 'forward', 'no', 1)
167 | elif status_left == 1:
168 | move.move(100, 'no', 'right', 1)
169 | elif status_right == 1:
170 | move.move(100, 'no', 'left', 1)
171 | else:
172 | move.move(100, 'backward', 'no', 1)
173 |
174 | time.sleep(0.1)
175 |
176 |
177 | def automaticProcessing(self):
178 | print('automaticProcessing')
179 | if self.rangeKeep/3 > ultra.checkdist():
180 | move.move(100, 'backward', 'no', 0.5)
181 | elif self.rangeKeep > ultra.checkdist():
182 | move.move(100, 'no', 'left', 0.5)
183 | else:
184 | move.move(100, 'forward', 'no', 0.5)
185 | time.sleep(0.1)
186 | if self.functionMode == 'none':
187 | move.move(80, 'no', 'no', 0.5)
188 |
189 |
190 | def functionGoing(self):
191 | if self.functionMode == 'none':
192 | self.pause()
193 | elif self.functionMode == 'Automatic':
194 | self.automaticProcessing()
195 | elif self.functionMode == 'trackLine':
196 | self.trackLineProcessing()
197 |
198 |
199 | def run(self):
200 | while 1:
201 | self.__flag.wait()
202 | self.functionGoing()
203 | pass
204 |
205 |
206 | if __name__ == '__main__':
207 | pass
208 | # fuc=Functions()
209 | # fuc.radarScan()
210 | # fuc.start()
211 | # fuc.automatic()
212 | # # fuc.steady(300)
213 | # time.sleep(30)
214 | # fuc.pause()
215 | # time.sleep(1)
216 | # move.move(80, 'no', 'no', 0.5)
217 |
--------------------------------------------------------------------------------
/server/servo.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # File name : servo.py
3 | # Description : Control Servos
4 | # Author : William
5 | # Date : 2019/02/23
6 | from __future__ import division
7 | import time
8 | import RPi.GPIO as GPIO
9 | import sys
10 | import Adafruit_PCA9685
11 | import ultra
12 |
13 | '''
14 | change this form 1 to 0 to reverse servos
15 | '''
16 | pwm0_direction = 1
17 | pwm1_direction = 1
18 | pwm2_direction = 1
19 | pwm3_direction = 1
20 |
21 |
22 | pwm = Adafruit_PCA9685.PCA9685()
23 | pwm.set_pwm_freq(50)
24 |
25 | pwm0_init = 300
26 | pwm0_max = 450
27 | pwm0_min = 150
28 | pwm0_pos = pwm0_init
29 |
30 | pwm1_init = 300
31 | pwm1_max = 480
32 | pwm1_min = 160
33 | pwm1_pos = pwm1_init
34 |
35 | pwm2_init = 300
36 | pwm2_max = 500
37 | pwm2_min = 100
38 | pwm2_pos = pwm2_init
39 |
40 | pwm3_init = 300
41 | pwm3_max = 500
42 | pwm3_min = 300
43 | pwm3_pos = pwm3_init
44 |
45 | org_pos = 300
46 |
47 |
48 | def radar_scan():
49 | global pwm0_pos
50 | scan_result = 'U: '
51 | scan_speed = 1
52 | if pwm0_direction:
53 | pwm0_pos = pwm0_max
54 | pwm.set_pwm(0, 0, pwm0_pos)
55 | time.sleep(0.5)
56 | scan_result += str(ultra.checkdist())
57 | scan_result += ' '
58 | while pwm0_pos>pwm0_min:
59 | pwm0_pos-=scan_speed
60 | pwm.set_pwm(0, 0, pwm0_pos)
61 | scan_result += str(ultra.checkdist())
62 | scan_result += ' '
63 | pwm.set_pwm(0, 0, pwm0_init)
64 | else:
65 | pwm0_pos = pwm0_min
66 | pwm.set_pwm(0, 0, pwm0_pos)
67 | time.sleep(0.5)
68 | scan_result += str(ultra.checkdist())
69 | scan_result += ' '
70 | while pwm0_pos max_genout:
84 | raw_output = max_genout
85 | elif raw < min_genout:
86 | raw_output = min_genout
87 | else:
88 | raw_output = raw
89 | return int(raw_output)
90 |
91 |
92 | def camera_ang(direction, ang):
93 | global org_pos
94 | if ang == 'no':
95 | ang = 50
96 | if look_direction:
97 | if direction == 'lookdown':
98 | org_pos+=ang
99 | org_pos = ctrl_range(org_pos, look_max, look_min)
100 | elif direction == 'lookup':
101 | org_pos-=ang
102 | org_pos = ctrl_range(org_pos, look_max, look_min)
103 | elif direction == 'home':
104 | org_pos = 300
105 | else:
106 | if direction == 'lookdown':
107 | org_pos-=ang
108 | org_pos = ctrl_range(org_pos, look_max, look_min)
109 | elif direction == 'lookup':
110 | org_pos+=ang
111 | org_pos = ctrl_range(org_pos, look_max, look_min)
112 | elif direction == 'home':
113 | org_pos = 300
114 |
115 | pwm.set_all_pwm(0,org_pos)
116 |
117 |
118 | def lookleft(speed):
119 | global pwm0_pos
120 | if pwm0_direction:
121 | pwm0_pos += speed
122 | pwm0_pos = ctrl_range(pwm0_pos, pwm0_max, pwm0_min)
123 | pwm.set_pwm(0, 0, pwm0_pos)
124 | else:
125 | pwm0_pos -= speed
126 | pwm0_pos = ctrl_range(pwm0_pos, pwm0_max, pwm0_min)
127 | pwm.set_pwm(0, 0, pwm0_pos)
128 |
129 |
130 | def lookright(speed):
131 | global pwm0_pos
132 | if pwm0_direction:
133 | pwm0_pos -= speed
134 | pwm0_pos = ctrl_range(pwm0_pos, pwm0_max, pwm0_min)
135 | pwm.set_pwm(0, 0, pwm0_pos)
136 | else:
137 | pwm0_pos += speed
138 | pwm0_pos = ctrl_range(pwm0_pos, pwm0_max, pwm0_min)
139 | pwm.set_pwm(0, 0, pwm0_pos)
140 |
141 |
142 | def up(speed):
143 | global pwm1_pos
144 | if pwm1_direction:
145 | pwm1_pos -= speed
146 | pwm1_pos = ctrl_range(pwm1_pos, pwm1_max, pwm1_min)
147 | pwm.set_pwm(1, 0, pwm1_pos)
148 | else:
149 | pwm1_pos += speed
150 | pwm1_pos = ctrl_range(pwm1_pos, pwm1_max, pwm1_min)
151 | pwm.set_pwm(1, 0, pwm1_pos)
152 | #print(pwm1_pos)
153 |
154 |
155 | def down(speed):
156 | global pwm1_pos
157 | if pwm1_direction:
158 | pwm1_pos += speed
159 | pwm1_pos = ctrl_range(pwm1_pos, pwm1_max, pwm1_min)
160 | pwm.set_pwm(1, 0, pwm1_pos)
161 | else:
162 | pwm1_pos -= speed
163 | pwm1_pos = ctrl_range(pwm1_pos, pwm1_max, pwm1_min)
164 | pwm.set_pwm(1, 0, pwm1_pos)
165 | #print(pwm1_pos)
166 |
167 | def lookup(speed):
168 | global pwm2_pos
169 | if pwm2_direction:
170 | pwm2_pos -= speed
171 | pwm2_pos = ctrl_range(pwm2_pos, pwm2_max, pwm2_min)
172 | pwm.set_pwm(2, 0, pwm2_pos)
173 | else:
174 | pwm2_pos += speed
175 | pwm2_pos = ctrl_range(pwm2_pos, pwm2_max, pwm2_min)
176 | pwm.set_pwm(2, 0, pwm2_pos)
177 |
178 |
179 | def lookdown(speed):
180 | global pwm2_pos
181 | if pwm2_direction:
182 | pwm2_pos += speed
183 | pwm2_pos = ctrl_range(pwm2_pos, pwm2_max, pwm2_min)
184 | pwm.set_pwm(2, 0, pwm2_pos)
185 | else:
186 | pwm2_pos -= speed
187 | pwm2_pos = ctrl_range(pwm2_pos, pwm2_max, pwm2_min)
188 | pwm.set_pwm(2, 0, pwm2_pos)
189 |
190 |
191 | def grab(speed):
192 | global pwm3_pos
193 | if pwm3_direction:
194 | pwm3_pos -= speed
195 | pwm3_pos = ctrl_range(pwm3_pos, pwm3_max, pwm3_min)
196 | pwm.set_pwm(3, 0, pwm3_pos)
197 | else:
198 | pwm3_pos += speed
199 | pwm3_pos = ctrl_range(pwm3_pos, pwm3_max, pwm3_min)
200 | pwm.set_pwm(3, 0, pwm3_pos)
201 | print(pwm3_pos)
202 |
203 |
204 | def loose(speed):
205 | global pwm3_pos
206 | if pwm3_direction:
207 | pwm3_pos += speed
208 | pwm3_pos = ctrl_range(pwm3_pos, pwm3_max, pwm3_min)
209 | pwm.set_pwm(3, 0, pwm3_pos)
210 | else:
211 | pwm3_pos -= speed
212 | pwm3_pos = ctrl_range(pwm3_pos, pwm3_max, pwm3_min)
213 | pwm.set_pwm(3, 0, pwm3_pos)
214 | print(pwm3_pos)
215 |
216 |
217 | def servo_init():
218 | pwm.set_pwm(0, 0, pwm0_pos)
219 | pwm.set_pwm(1, 0, pwm1_pos)
220 | pwm.set_pwm(2, 0, pwm2_max)
221 | pwm.set_pwm(3, 0, pwm3_pos)
222 | try:
223 | pwm.set_all_pwm(0, 300)
224 | except:
225 | pass
226 |
227 |
228 | def clean_all():
229 | global pwm
230 | pwm = Adafruit_PCA9685.PCA9685()
231 | pwm.set_pwm_freq(50)
232 | pwm.set_all_pwm(0, 0)
233 |
234 |
235 | def ahead():
236 | global pwm0_pos, pwm1_pos
237 | pwm.set_pwm(0, 0, pwm0_init)
238 | pwm.set_pwm(1, 0, (pwm1_max-20))
239 | pwm0_pos = pwm0_init
240 | pwm1_pos = pwm1_max-20
241 |
242 |
243 | def get_direction():
244 | return (pwm0_pos - pwm0_init)
245 |
246 |
247 | if __name__ == '__main__':
248 |
249 | channel = 0 # servo port number.
250 | while True:
251 | pwm.set_pwm(channel, 0, 150)
252 | time.sleep(1)
253 | pwm.set_pwm(channel, 0, 450)
254 | time.sleep(1)
255 |
256 |
--------------------------------------------------------------------------------
/server/appserverAP.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env/python
2 | # File name : appserverAP.py
3 | # Author : William
4 | # Date : 2019/10/28
5 |
6 | import socket
7 | import threading
8 | import time
9 | import os
10 | from rpi_ws281x import *
11 | import LED
12 | import move
13 | import servo
14 |
15 | LED = LED.LED()
16 | LED.colorWipe(Color(80,255,0))
17 |
18 | step_set = 1
19 | speed_set = 100
20 | rad = 0.6
21 |
22 | direction_command = 'no'
23 | turn_command = 'no'
24 | pos_input = 1
25 | catch_input = 1
26 | cir_input = 6
27 |
28 |
29 | def app_ctrl():
30 | app_HOST = ''
31 | app_PORT = 10123
32 | app_BUFSIZ = 1024
33 | app_ADDR = (app_HOST, app_PORT)
34 |
35 | def ap_thread():
36 | os.system("sudo create_ap wlan0 eth0 AdeeptCar 12345678")
37 |
38 | def setup():
39 | move.setup()
40 |
41 | def appCommand(data_input):
42 | global direction_command, turn_command, pos_input, catch_input, cir_input
43 | if data_input == 'forwardStart\n':
44 | direction_command = 'forward'
45 | move.move(speed_set, direction_command, turn_command, rad)
46 |
47 | elif data_input == 'backwardStart\n':
48 | direction_command = 'backward'
49 | move.move(speed_set, direction_command, turn_command, rad)
50 |
51 | elif data_input == 'leftStart\n':
52 | turn_command = 'left'
53 | move.move(speed_set, direction_command, turn_command, rad)
54 |
55 | elif data_input == 'rightStart\n':
56 | turn_command = 'right'
57 | move.move(speed_set, direction_command, turn_command, rad)
58 |
59 | elif 'forwardStop' in data_input:
60 | direction_command = 'no'
61 | move.move(speed_set, direction_command, turn_command, rad)
62 |
63 | elif 'backwardStop' in data_input:
64 | direction_command = 'no'
65 | move.move(speed_set, direction_command, turn_command, rad)
66 |
67 | elif 'leftStop' in data_input:
68 | turn_command = 'no'
69 | move.move(speed_set, direction_command, turn_command, rad)
70 |
71 | elif 'rightStop' in data_input:
72 | turn_command = 'no'
73 | move.move(speed_set, direction_command, turn_command, rad)
74 |
75 |
76 | if data_input == 'lookLeftStart\n':
77 | if cir_input < 12:
78 | cir_input+=1
79 | servo.cir_pos(cir_input)
80 |
81 | elif data_input == 'lookRightStart\n':
82 | if cir_input > 1:
83 | cir_input-=1
84 | servo.cir_pos(cir_input)
85 |
86 | elif data_input == 'downStart\n':
87 | servo.camera_ang('lookdown',10)
88 |
89 | elif data_input == 'upStart\n':
90 | servo.camera_ang('lookup',10)
91 |
92 | elif 'lookLeftStop' in data_input:
93 | pass
94 | elif 'lookRightStop' in data_input:
95 | pass
96 | elif 'downStop' in data_input:
97 | pass
98 | elif 'upStop' in data_input:
99 | pass
100 |
101 |
102 | if data_input == 'aStart\n':
103 | if pos_input < 17:
104 | pos_input+=1
105 | servo.hand_pos(pos_input)
106 |
107 | elif data_input == 'bStart\n':
108 | if pos_input > 1:
109 | pos_input-=1
110 | servo.hand_pos(pos_input)
111 |
112 | elif data_input == 'cStart\n':
113 | if catch_input < 13:
114 | catch_input+=3
115 | servo.catch(catch_input)
116 |
117 | elif data_input == 'dStart\n':
118 | if catch_input > 1:
119 | catch_input-=3
120 | servo.catch(catch_input)
121 |
122 | elif 'aStop' in data_input:
123 | pass
124 | elif 'bStop' in data_input:
125 | pass
126 | elif 'cStop' in data_input:
127 | pass
128 | elif 'dStop' in data_input:
129 | pass
130 |
131 | print(data_input)
132 |
133 | def appconnect():
134 | global AppCliSock, AppAddr
135 | try:
136 | s =socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
137 | s.connect(("1.1.1.1",80))
138 | ipaddr_check=s.getsockname()[0]
139 | s.close()
140 | print(ipaddr_check)
141 |
142 | AppSerSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
143 | AppSerSock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
144 | AppSerSock.bind(app_ADDR)
145 | AppSerSock.listen(5)
146 | print('waiting for App connection...')
147 | AppCliSock, AppAddr = AppSerSock.accept()
148 | print('...App connected from :', AppAddr)
149 | except:
150 | ap_threading=threading.Thread(target=ap_thread) #Define a thread for data receiving
151 | ap_threading.setDaemon(True) #'True' means it is a front thread,it would close when the mainloop() closes
152 | ap_threading.start() #Thread starts
153 |
154 | LED.colorWipe(Color(0,16,50))
155 | time.sleep(1)
156 | LED.colorWipe(Color(0,16,100))
157 | time.sleep(1)
158 | LED.colorWipe(Color(0,16,150))
159 | time.sleep(1)
160 | LED.colorWipe(Color(0,16,200))
161 | time.sleep(1)
162 | LED.colorWipe(Color(0,16,255))
163 | time.sleep(1)
164 | LED.colorWipe(Color(35,255,35))
165 |
166 | AppSerSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
167 | AppSerSock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
168 | AppSerSock.bind(app_ADDR)
169 | AppSerSock.listen(5)
170 | print('waiting for App connection...')
171 | AppCliSock, AppAddr = AppSerSock.accept()
172 | print('...App connected from :', AppAddr)
173 |
174 | appconnect()
175 | setup()
176 | app_threading=threading.Thread(target=appconnect) #Define a thread for FPV and OpenCV
177 | app_threading.setDaemon(True) #'True' means it is a front thread,it would close when the mainloop() closes
178 | app_threading.start() #Thread starts
179 |
180 | while 1:
181 | data = ''
182 | data = str(AppCliSock.recv(app_BUFSIZ).decode())
183 | if not data:
184 | continue
185 | appCommand(data)
186 | pass
187 |
188 | AppConntect_threading=threading.Thread(target=app_ctrl) #Define a thread for FPV and OpenCV
189 | AppConntect_threading.setDaemon(True) #'True' means it is a front thread,it would close when the mainloop() closes
190 | AppConntect_threading.start() #Thread starts
191 |
192 | if __name__ == '__main__':
193 | i = 1
194 | while 1:
195 | i += 1
196 | print(i)
197 | time.sleep(30)
198 | pass
--------------------------------------------------------------------------------
/server/dist/css/app.5a950261.css:
--------------------------------------------------------------------------------
1 | .appBar[data-v-2f6fc0b6]{-webkit-animation:shadowLight-data-v-2f6fc0b6 4s;animation:shadowLight-data-v-2f6fc0b6 4s;-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite;-webkit-animation-direction:alternate;animation-direction:alternate;z-index:100;-webkit-box-shadow:0 -.2rem .7rem .1rem #b1b1b1;box-shadow:0 -.2rem .7rem .1rem #b1b1b1}@-webkit-keyframes shadowLight-data-v-2f6fc0b6{0%{-webkit-box-shadow:0 -.2rem .7rem .1rem #646464;box-shadow:0 -.2rem .7rem .1rem #646464}to{-webkit-box-shadow:0 .2rem .7rem .1rem #b1b1b1;box-shadow:0 .2rem .7rem .1rem #b1b1b1}}@keyframes shadowLight-data-v-2f6fc0b6{0%{-webkit-box-shadow:0 -.2rem .7rem .1rem #646464;box-shadow:0 -.2rem .7rem .1rem #646464}to{-webkit-box-shadow:0 .2rem .7rem .1rem #b1b1b1;box-shadow:0 .2rem .7rem .1rem #b1b1b1}}.mod-wrapper[data-v-68bf214e] .v-input__slider{margin-bottom:-.5rem}.mod-wrapper[data-v-68bf214e] .v-input__slider .v-label{border-radius:.3rem;background-color:#f0f0f0;padding:0 .3rem;margin:0}.mod-wrapper[data-v-68bf214e] .v-input__slider .v-slider{margin:0 .8rem}.mod-wrapper[data-v-68bf214e] .v-input__slider .v-slider .v-slider__track-fill{background-color:#263238!important}.mod-wrapper[data-v-68bf214e] .v-input__slider .v-slider .v-slider__track-background{background-color:#fff!important}.mod-wrapper[data-v-68bf214e] .v-input__slider .v-slider .v-slider__thumb,.mod-wrapper[data-v-68bf214e] .v-input__slider .v-slider .v-slider__thumb:before{background-color:#fafafa!important}.mod-wrapper[data-v-68bf214e] .v-input__slider .v-slider .v-slider__thumb-label{color:#aaa!important;background-color:#ededed!important}.mod-sheet[data-v-68bf214e]{border-radius:.4rem .4rem;-webkit-box-shadow:0 0 .7rem .25rem hsla(0,0%,100%,.7);box-shadow:0 0 .7rem .25rem hsla(0,0%,100%,.7)}.mod-sheet .mod-title[data-v-68bf214e]{border-radius:.4rem .4rem 0 0;padding:.2rem 1rem 0 .8rem;font-weight:500;margin:0;background-color:#fff;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.mod-sheet .mod-wrapper[data-v-68bf214e]{border-radius:0 0 .4rem .4rem;width:100%;padding:.1px 1rem .6rem 1rem;background-color:#cfd8dc}.vedio-wrapper[data-v-024a6bab]{position:relative;overflow:hidden;border-radius:.4rem;height:0;width:100%;padding-bottom:75%;margin-top:.5rem}.vedio-wrapper .draw-area[data-v-024a6bab]{position:absolute;top:0;padding-bottom:75%;width:100%}.vedio-wrapper .vedio[data-v-024a6bab]{top:.5rem;margin-bottom:-8px;width:100%}.vedio-wrapper .canvas[data-v-024a6bab]{width:100%}.status-wrapper[data-v-05264423]{margin:0 -.3rem;-ms-flex-wrap:wrap;flex-wrap:wrap}.status-wrapper .chips[data-v-05264423],.status-wrapper[data-v-05264423]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.status-wrapper .chips[data-v-05264423]{-webkit-box-shadow:#000 0 0 .1rem 1px;box-shadow:0 0 .1rem 1px #000;width:100%;margin:0!important;margin-top:.4rem!important;padding:0 4%}.status-wrapper .chips .chip-title[data-v-05264423]{padding-right:.3rem}.buttons[data-v-726ac712]{margin-top:.5rem;min-width:0!important}.button-child[data-v-b4e411fa]{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;width:100%}.button-child .buttons[data-v-b4e411fa]{margin-top:.5rem}.CVFL-wrapper[data-v-38858175]{display:-webkit-box;display:-ms-flexbox;display:flex}.CVFL-wrapper .sliders[data-v-38858175]{width:75%}.CVFL-wrapper .sliders[data-v-38858175] label{margin:0}.CVFL-wrapper .sliders[data-v-38858175] .v-input{margin-left:0!important;margin-right:0!important}.CVFL-wrapper .CVFL-bottons[data-v-38858175]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-ms-flex-pack:distribute;justify-content:space-around;width:25%}.CVFL-wrapper .CVFL-bottons .button[data-v-38858175]{width:100%}.CVFL-wrapper .colorButton[data-v-38858175]{position:relative;overflow:hidden}.CVFL-wrapper .colorButton[data-v-38858175]:after{content:"";width:100%;height:100%;position:absolute;top:0;left:0;border-bottom:5px solid #bfbfbf;border-color:inherit;-webkit-transform-origin:top left}.colorSelecter[data-v-38858175] .v-color-picker__swatch{width:16%;padding:0 1%}.colorSelecter[data-v-38858175] .v-color-picker__color{width:100%}.color-picker-child[data-v-3dbdf3cf] .v-color-picker__swatch{width:16%;padding:0 1%}.color-picker-child[data-v-3dbdf3cf] .v-color-picker__color{width:100%}.FC-bottons[data-v-5a57ef1d]{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;width:100%}.FC-bottons .button[data-v-5a57ef1d]{margin-top:.5rem;width:100%}.colorButton[data-v-5a57ef1d]{position:relative;overflow:hidden}.colorButton[data-v-5a57ef1d]:after{content:"";width:100%;height:100%;position:absolute;top:0;left:0;border-bottom:5px solid #bfbfbf;border-color:inherit;-webkit-transform-origin:top left}.expansion[data-v-4404e3bc]{-webkit-user-select:text;-moz-user-select:text;-ms-user-select:text;user-select:text;padding-top:.5rem}.expansion .v-expansion-panel-header[data-v-4404e3bc]{font-weight:650}.area-bg[data-v-ff914742]{display:-webkit-box;display:-ms-flexbox;display:flex;position:absolute;min-height:100%;width:100%;background:url(/api/img/bg.jpg) fixed top}.area-wrapper[data-v-ff914742]{margin:0 auto;min-height:100%;min-width:320px;width:85rem;max-width:85rem;background-color:#263238}.innerRow[data-v-ff914742]{margin:-12px}.controll-area[data-v-ff914742]{min-height:100%;max-width:80rem}.controll-area .sheets[data-v-ff914742]{background-color:#b0bec5}.light[data-v-b9aab66e]{position:absolute;-webkit-transition:margin-left linear;transition:margin-left linear;width:0;-webkit-box-shadow:0 0 .9rem .1rem #c7c7c7;box-shadow:0 0 .9rem .1rem #c7c7c7}::-webkit-scrollbar{display:none}html{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-ms-touch-action:manipulation;touch-action:manipulation}.col{-ms-flex-preferred-size:auto;flex-basis:auto}
2 |
3 | /*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{-webkit-box-sizing:content-box;box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{-webkit-box-sizing:border-box;box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}[hidden],template{display:none}
--------------------------------------------------------------------------------
/server/FPV.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env/python3
2 | # File name : server.py
3 | # Description : for FPV video and OpenCV functions
4 | # Website : www.adeept.com
5 | # E-mail : support@adeept.com
6 | # Author : William(Based on Adrian Rosebrock's OpenCV code on pyimagesearch.com)
7 | # Date : 2018/08/22
8 |
9 | import time
10 | import threading
11 | import cv2
12 | import zmq
13 | import base64
14 | import picamera
15 | from picamera.array import PiRGBArray
16 | import argparse
17 | import imutils
18 | from collections import deque
19 | import psutil
20 | import os
21 | import servo
22 | import PID
23 | import LED
24 | import datetime
25 | from rpi_ws281x import *
26 | import move
27 |
28 | pid = PID.PID()
29 | pid.SetKp(0.5)
30 | pid.SetKd(0)
31 | pid.SetKi(0)
32 | Y_lock = 0
33 | X_lock = 0
34 | tor = 17
35 | FindColorMode = 0
36 | WatchDogMode = 0
37 | UltraData = 3
38 | LED = LED.LED()
39 |
40 | class FPV:
41 | def __init__(self):
42 | self.frame_num = 0
43 | self.fps = 0
44 |
45 | self.colorUpper = (44, 255, 255)
46 | self.colorLower = (24, 100, 100)
47 |
48 |
49 | def SetIP(self,invar):
50 | self.IP = invar
51 |
52 |
53 | def FindColor(self,invar):
54 | global FindColorMode
55 | FindColorMode = invar
56 | if not FindColorMode:
57 | servo.camera_ang('home',0)
58 |
59 |
60 | def WatchDog(self,invar):
61 | global WatchDogMode
62 | WatchDogMode = invar
63 |
64 |
65 | def UltraData(self,invar):
66 | global UltraData
67 | UltraData = invar
68 |
69 |
70 | def capture_thread(self,IPinver):
71 | ap = argparse.ArgumentParser() #OpenCV initialization
72 | ap.add_argument("-b", "--buffer", type=int, default=64,
73 | help="max buffer size")
74 | args = vars(ap.parse_args())
75 | pts = deque(maxlen=args["buffer"])
76 |
77 | font = cv2.FONT_HERSHEY_SIMPLEX
78 |
79 | camera = picamera.PiCamera()
80 | camera.resolution = (640, 480)
81 | camera.framerate = 20
82 | rawCapture = PiRGBArray(camera, size=(640, 480))
83 |
84 | context = zmq.Context()
85 | footage_socket = context.socket(zmq.PUB)
86 | print(IPinver)
87 | footage_socket.connect('tcp://%s:5555'%IPinver)
88 |
89 | avg = None
90 | motionCounter = 0
91 | #time.sleep(4)
92 | lastMovtionCaptured = datetime.datetime.now()
93 |
94 | for frame in camera.capture_continuous(rawCapture, format="bgr", use_video_port=True):
95 | frame_image = frame.array
96 | cv2.line(frame_image,(300,240),(340,240),(128,255,128),1)
97 | cv2.line(frame_image,(320,220),(320,260),(128,255,128),1)
98 | timestamp = datetime.datetime.now()
99 |
100 | if FindColorMode:
101 |
102 | ####>>>OpenCV Start<<<####
103 | hsv = cv2.cvtColor(frame_image, cv2.COLOR_BGR2HSV)
104 | mask = cv2.inRange(hsv, self.colorLower, self.colorUpper)
105 | mask = cv2.erode(mask, None, iterations=2)
106 | mask = cv2.dilate(mask, None, iterations=2)
107 | cnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL,
108 | cv2.CHAIN_APPROX_SIMPLE)[-2]
109 | center = None
110 | if len(cnts) > 0:
111 | cv2.putText(frame_image,'Target Detected',(40,60), font, 0.5,(255,255,255),1,cv2.LINE_AA)
112 | c = max(cnts, key=cv2.contourArea)
113 | ((x, y), radius) = cv2.minEnclosingCircle(c)
114 | M = cv2.moments(c)
115 | center = (int(M["m10"] / M["m00"]), int(M["m01"] / M["m00"]))
116 | X = int(x)
117 | Y = int(y)
118 | if radius > 10:
119 | cv2.rectangle(frame_image,(int(x-radius),int(y+radius)),(int(x+radius),int(y-radius)),(255,255,255),1)
120 |
121 | if Y < (240-tor):
122 | error = (240-Y)/5
123 | outv = int(round((pid.GenOut(error)),0))
124 | servo.camera_ang('lookup',outv)
125 | Y_lock = 0
126 | elif Y > (240+tor):
127 | error = (Y-240)/5
128 | outv = int(round((pid.GenOut(error)),0))
129 | servo.camera_ang('lookdown',outv)
130 | Y_lock = 0
131 | else:
132 | Y_lock = 1
133 |
134 |
135 | if X < (320-tor*3):
136 | move.move(70, 'no', 'left', 0.6)
137 | #time.sleep(0.1)
138 | #move.motorStop()
139 | X_lock = 0
140 | elif X > (330+tor*3):
141 | move.move(70, 'no', 'right', 0.6)
142 | #time.sleep(0.1)
143 | #move.motorStop()
144 | X_lock = 0
145 | else:
146 | move.motorStop()
147 | X_lock = 1
148 |
149 | if X_lock == 1 and Y_lock == 1:
150 | if UltraData > 0.5:
151 | LED.colorWipe(Color(255,16,0))
152 | move.move(70, 'forward', 'no', 0.6)
153 | elif UltraData < 0.4:
154 | LED.colorWipe(Color(0,16,255))
155 | move.move(70, 'backward', 'no', 0.6)
156 | print(UltraData)
157 | else:
158 | move.motorStop()
159 |
160 |
161 | else:
162 | cv2.putText(frame_image,'Target Detecting',(40,60), font, 0.5,(255,255,255),1,cv2.LINE_AA)
163 | move.motorStop()
164 |
165 | for i in range(1, len(pts)):
166 | if pts[i - 1] is None or pts[i] is None:
167 | continue
168 | thickness = int(np.sqrt(args["buffer"] / float(i + 1)) * 2.5)
169 | cv2.line(frame_image, pts[i - 1], pts[i], (0, 0, 255), thickness)
170 | ####>>>OpenCV Ends<<<####
171 |
172 |
173 | if WatchDogMode:
174 | gray = cv2.cvtColor(frame_image, cv2.COLOR_BGR2GRAY)
175 | gray = cv2.GaussianBlur(gray, (21, 21), 0)
176 |
177 | if avg is None:
178 | print("[INFO] starting background model...")
179 | avg = gray.copy().astype("float")
180 | rawCapture.truncate(0)
181 | continue
182 |
183 | cv2.accumulateWeighted(gray, avg, 0.5)
184 | frameDelta = cv2.absdiff(gray, cv2.convertScaleAbs(avg))
185 |
186 | # threshold the delta image, dilate the thresholded image to fill
187 | # in holes, then find contours on thresholded image
188 | thresh = cv2.threshold(frameDelta, 5, 255,
189 | cv2.THRESH_BINARY)[1]
190 | thresh = cv2.dilate(thresh, None, iterations=2)
191 | cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,
192 | cv2.CHAIN_APPROX_SIMPLE)
193 | cnts = imutils.grab_contours(cnts)
194 | #print('x')
195 |
196 | # loop over the contours
197 | for c in cnts:
198 | # if the contour is too small, ignore it
199 | if cv2.contourArea(c) < 5000:
200 | continue
201 |
202 | # compute the bounding box for the contour, draw it on the frame,
203 | # and update the text
204 | (x, y, w, h) = cv2.boundingRect(c)
205 | cv2.rectangle(frame_image, (x, y), (x + w, y + h), (128, 255, 0), 1)
206 | text = "Occupied"
207 | motionCounter += 1
208 | #print(motionCounter)
209 | #print(text)
210 | LED.colorWipe(Color(255,16,0))
211 | lastMovtionCaptured = timestamp
212 |
213 | if (timestamp - lastMovtionCaptured).seconds >= 0.5:
214 | LED.colorWipe(Color(0,16,255))
215 |
216 |
217 | encoded, buffer = cv2.imencode('.jpg', frame_image)
218 | jpg_as_text = base64.b64encode(buffer)
219 | footage_socket.send(jpg_as_text)
220 |
221 | rawCapture.truncate(0)
222 |
223 |
224 | if __name__ == '__main__':
225 | fpv=FPV()
226 | while 1:
227 | fpv.capture_thread('192.168.0.110')
228 | pass
229 |
230 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python3
2 | # coding=utf-8
3 | # File name : setup.py
4 | # Author : Devin
5 |
6 | import os
7 | import time
8 | import subprocess
9 |
10 | username = os.popen("echo ${SUDO_USER:-$(who -m | awk '{ print $1 }')}").readline().strip() # pi
11 | user_home = os.popen('getent passwd %s | cut -d: -f 6'%username).readline().strip() # home
12 |
13 | curpath = os.path.realpath(__file__)
14 | thisPath = "/" + os.path.dirname(curpath)
15 |
16 | print(thisPath)
17 |
18 | def replace_num(file,initial,new_num):
19 | newline=""
20 | str_num=str(new_num)
21 | with open(file,"r") as f:
22 | for line in f.readlines():
23 | if(line.find(initial) == 0):
24 | line = (str_num+'\n')
25 | newline += line
26 | with open(file,"w") as f:
27 | f.writelines(newline)
28 |
29 |
30 | def run_command(cmd=""):
31 | import subprocess
32 | p = subprocess.Popen(
33 | cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
34 | result = p.stdout.read().decode('utf-8')
35 | status = p.poll()
36 | return status, result
37 |
38 | def check_rpi_model():
39 | _, result = run_command("cat /proc/device-tree/model |awk '{print $3}'")
40 | result = result.strip()
41 | if result == '3':
42 | return int(3)
43 | elif result == '4':
44 | return int(4)
45 | else:
46 | return None
47 |
48 | def check_raspbain_version():
49 | _, result = run_command("cat /etc/debian_version|awk -F. '{print $1}'")
50 | return int(result.strip())
51 |
52 | def check_python_version():
53 | import sys
54 | major = int(sys.version_info.major)
55 | minor = int(sys.version_info.minor)
56 | micro = int(sys.version_info.micro)
57 | return major, minor, micro
58 |
59 | def check_os_bit():
60 | '''
61 | # import platform
62 | # machine_type = platform.machine()
63 | latest bullseye uses a 64-bit kernel
64 | This method is no longer applicable, the latest raspbian will uses 64-bit kernel
65 | (kernel 6.1.x) by default, "uname -m" shows "aarch64",
66 | but the system is still 32-bit.
67 | '''
68 | _ , os_bit = run_command("getconf LONG_BIT")
69 | return int(os_bit)
70 |
71 | def check_systemctl_service(service_name):
72 | return subprocess.run(
73 | ["systemctl", "is-active", service_name],
74 | capture_output=True, text=True
75 | ).stdout.strip() == "active"
76 |
77 |
78 | commands_apt = [
79 | "sudo apt-get update",
80 | "sudo apt-get install python3-gpiozero python3-pigpio",
81 | "sudo apt-get install -y python3-pyqt5 python3-opengl",
82 | "sudo apt-get install -y python3-picamera2",
83 | "sudo apt-get install -y python3-opencv",
84 | "sudo apt-get install -y opencv-data",
85 | "sudo apt-get install -y python3-pyaudio"
86 | ]
87 | mark_apt = 0
88 | for x in range(3):
89 | for command in commands_apt:
90 | if os.system(command) != 0:
91 | print("Error running installation step apt")
92 | mark_apt = 1
93 | if mark_apt == 0:
94 | break
95 |
96 | commands_pip_1 = [
97 | "sudo pip3 install adafruit-circuitpython-motor",
98 | "sudo pip3 install adafruit-circuitpython-pca9685",
99 | "sudo pip3 install flask",
100 | "sudo pip3 install flask_cors",
101 | "sudo pip3 install numpy",
102 | "sudo pip3 install pyzmq",
103 | "sudo pip3 install imutils zmq pybase64 psutil",
104 | "sudo pip3 install websockets==13.0",
105 | "sudo pip3 install rpi_ws281x",
106 | "sudo pip3 install adafruit-circuitpython-ads7830",
107 | "sudo pip3 install adafruit-pca9685"
108 | ]
109 | commands_pip_2 = [
110 | "sudo pip3 install adafruit-circuitpython-motor --break-system-packages",
111 | "sudo pip3 install adafruit-circuitpython-pca9685 --break-system-packages",
112 | "sudo pip3 install flask --break-system-packages",
113 | "sudo pip3 install flask_cors --break-system-packages",
114 | "sudo pip3 install numpy --break-system-packages",
115 | "sudo pip3 install pyzmq --break-system-packages",
116 | "sudo pip3 install imutils zmq pybase64 psutil --break-system-packages",
117 | "sudo pip3 install websockets==13.0 --break-system-packages",
118 | "sudo pip3 install rpi_ws281x --break-system-packages",
119 | "sudo pip3 install adafruit-circuitpython-ads7830 --break-system-packages",
120 | "sudo pip3 install adafruit-pca9685 --break-system-packages"
121 | ]
122 | mark_pip = 0
123 | OS_version = check_raspbain_version()
124 | if OS_version <= 11:
125 | for x in range(3):
126 | for command in commands_pip_1:
127 | if os.system(command) != 0:
128 | print("Error running installation step pip")
129 | mark_pip = 1
130 | if mark_pip == 0:
131 | break
132 | else:
133 | for x in range(3):
134 | for command in commands_pip_2:
135 | if os.system(command) != 0:
136 | print("Error running installation step pip")
137 | mark_pip = 1
138 | if mark_pip == 0:
139 | break
140 |
141 |
142 | wifi_service_name="wifi-hotspot-manager.service"
143 | if not check_systemctl_service(wifi_service_name):
144 | # wifi and hotspot switch script
145 | os.system(f"sudo cp {thisPath}/wifi_hotspot_manager.sh /home/pi")
146 | os.system("sudo chmod +x /home/pi/wifi_hotspot_manager.sh")
147 |
148 |
149 | wifi_service_content="""[Unit]
150 | Description=WiFi and Hotspot Manager Service
151 | After=network.target NetworkManager.service
152 | Wants=NetworkManager.service
153 |
154 | [Service]
155 | Type=oneshot
156 | ExecStart=/home/pi/wifi_hotspot_manager.sh
157 | User=root
158 | RemainAfterExit=yes
159 |
160 | [Install]
161 | WantedBy=multi-user.target
162 | """
163 | # system-level services must be placed in this directory
164 | wifi_service_file_path = "/etc/systemd/system/" + wifi_service_name
165 |
166 | try:
167 | # Write to the service file (requires root privileges)
168 | with open(wifi_service_file_path, "w") as f:
169 | f.write(wifi_service_content)
170 | print(f"Service file created: {wifi_service_file_path}")
171 |
172 | # Set file permissions
173 | os.chmod(wifi_service_file_path, 0o644)
174 |
175 | # Reload systemd configuration, enable and start the service
176 | subprocess.run(["sudo", "systemctl", "daemon-reload"], check=True)
177 | subprocess.run(["sudo", "systemctl", "enable", wifi_service_name], check=True)
178 |
179 | print(f"Service {wifi_service_name} has been enabled and started")
180 | except subprocess.CalledProcessError as e:
181 | print(f"Command execution failed: {e}")
182 | except Exception as e:
183 | print(f"An error occurred: {e}")
184 |
185 |
186 | robot_service_name="Adeept_Robot.service"
187 | if not check_systemctl_service(robot_service_name):
188 | # auto start script
189 | try:
190 | os.system("sudo touch /"+ user_home +"/startup.sh")
191 | with open("/"+ user_home +"/startup.sh",'w') as file_to_write:
192 | #you can choose how to control the robot
193 | file_to_write.write("#!/bin/sh\nsleep 5\nsudo python3 " + thisPath + "/server/webServer.py")
194 | except:
195 | pass
196 | os.system("sudo chmod 777 /"+ user_home +"/startup.sh")
197 |
198 | #config systemctl service
199 | # Define the content of the systemd service file
200 | robot_service_content=f"""[Unit]
201 | Description=Auto-start robot control script
202 | After={wifi_service_name}
203 |
204 | [Service]
205 | Type=simple
206 | User=root
207 | WorkingDirectory=/home/pi
208 | ExecStart=/home/pi/startup.sh
209 | Restart=no
210 |
211 | [Install]
212 | WantedBy=multi-user.target
213 | """
214 |
215 | # Path for the service file (system-level services must be placed in this directory)
216 | robot_service_file_path = "/etc/systemd/system/" + robot_service_name
217 |
218 | try:
219 | # Write to the service file (requires root privileges)
220 | with open(robot_service_file_path, "w") as f:
221 | f.write(robot_service_content)
222 | print(f"Service file created: {robot_service_file_path}")
223 |
224 | # Set file permissions
225 | os.chmod(robot_service_file_path, 0o644)
226 |
227 | # Reload systemd configuration, enable and start the service
228 | subprocess.run(["sudo", "systemctl", "daemon-reload"], check=True)
229 | subprocess.run(["sudo", "systemctl", "enable", robot_service_name], check=True)
230 |
231 | print(f"Service {robot_service_name} has been enabled and started")
232 | except subprocess.CalledProcessError as e:
233 | print(f"Command execution failed: {e}")
234 | except Exception as e:
235 | print(f"An error occurred: {e}")
236 |
237 |
238 | print('The program in Raspberry Pi has been installed, disconnected and restarted. \nYou can now power off the Raspberry Pi to install the camera and driver board (Robot HAT). \nAfter turning on again, the Raspberry Pi will automatically run the program to set the servos port signal to turn the servos to the middle position, which is convenient for mechanical assembly.')
239 | print('restarting...')
240 | os.system("sudo reboot")
241 |
--------------------------------------------------------------------------------
/server/appserver.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env/python
2 | # File name : server.py
3 | # Production : Gtank
4 | # Website : www.gewbot.com
5 | # E-mail : gewubot@163.com
6 | # Author : William
7 | # Date : 2019/10/28
8 |
9 | import socket
10 | import threading
11 | import time
12 | import os
13 | import LED
14 | import move
15 | import servo
16 | import switch
17 | servo.servo_init()
18 | switch.switchSetup()
19 | switch.set_all_switch_off()
20 | LED = LED.LED()
21 | LED.colorWipe(80,255,0)
22 |
23 | step_set = 1
24 | speed_set = 100
25 | rad = 0.6
26 |
27 | direction_command = 'no'
28 | turn_command = 'no'
29 | servo_command = 'no'
30 | pos_input = 1
31 | catch_input = 1
32 | cir_input = 6
33 |
34 | servo_speed = 11
35 |
36 |
37 | class Servo_ctrl(threading.Thread):
38 | def __init__(self, *args, **kwargs):
39 | super(Servo_ctrl, self).__init__(*args, **kwargs)
40 | self.__flag = threading.Event() # 用于暂停线程的标识
41 | self.__flag.set() # 设置为True
42 | self.__running = threading.Event() # 用于停止线程的标识
43 | self.__running.set() # 将running设置为True
44 |
45 | def run(self):
46 | while self.__running.isSet():
47 | self.__flag.wait() # 为True时立即返回, 为False时阻塞直到内部的标识位为True后返回
48 | if servo_command == 'lookleft':
49 | servo.lookleft(servo_speed)
50 | elif servo_command == 'lookright':
51 | servo.lookright(servo_speed)
52 | elif servo_command == 'up':
53 | servo.up(servo_speed)
54 | elif servo_command == 'down':
55 | servo.down(servo_speed)
56 | elif servo_command == 'lookup':
57 | servo.lookup(servo_speed)
58 | elif servo_command == 'lookdown':
59 | servo.lookdown(servo_speed)
60 | elif servo_command == 'grab':
61 | servo.grab(servo_speed)
62 | elif servo_command == 'loose':
63 | servo.loose(servo_speed)
64 | else:
65 | pass
66 | time.sleep(0.07)
67 |
68 | def pause(self):
69 | self.__flag.clear() # 设置为False, 让线程阻塞
70 |
71 | def resume(self):
72 | self.__flag.set() # 设置为True, 让线程停止阻塞
73 |
74 | def stop(self):
75 | self.__flag.set() # 将线程从暂停状态恢复, 如何已经暂停的话
76 | self.__running.clear() # 设置为False
77 |
78 |
79 | def app_ctrl():
80 | global servo_move
81 | app_HOST = ''
82 | app_PORT = 10123
83 | app_BUFSIZ = 1024
84 | app_ADDR = (app_HOST, app_PORT)
85 |
86 | servo_move = Servo_ctrl()
87 | servo_move.start()
88 | servo_move.pause()
89 |
90 | def ap_thread():
91 | os.system("sudo create_ap wlan0 eth0 Groovy 12345678")
92 |
93 | def setup():
94 | move.setup()
95 |
96 | def appCommand(data_input):
97 | global direction_command, turn_command, servo_command
98 | if data_input == 'forwardStart\n':
99 | direction_command = 'forward'
100 | move.move(speed_set, direction_command, turn_command, rad)
101 |
102 | elif data_input == 'backwardStart\n':
103 | direction_command = 'backward'
104 | move.move(speed_set, direction_command, turn_command, rad)
105 |
106 | elif data_input == 'leftStart\n':
107 | turn_command = 'left'
108 | move.move(speed_set, direction_command, turn_command, rad)
109 |
110 | elif data_input == 'rightStart\n':
111 | turn_command = 'right'
112 | move.move(speed_set, direction_command, turn_command, rad)
113 |
114 | elif 'forwardStop' in data_input:
115 | direction_command = 'no'
116 | move.move(speed_set, direction_command, turn_command, rad)
117 |
118 | elif 'backwardStop' in data_input:
119 | direction_command = 'no'
120 | move.move(speed_set, direction_command, turn_command, rad)
121 |
122 | elif 'leftStop' in data_input:
123 | turn_command = 'no'
124 | move.move(speed_set, direction_command, turn_command, rad)
125 |
126 | elif 'rightStop' in data_input:
127 | turn_command = 'no'
128 | move.move(speed_set, direction_command, turn_command, rad)
129 |
130 |
131 | if data_input == 'lookLeftStart\n':
132 | servo_command = 'lookleft'
133 | servo_move.resume()
134 |
135 | elif data_input == 'lookRightStart\n':
136 | servo_command = 'lookright'
137 | servo_move.resume()
138 |
139 | elif data_input == 'downStart\n':
140 | servo_command = 'down'
141 | servo_move.resume()
142 |
143 | elif data_input == 'upStart\n':
144 | servo_command = 'up'
145 | servo_move.resume()
146 |
147 | elif 'lookLeftStop' in data_input:
148 | servo_move.pause()
149 | servo_command = 'no'
150 | elif 'lookRightStop' in data_input:
151 | servo_move.pause()
152 | servo_command = 'no'
153 | elif 'downStop' in data_input:
154 | servo_move.pause()
155 | servo_command = 'no'
156 | elif 'upStop' in data_input:
157 | servo_move.pause()
158 | servo_command = 'no'
159 |
160 |
161 | if data_input == 'aStart\n':
162 | servo_command = 'grab'
163 | servo_move.resume()
164 |
165 | elif data_input == 'bStart\n':
166 | servo_command = 'loose'
167 | servo_move.resume()
168 |
169 | elif data_input == 'cStart\n':
170 | switch.switch(1,1)
171 | switch.switch(2,1)
172 | switch.switch(3,1)
173 |
174 | elif data_input == 'dStart\n':
175 | switch.switch(1,0)
176 | switch.switch(2,0)
177 | switch.switch(3,0)
178 |
179 | elif 'aStop' in data_input:
180 | servo_move.pause()
181 | servo_command = 'no'
182 | elif 'bStop' in data_input:
183 | servo_move.pause()
184 | servo_command = 'no'
185 | elif 'cStop' in data_input:
186 | pass
187 | elif 'dStop' in data_input:
188 | pass
189 |
190 | print(data_input)
191 |
192 | def appconnect():
193 | global AppCliSock, AppAddr
194 | try:
195 | s =socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
196 | s.connect(("1.1.1.1",80))
197 | ipaddr_check=s.getsockname()[0]
198 | s.close()
199 | print(ipaddr_check)
200 |
201 | AppSerSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
202 | AppSerSock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
203 | AppSerSock.bind(app_ADDR)
204 | AppSerSock.listen(5)
205 | print('waiting for App connection...')
206 | AppCliSock, AppAddr = AppSerSock.accept()
207 | print('...App connected from :', AppAddr)
208 | except:
209 | ap_threading=threading.Thread(target=ap_thread) #Define a thread for data receiving
210 | ap_threading.setDaemon(True) #'True' means it is a front thread,it would close when the mainloop() closes
211 | ap_threading.start() #Thread starts
212 |
213 | LED.colorWipe(0,16,50)
214 | time.sleep(1)
215 | LED.colorWipe(0,16,100)
216 | time.sleep(1)
217 | LED.colorWipe(0,16,150)
218 | time.sleep(1)
219 | LED.colorWipe(0,16,200)
220 | time.sleep(1)
221 | LED.colorWipe(0,16,255)
222 | time.sleep(1)
223 | LED.colorWipe(35,255,35)
224 |
225 | AppSerSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
226 | AppSerSock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
227 | AppSerSock.bind(app_ADDR)
228 | AppSerSock.listen(5)
229 | print('waiting for App connection...')
230 | AppCliSock, AppAddr = AppSerSock.accept()
231 | print('...App connected from :', AppAddr)
232 |
233 | appconnect()
234 | setup()
235 | app_threading=threading.Thread(target=appconnect) #Define a thread for FPV and OpenCV
236 | app_threading.setDaemon(True) #'True' means it is a front thread,it would close when the mainloop() closes
237 | app_threading.start() #Thread starts
238 |
239 | while 1:
240 | data = ''
241 | data = str(AppCliSock.recv(app_BUFSIZ).decode())
242 | if not data:
243 | continue
244 | appCommand(data)
245 | pass
246 |
247 | AppConntect_threading=threading.Thread(target=app_ctrl) #Define a thread for FPV and OpenCV
248 | AppConntect_threading.setDaemon(True) #'True' means it is a front thread,it would close when the mainloop() closes
249 | AppConntect_threading.start() #Thread starts
250 |
251 | if __name__ == '__main__':
252 | i = 1
253 | try:
254 | while 1:
255 | i += 1
256 | print(i)
257 | time.sleep(30)
258 | pass
259 | except:
260 | servo_move.stop()
261 | move.move(0, 'no', 'no', rad)
262 | LED.colorWipe(0,0,0)
--------------------------------------------------------------------------------
/server/RPIservo.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # File name : servo.py
3 | # Description : Control Servos
4 | # Author : William
5 | # Date : 2019/02/23
6 | from __future__ import division
7 | import time
8 | import RPi.GPIO as GPIO
9 | import sys
10 | import Adafruit_PCA9685
11 | import threading
12 |
13 | import random
14 | '''
15 | change this form 1 to -1 to reverse servos
16 | '''
17 | pwm = Adafruit_PCA9685.PCA9685(address=0x40, busnum=1)
18 | pwm.set_pwm_freq(50)
19 |
20 | init_pwm0 = 300
21 | init_pwm1 = 300
22 | init_pwm2 = 300
23 | init_pwm3 = 300
24 |
25 | init_pwm4 = 300
26 | init_pwm5 = 300
27 | init_pwm6 = 300
28 | init_pwm7 = 300
29 |
30 | init_pwm8 = 300
31 | init_pwm9 = 300
32 | init_pwm10 = 300
33 | init_pwm11 = 300
34 |
35 | init_pwm12 = 300
36 | init_pwm13 = 300
37 | init_pwm14 = 300
38 | init_pwm15 = 300
39 |
40 | class ServoCtrl(threading.Thread):
41 |
42 | def __init__(self, *args, **kwargs):
43 | self.sc_direction = [1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1]
44 | self.initPos = [init_pwm0,init_pwm1,init_pwm2,init_pwm3,
45 | init_pwm4,init_pwm5,init_pwm6,init_pwm7,
46 | init_pwm8,init_pwm9,init_pwm10,init_pwm11,
47 | init_pwm12,init_pwm13,init_pwm14,init_pwm15]
48 | self.goalPos = [300,300,300,300, 300,300,300,300 ,300,300,300,300 ,300,300,300,300]
49 | self.nowPos = [300,300,300,300, 300,300,300,300 ,300,300,300,300 ,300,300,300,300]
50 | self.bufferPos = [300.0,300.0,300.0,300.0, 300.0,300.0,300.0,300.0 ,300.0,300.0,300.0,300.0 ,300.0,300.0,300.0,300.0]
51 | self.lastPos = [300,300,300,300, 300,300,300,300 ,300,300,300,300 ,300,300,300,300]
52 | self.ingGoal = [300,300,300,300, 300,300,300,300 ,300,300,300,300 ,300,300,300,300]
53 | # self.maxPos = [560,560,560,560, 560,560,560,560 ,560,560,560,560 ,560,560,560,560]
54 | self.maxPos = [520,520,520,520, 520,520,520,520 ,520,520,520,520 ,520,520,520,520]
55 | self.minPos = [100,100,100,100, 100,100,100,100 ,100,100,100,100 ,100,100,100,100]
56 | self.scSpeed = [0,0,0,0, 0,0,0,0 ,0,0,0,0 ,0,0,0,0]
57 |
58 | # self.ctrlRangeMax = 560
59 | self.ctrlRangeMax = 520
60 | self.ctrlRangeMin = 100
61 | self.angleRange = 180
62 |
63 | '''
64 | scMode: 'init' 'auto' 'certain' 'quick' 'wiggle'
65 | '''
66 | self.scMode = 'auto'
67 | self.scTime = 2.0
68 | self.scSteps = 30
69 |
70 | self.scDelay = 0.037
71 | self.scMoveTime = 0.037
72 |
73 | self.goalUpdate = 0
74 | self.wiggleID = 0
75 | self.wiggleDirection = 1
76 |
77 | super(ServoCtrl, self).__init__(*args, **kwargs)
78 | self.__flag = threading.Event()
79 | self.__flag.clear()
80 |
81 |
82 | def pause(self):
83 | print('......................pause..........................')
84 | self.__flag.clear()
85 |
86 |
87 | def resume(self):
88 | print('resume')
89 | self.__flag.set()
90 |
91 |
92 | def moveInit(self):
93 | self.scMode = 'init'
94 | for i in range(0,16):
95 | pwm.set_pwm(i,0,self.initPos[i])
96 | self.lastPos[i] = self.initPos[i]
97 | self.nowPos[i] = self.initPos[i]
98 | self.bufferPos[i] = float(self.initPos[i])
99 | self.goalPos[i] = self.initPos[i]
100 | self.pause()
101 |
102 |
103 | def initConfig(self, ID, initInput, moveTo):
104 | if initInput > self.minPos[ID] and initInput < self.maxPos[ID]:
105 | self.initPos[ID] = initInput
106 | if moveTo:
107 | pwm.set_pwm(ID,0,self.initPos[ID])
108 | else:
109 | print('initPos Value Error.')
110 |
111 |
112 | def moveServoInit(self, ID):
113 | self.scMode = 'init'
114 | for i in range(0,len(ID)):
115 | pwm.set_pwm(ID[i], 0, self.initPos[ID[i]])
116 | self.lastPos[ID[i]] = self.initPos[ID[i]]
117 | self.nowPos[ID[i]] = self.initPos[ID[i]]
118 | self.bufferPos[ID[i]] = float(self.initPos[ID[i]])
119 | self.goalPos[ID[i]] = self.initPos[ID[i]]
120 | self.pause()
121 |
122 |
123 | def posUpdate(self):
124 | self.goalUpdate = 1
125 | for i in range(0,16):
126 | self.lastPos[i] = self.nowPos[i]
127 | self.goalUpdate = 0
128 |
129 |
130 | def speedUpdate(self, IDinput, speedInput):
131 | for i in range(0,len(IDinput)):
132 | self.scSpeed[IDinput[i]] = speedInput[i]
133 |
134 |
135 | def moveAuto(self):
136 | for i in range(0,16):
137 | self.ingGoal[i] = self.goalPos[i]
138 |
139 | for i in range(0, self.scSteps):
140 | for dc in range(0,16):
141 | if not self.goalUpdate:
142 | self.nowPos[dc] = int(round((self.lastPos[dc] + (((self.goalPos[dc] - self.lastPos[dc])/self.scSteps)*(i+1))),0))
143 | pwm.set_pwm(dc, 0, self.nowPos[dc])
144 |
145 | if self.ingGoal != self.goalPos:
146 | self.posUpdate()
147 | time.sleep(self.scTime/self.scSteps)
148 | return 1
149 | time.sleep((self.scTime/self.scSteps - self.scMoveTime))
150 |
151 | self.posUpdate()
152 | self.pause()
153 | return 0
154 |
155 |
156 | def moveCert(self):
157 | for i in range(0,16):
158 | self.ingGoal[i] = self.goalPos[i]
159 | self.bufferPos[i] = self.lastPos[i]
160 |
161 | while self.nowPos != self.goalPos:
162 | for i in range(0,16):
163 | if self.lastPos[i] < self.goalPos[i]:
164 | self.bufferPos[i] += self.pwmGenOut(self.scSpeed[i])/(1/self.scDelay)
165 | newNow = int(round(self.bufferPos[i], 0))
166 | if newNow > self.goalPos[i]:newNow = self.goalPos[i]
167 | self.nowPos[i] = newNow
168 | elif self.lastPos[i] > self.goalPos[i]:
169 | self.bufferPos[i] -= self.pwmGenOut(self.scSpeed[i])/(1/self.scDelay)
170 | newNow = int(round(self.bufferPos[i], 0))
171 | if newNow < self.goalPos[i]:newNow = self.goalPos[i]
172 | self.nowPos[i] = newNow
173 |
174 | if not self.goalUpdate:
175 | pwm.set_pwm(i, 0, self.nowPos[i])
176 |
177 | if self.ingGoal != self.goalPos:
178 | self.posUpdate()
179 | return 1
180 | self.posUpdate()
181 | time.sleep(self.scDelay-self.scMoveTime)
182 |
183 | else:
184 | self.pause()
185 | return 0
186 |
187 |
188 | def pwmGenOut(self, angleInput):
189 | return int(round(((self.ctrlRangeMax-self.ctrlRangeMin)/self.angleRange*angleInput),0))
190 |
191 |
192 | def setAutoTime(self, autoSpeedSet):
193 | self.scTime = autoSpeedSet
194 |
195 |
196 | def setDelay(self, delaySet):
197 | self.scDelay = delaySet
198 |
199 |
200 | def autoSpeed(self, ID, angleInput):
201 | self.scMode = 'auto'
202 | self.goalUpdate = 1
203 | for i in range(0,len(ID)):
204 | newGoal = self.initPos[ID[i]] + self.pwmGenOut(angleInput[i])*self.sc_direction[ID[i]]
205 | if newGoal>self.maxPos[ID[i]]:newGoal=self.maxPos[ID[i]]
206 | elif newGoalself.maxPos[ID[i]]:newGoal=self.maxPos[ID[i]]
218 | elif newGoal self.maxPos[self.wiggleID]:self.bufferPos[self.wiggleID] = self.maxPos[self.wiggleID]
229 | elif self.bufferPos[self.wiggleID] < self.minPos[self.wiggleID]:self.bufferPos[self.wiggleID] = self.minPos[self.wiggleID]
230 | self.nowPos[self.wiggleID] = newNow
231 | self.lastPos[self.wiggleID] = newNow
232 | if self.bufferPos[self.wiggleID] < self.maxPos[self.wiggleID] and self.bufferPos[self.wiggleID] > self.minPos[self.wiggleID]:
233 | pwm.set_pwm(self.wiggleID, 0, self.nowPos[self.wiggleID])
234 | else:
235 | self.stopWiggle()
236 | time.sleep(self.scDelay-self.scMoveTime)
237 |
238 |
239 | def stopWiggle(self):
240 | self.pause()
241 | self.posUpdate()
242 |
243 |
244 | def singleServo(self, ID, direcInput, speedSet):
245 | self.wiggleID = ID
246 | self.wiggleDirection = direcInput
247 | self.scSpeed[ID] = speedSet
248 | self.scMode = 'wiggle'
249 | self.posUpdate()
250 | self.resume()
251 |
252 |
253 | def moveAngle(self, ID, angleInput):
254 | self.nowPos[ID] = int(self.initPos[ID] + self.sc_direction[ID]*self.pwmGenOut(angleInput))
255 | if self.nowPos[ID] > self.maxPos[ID]:self.nowPos[ID] = self.maxPos[ID]
256 | elif self.nowPos[ID] < self.minPos[ID]:self.nowPos[ID] = self.minPos[ID]
257 | self.lastPos[ID] = self.nowPos[ID]
258 | pwm.set_pwm(ID, 0, self.nowPos[ID])
259 |
260 |
261 | def scMove(self):
262 | if self.scMode == 'init':
263 | self.moveInit()
264 | elif self.scMode == 'auto':
265 | self.moveAuto()
266 | elif self.scMode == 'certain':
267 | self.moveCert()
268 | elif self.scMode == 'wiggle':
269 | self.moveWiggle()
270 |
271 |
272 | def setPWM(self, ID, PWM_input):
273 | self.lastPos[ID] = PWM_input
274 | self.nowPos[ID] = PWM_input
275 | self.bufferPos[ID] = float(PWM_input)
276 | self.goalPos[ID] = PWM_input
277 | pwm.set_pwm(ID, 0, PWM_input)
278 | self.pause()
279 |
280 |
281 | def run(self):
282 | while 1:
283 | self.__flag.wait()
284 | self.scMove()
285 | pass
286 |
287 |
288 | if __name__ == '__main__':
289 | sc = ServoCtrl()
290 | sc.start()
291 | while 1:
292 | sc.moveAngle(0,(random.random()*100-50))
293 | time.sleep(1)
294 | sc.moveAngle(1,(random.random()*100-50))
295 | time.sleep(1)
296 | '''
297 | sc.singleServo(0, 1, 5)
298 | time.sleep(6)
299 | sc.singleServo(0, -1, 30)
300 | time.sleep(1)
301 | '''
302 | '''
303 | delaytime = 5
304 | sc.certSpeed([0,7], [60,0], [40,60])
305 | print('xx1xx')
306 | time.sleep(delaytime)
307 |
308 | sc.certSpeed([0,7], [0,60], [40,60])
309 | print('xx2xx')
310 | time.sleep(delaytime+2)
311 |
312 | # sc.moveServoInit([0])
313 | # time.sleep(delaytime)
314 | '''
315 | '''
316 | pwm.set_pwm(0,0,560)
317 | time.sleep(1)
318 | pwm.set_pwm(0,0,100)
319 | time.sleep(2)
320 | '''
321 | pass
322 | pass
323 |
--------------------------------------------------------------------------------
/server/dist/img/icons/safari-pinned-tab.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
150 |
--------------------------------------------------------------------------------
/server/server.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env/python
2 | # File name : server.py
3 | # Production : RaspTank
4 | # Website : www.adeept.com
5 | # E-mail : support@adeept.com
6 | # Author : William
7 | # Date : 2018/08/22
8 |
9 | import socket
10 | import time
11 | import threading
12 | import move
13 | import Adafruit_PCA9685
14 | pwm = Adafruit_PCA9685.PCA9685()
15 | pwm.set_pwm_freq(50)
16 | pwm.set_all_pwm(0,300)
17 | from rpi_ws281x import *
18 | import argparse
19 | import os
20 | import ultra
21 | import FPV
22 | import psutil
23 | import servo
24 | import LED
25 | import findline
26 |
27 | step_set = 1
28 | speed_set = 100
29 | rad = 0.6
30 |
31 | new_frame = 0
32 | direction_command = 'no'
33 | turn_command = 'no'
34 | #pwm = Adafruit_PCA9685.PCA9685()
35 | #pwm.set_pwm_freq(50)
36 | pos_input = 1
37 | catch_input = 1
38 | cir_input = 6
39 |
40 | ultrasonicMode = 0
41 | FindLineMode = 0
42 | FindColorMode = 0
43 |
44 |
45 | def app_ctrl():
46 | app_HOST = ''
47 | app_PORT = 10123
48 | app_BUFSIZ = 1024
49 | app_ADDR = (app_HOST, app_PORT)
50 |
51 | AppSerSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
52 | AppSerSock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
53 | AppSerSock.bind(app_ADDR)
54 |
55 | def setup():
56 | move.setup()
57 |
58 | def appCommand(data_input):
59 | global direction_command, turn_command, pos_input, catch_input, cir_input
60 | if data_input == 'forwardStart\n':
61 | direction_command = 'forward'
62 | move.move(speed_set, direction_command, turn_command, rad)
63 |
64 | elif data_input == 'backwardStart\n':
65 | direction_command = 'backward'
66 | move.move(speed_set, direction_command, turn_command, rad)
67 |
68 | elif data_input == 'leftStart\n':
69 | turn_command = 'left'
70 | move.move(speed_set, direction_command, turn_command, rad)
71 |
72 | elif data_input == 'rightStart\n':
73 | turn_command = 'right'
74 | move.move(speed_set, direction_command, turn_command, rad)
75 |
76 | elif 'forwardStop' in data_input:
77 | direction_command = 'no'
78 | move.move(speed_set, direction_command, turn_command, rad)
79 |
80 | elif 'backwardStop' in data_input:
81 | direction_command = 'no'
82 | move.move(speed_set, direction_command, turn_command, rad)
83 |
84 | elif 'leftStop' in data_input:
85 | turn_command = 'no'
86 | move.move(speed_set, direction_command, turn_command, rad)
87 |
88 | elif 'rightStop' in data_input:
89 | turn_command = 'no'
90 | move.move(speed_set, direction_command, turn_command, rad)
91 |
92 |
93 | if data_input == 'lookLeftStart\n':
94 | if cir_input < 12:
95 | cir_input+=1
96 | servo.cir_pos(cir_input)
97 |
98 | elif data_input == 'lookRightStart\n':
99 | if cir_input > 1:
100 | cir_input-=1
101 | servo.cir_pos(cir_input)
102 |
103 | elif data_input == 'downStart\n':
104 | servo.camera_ang('lookdown',10)
105 |
106 | elif data_input == 'upStart\n':
107 | servo.camera_ang('lookup',10)
108 |
109 | elif 'lookLeftStop' in data_input:
110 | pass
111 | elif 'lookRightStop' in data_input:
112 | pass
113 | elif 'downStop' in data_input:
114 | pass
115 | elif 'upStop' in data_input:
116 | pass
117 |
118 |
119 | if data_input == 'aStart\n':
120 | if pos_input < 17:
121 | pos_input+=1
122 | servo.hand_pos(pos_input)
123 |
124 | elif data_input == 'bStart\n':
125 | if pos_input > 1:
126 | pos_input-=1
127 | servo.hand_pos(pos_input)
128 |
129 | elif data_input == 'cStart\n':
130 | if catch_input < 13:
131 | catch_input+=3
132 | servo.catch(catch_input)
133 |
134 | elif data_input == 'dStart\n':
135 | if catch_input > 1:
136 | catch_input-=3
137 | servo.catch(catch_input)
138 |
139 | elif 'aStop' in data_input:
140 | pass
141 | elif 'bStop' in data_input:
142 | pass
143 | elif 'cStop' in data_input:
144 | pass
145 | elif 'dStop' in data_input:
146 | pass
147 |
148 | print(data_input)
149 |
150 | def appconnect():
151 | global AppCliSock, AppAddr
152 | AppSerSock.listen(5)
153 | print('waiting for App connection...')
154 | AppCliSock, AppAddr = AppSerSock.accept()
155 | print('...App connected from :', AppAddr)
156 |
157 | appconnect()
158 | setup()
159 | app_threading=threading.Thread(target=appconnect) #Define a thread for FPV and OpenCV
160 | app_threading.setDaemon(True) #'True' means it is a front thread,it would close when the mainloop() closes
161 | app_threading.start() #Thread starts
162 |
163 | while 1:
164 | data = ''
165 | data = str(AppCliSock.recv(app_BUFSIZ).decode())
166 | if not data:
167 | continue
168 | appCommand(data)
169 | pass
170 |
171 | AppConntect_threading=threading.Thread(target=app_ctrl) #Define a thread for FPV and OpenCV
172 | AppConntect_threading.setDaemon(True) #'True' means it is a front thread,it would close when the mainloop() closes
173 | AppConntect_threading.start() #Thread starts
174 |
175 |
176 | def findline_thread(): #Line tracking mode
177 | while 1:
178 | while FindLineMode:
179 | findline.run()
180 | time.sleep(0.2)
181 |
182 | def get_cpu_tempfunc():
183 | """ Return CPU temperature """
184 | result = 0
185 | mypath = "/sys/class/thermal/thermal_zone0/temp"
186 | with open(mypath, 'r') as mytmpfile:
187 | for line in mytmpfile:
188 | result = line
189 |
190 | result = float(result)/1000
191 | result = round(result, 1)
192 | return str(result)
193 |
194 |
195 | def get_gpu_tempfunc():
196 | """ Return GPU temperature as a character string"""
197 | res = os.popen('/opt/vc/bin/vcgencmd measure_temp').readline()
198 | return res.replace("temp=", "")
199 |
200 |
201 | def get_cpu_use():
202 | """ Return CPU usage using psutil"""
203 | cpu_cent = psutil.cpu_percent()
204 | return str(cpu_cent)
205 |
206 |
207 | def get_ram_info():
208 | """ Return RAM usage using psutil """
209 | ram_cent = psutil.virtual_memory()[2]
210 | return str(ram_cent)
211 |
212 |
213 | def get_swap_info():
214 | """ Return swap memory usage using psutil """
215 | swap_cent = psutil.swap_memory()[3]
216 | return str(swap_cent)
217 |
218 |
219 | def info_get():
220 | global cpu_t,cpu_u,gpu_t,ram_info
221 | while 1:
222 | cpu_t = get_cpu_tempfunc()
223 | cpu_u = get_cpu_use()
224 | ram_info = get_ram_info()
225 | time.sleep(3)
226 |
227 |
228 | def info_send_client():
229 | SERVER_IP = addr[0]
230 | SERVER_PORT = 2256 #Define port serial
231 | SERVER_ADDR = (SERVER_IP, SERVER_PORT)
232 | Info_Socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #Set connection value for socket
233 | Info_Socket.connect(SERVER_ADDR)
234 | print(SERVER_ADDR)
235 | while 1:
236 | try:
237 | Info_Socket.send((get_cpu_tempfunc()+' '+get_cpu_use()+' '+get_ram_info()).encode())
238 | time.sleep(1)
239 | except:
240 | pass
241 |
242 |
243 | def ultra_send_client():
244 | ultra_IP = addr[0]
245 | ultra_PORT = 2257 #Define port serial
246 | ultra_ADDR = (ultra_IP, ultra_PORT)
247 | ultra_Socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #Set connection value for socket
248 | ultra_Socket.connect(ultra_ADDR)
249 | print(ultra_ADDR)
250 | while 1:
251 | while ultrasonicMode:
252 | try:
253 | if not FindColorMode:
254 | ultra_Socket.send(str(round(ultra.checkdist(),2)).encode())
255 | time.sleep(0.5)
256 | continue
257 | fpv.UltraData(round(ultra.checkdist(),2))
258 | time.sleep(0.2)
259 | except:
260 | pass
261 | time.sleep(0.5)
262 |
263 |
264 | def FPV_thread():
265 | fpv=FPV.FPV()
266 | fpv.capture_thread(addr[0])
267 |
268 |
269 | def ap_thread():
270 | os.system("sudo create_ap wlan0 eth0 AdeeptCar 12345678")
271 |
272 |
273 | def run():
274 | global direction_command, turn_command, pos_input, catch_input, cir_input, ultrasonicMode, FindLineMode, FindColorMode
275 | move.setup()
276 | findline.setup()
277 |
278 | info_threading=threading.Thread(target=info_send_client) #Define a thread for FPV and OpenCV
279 | info_threading.setDaemon(True) #'True' means it is a front thread,it would close when the mainloop() closes
280 | info_threading.start() #Thread starts
281 |
282 | ultra_threading=threading.Thread(target=ultra_send_client) #Define a thread for FPV and OpenCV
283 | ultra_threading.setDaemon(True) #'True' means it is a front thread,it would close when the mainloop() closes
284 | ultra_threading.start() #Thread starts
285 |
286 | findline_threading=threading.Thread(target=findline_thread) #Define a thread for FPV and OpenCV
287 | findline_threading.setDaemon(True) #'True' means it is a front thread,it would close when the mainloop() closes
288 | findline_threading.start() #Thread starts
289 | #move.stand()
290 |
291 | ws_R = 0
292 | ws_G = 0
293 | ws_B = 0
294 |
295 | Y_pitch = 0
296 | Y_pitch_MAX = 200
297 | Y_pitch_MIN = -200
298 |
299 | while True:
300 | data = ''
301 | data = str(tcpCliSock.recv(BUFSIZ).decode())
302 | if not data:
303 | continue
304 | elif 'forward' == data:
305 | direction_command = 'forward'
306 | move.move(speed_set, direction_command, turn_command, rad)
307 | elif 'backward' == data:
308 | direction_command = 'backward'
309 | move.move(speed_set, direction_command, turn_command, rad)
310 | elif 'DS' in data:
311 | direction_command = 'no'
312 | move.move(speed_set, direction_command, turn_command, rad)
313 |
314 | elif 'left' == data:
315 | turn_command = 'left'
316 | move.move(speed_set, direction_command, turn_command, rad)
317 | elif 'right' == data:
318 | turn_command = 'right'
319 | move.move(speed_set, direction_command, turn_command, rad)
320 | elif 'TS' in data:
321 | turn_command = 'no'
322 | move.move(speed_set, direction_command, turn_command, rad)
323 |
324 | elif 'out' == data:
325 | if pos_input < 17:
326 | pos_input+=1
327 | servo.hand_pos(pos_input)
328 | elif 'in' == data:
329 | if pos_input > 1:
330 | pos_input-=1
331 | servo.hand_pos(pos_input)
332 |
333 | elif 'headup' == data:
334 | servo.camera_ang('lookup',0)
335 | elif 'headdown' == data:
336 | servo.camera_ang('lookdown',0)
337 | elif 'headhome' == data:
338 | servo.initPosAll()
339 |
340 | elif 'c_left' == data:
341 | if cir_input < 12:
342 | cir_input+=1
343 | servo.cir_pos(cir_input)
344 | elif 'c_right' == data:
345 | if cir_input > 1:
346 | cir_input-=1
347 | servo.cir_pos(cir_input)
348 |
349 | elif 'catch' == data:
350 | if catch_input < 13:
351 | catch_input+=1
352 | servo.catch(catch_input)
353 | elif 'loose' == data:
354 | if catch_input > 1:
355 | catch_input-=1
356 | servo.catch(catch_input)
357 |
358 | elif 'wsR' in data:
359 | try:
360 | set_R=data.split()
361 | ws_R = int(set_R[1])
362 | LED.colorWipe(ws_R,ws_G,ws_B)
363 | except:
364 | pass
365 | elif 'wsG' in data:
366 | try:
367 | set_G=data.split()
368 | ws_G = int(set_G[1])
369 | LED.colorWipe(ws_R,ws_G,ws_B)
370 | except:
371 | pass
372 | elif 'wsB' in data:
373 | try:
374 | set_B=data.split()
375 | ws_B = int(set_B[1])
376 | LED.colorWipe(ws_R,ws_G,ws_B)
377 | except:
378 | pass
379 |
380 | elif 'FindColor' in data:
381 | fpv.FindColor(1)
382 | FindColorMode = 1
383 | ultrasonicMode = 1
384 | tcpCliSock.send(('FindColor').encode())
385 |
386 | elif 'WatchDog' in data:
387 | fpv.WatchDog(1)
388 | tcpCliSock.send(('WatchDog').encode())
389 |
390 | elif 'steady' in data:
391 | ultrasonicMode = 1
392 | tcpCliSock.send(('steady').encode())
393 |
394 | elif 'FindLine' in data:
395 | FindLineMode = 1
396 | tcpCliSock.send(('FindLine').encode())
397 |
398 | elif 'funEnd' in data:
399 | fpv.FindColor(0)
400 | fpv.WatchDog(0)
401 | ultrasonicMode = 0
402 | FindLineMode = 0
403 | FindColorMode = 0
404 | tcpCliSock.send(('FunEnd').encode())
405 | move.motorStop()
406 | time.sleep(0.3)
407 | move.motorStop()
408 |
409 | else:
410 | pass
411 | #print(data)
412 |
413 |
414 | if __name__ == '__main__':
415 |
416 | HOST = ''
417 | PORT = 10223 #Define port serial
418 | BUFSIZ = 1024 #Define buffer size
419 | ADDR = (HOST, PORT)
420 | pwm.set_all_pwm(0,300)
421 |
422 | try:
423 | LED = LED.LED()
424 | LED.colorWipe(Color(255,16,0))
425 | except ModuleNotFoundError as e:
426 | print('Use "sudo pip3 install rpi_ws281x" to install WS_281x package')
427 | pass
428 |
429 | while 1:
430 | try:
431 | s =socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
432 | s.connect(("1.1.1.1",80))
433 | ipaddr_check=s.getsockname()[0]
434 | s.close()
435 | print(ipaddr_check)
436 | except:
437 | ap_threading=threading.Thread(target=ap_thread) #Define a thread for data receiving
438 | ap_threading.setDaemon(True) #'True' means it is a front thread,it would close when the mainloop() closes
439 | ap_threading.start() #Thread starts
440 |
441 | LED.colorWipe(0,16,50)
442 | time.sleep(1)
443 | LED.colorWipe(0,16,100)
444 | time.sleep(1)
445 | LED.colorWipe(0,16,150)
446 | time.sleep(1)
447 | LED.colorWipe(0,16,200)
448 | time.sleep(1)
449 | LED.colorWipe(0,16,255)
450 | time.sleep(1)
451 | LED.colorWipe(35,255,35)
452 |
453 | try:
454 | tcpSerSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
455 | tcpSerSock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
456 | tcpSerSock.bind(ADDR)
457 | tcpSerSock.listen(5) #Start server,waiting for client
458 | print('waiting for connection...')
459 | tcpCliSock, addr = tcpSerSock.accept()
460 | print('...connected from :', addr)
461 |
462 | fpv=FPV.FPV()
463 | fps_threading=threading.Thread(target=FPV_thread) #Define a thread for FPV and OpenCV
464 | fps_threading.setDaemon(True) #'True' means it is a front thread,it would close when the mainloop() closes
465 | fps_threading.start() #Thread starts
466 | break
467 | except:
468 | LED.colorWipe(0,0,0)
469 |
470 | try:
471 | LED.colorWipe(0,80,255)
472 | except:
473 | pass
474 | run()
475 | try:
476 | pwm.set_all_pwm(0,0)
477 | run()
478 | except:
479 | LED.colorWipe(0,0,0)
480 | servo.clean_all()
481 | move.destroy()
482 |
--------------------------------------------------------------------------------
/server/webServer.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env/python
2 | # File name : server.py
3 | # Production : GWR
4 | # Website : www.adeept.com
5 | # Author : William
6 | # Date : 2020/03/17
7 |
8 | import time
9 | import threading
10 | import move
11 | import os
12 | import info
13 | import RPIservo
14 |
15 | import functions
16 | import robotLight
17 | import switch
18 | import socket
19 |
20 | #websocket
21 | import asyncio
22 | import websockets
23 |
24 | import json
25 | import app
26 |
27 | OLED_connection = 1
28 | try:
29 | import OLED
30 | screen = OLED.OLED_ctrl()
31 | screen.start()
32 | screen.screen_show(1, 'ADEEPT.COM')
33 | except:
34 | OLED_connection = 0
35 | print('OLED disconnected')
36 | pass
37 |
38 | functionMode = 0
39 | speed_set = 100
40 | rad = 0.5
41 | turnWiggle = 60
42 |
43 | scGear = RPIservo.ServoCtrl()
44 | scGear.moveInit()
45 |
46 | P_sc = RPIservo.ServoCtrl()
47 | P_sc.start()
48 |
49 | T_sc = RPIservo.ServoCtrl()
50 | T_sc.start()
51 |
52 | H1_sc = RPIservo.ServoCtrl()
53 | H1_sc.start()
54 |
55 | H2_sc = RPIservo.ServoCtrl()
56 | H2_sc.start()
57 |
58 | G_sc = RPIservo.ServoCtrl()
59 | G_sc.start()
60 |
61 | # modeSelect = 'none'
62 | modeSelect = 'PT'
63 |
64 | init_pwm0 = scGear.initPos[0]
65 | init_pwm1 = scGear.initPos[1]
66 | init_pwm2 = scGear.initPos[2]
67 | init_pwm3 = scGear.initPos[3]
68 | init_pwm4 = scGear.initPos[4]
69 |
70 | fuc = functions.Functions()
71 | fuc.start()
72 |
73 | curpath = os.path.realpath(__file__)
74 | thisPath = "/" + os.path.dirname(curpath)
75 |
76 | direction_command = 'no'
77 | turn_command = 'no'
78 |
79 | def servoPosInit():
80 | scGear.initConfig(0,init_pwm0,1)
81 | P_sc.initConfig(1,init_pwm1,1)
82 | T_sc.initConfig(2,init_pwm2,1)
83 | H1_sc.initConfig(3,init_pwm3,1)
84 | G_sc.initConfig(4,init_pwm4,1)
85 |
86 |
87 | def replace_num(initial,new_num): #Call this function to replace data in '.txt' file
88 | global r
89 | newline=""
90 | str_num=str(new_num)
91 | with open(thisPath+"/RPIservo.py","r") as f:
92 | for line in f.readlines():
93 | if(line.find(initial) == 0):
94 | line = initial+"%s" %(str_num+"\n")
95 | newline += line
96 | with open(thisPath+"/RPIservo.py","w") as f:
97 | f.writelines(newline)
98 |
99 |
100 | def ap_thread():
101 | os.system("sudo create_ap wlan0 eth0 Adeept 12345678")
102 |
103 |
104 | def functionSelect(command_input, response):
105 | global functionMode
106 | if 'scan' == command_input:
107 | if OLED_connection:
108 | screen.screen_show(5,'SCANNING')
109 | if modeSelect == 'PT':
110 | radar_send = fuc.radarScan()
111 | print(radar_send)
112 | response['title'] = 'scanResult'
113 | response['data'] = radar_send
114 | time.sleep(0.3)
115 |
116 | elif 'findColor' == command_input:
117 | if OLED_connection:
118 | screen.screen_show(5,'FindColor')
119 | if modeSelect == 'PT':
120 | flask_app.modeselect('findColor')
121 |
122 | elif 'motionGet' == command_input:
123 | if OLED_connection:
124 | screen.screen_show(5,'MotionGet')
125 | flask_app.modeselect('watchDog')
126 |
127 | elif 'stopCV' == command_input:
128 | flask_app.modeselect('none')
129 | switch.switch(1,0)
130 | switch.switch(2,0)
131 | switch.switch(3,0)
132 |
133 | elif 'police' == command_input:
134 | if OLED_connection:
135 | screen.screen_show(5,'POLICE')
136 | RL.police()
137 |
138 | elif 'policeOff' == command_input:
139 | RL.pause()
140 | move.motorStop()
141 |
142 | elif 'automatic' == command_input:
143 | if OLED_connection:
144 | screen.screen_show(5,'Automatic')
145 | if modeSelect == 'PT':
146 | fuc.automatic()
147 | else:
148 | fuc.pause()
149 |
150 | elif 'automaticOff' == command_input:
151 | fuc.pause()
152 | move.motorStop()
153 |
154 | elif 'trackLine' == command_input:
155 | fuc.trackLine()
156 | if OLED_connection:
157 | screen.screen_show(5,'TrackLine')
158 |
159 | elif 'trackLineOff' == command_input:
160 | fuc.pause()
161 | move.motorStop()
162 |
163 | elif 'steadyCamera' == command_input:
164 | if OLED_connection:
165 | screen.screen_show(5,'SteadyCamera')
166 | fuc.steady(T_sc.lastPos[2])
167 |
168 | elif 'steadyCameraOff' == command_input:
169 | fuc.pause()
170 | move.motorStop()
171 |
172 |
173 | def switchCtrl(command_input, response):
174 | if 'Switch_1_on' in command_input:
175 | switch.switch(1,1)
176 |
177 | elif 'Switch_1_off' in command_input:
178 | switch.switch(1,0)
179 |
180 | elif 'Switch_2_on' in command_input:
181 | switch.switch(2,1)
182 |
183 | elif 'Switch_2_off' in command_input:
184 | switch.switch(2,0)
185 |
186 | elif 'Switch_3_on' in command_input:
187 | switch.switch(3,1)
188 |
189 | elif 'Switch_3_off' in command_input:
190 | switch.switch(3,0)
191 |
192 |
193 | def robotCtrl(command_input, response):
194 | global direction_command, turn_command
195 | if 'forward' == command_input:
196 | direction_command = 'forward'
197 | move.move(speed_set, 'forward', 'no', rad)
198 |
199 | elif 'backward' == command_input:
200 | direction_command = 'backward'
201 | move.move(speed_set, 'backward', 'no', rad)
202 |
203 | elif 'DS' in command_input:
204 | direction_command = 'no'
205 | if turn_command == 'no':
206 | move.move(speed_set, 'no', 'no', rad)
207 |
208 |
209 | elif 'left' == command_input:
210 | turn_command = 'left'
211 | move.move(speed_set, 'no', 'left', rad)
212 |
213 | elif 'right' == command_input:
214 | turn_command = 'right'
215 | move.move(speed_set, 'no', 'right', rad)
216 |
217 | elif 'TS' in command_input:
218 | turn_command = 'no'
219 | if direction_command == 'no':
220 | move.move(speed_set, 'no', 'no', rad)
221 | else:
222 | move.move(speed_set, direction_command, 'no', rad)
223 |
224 |
225 | elif 'lookleft' == command_input:
226 | P_sc.singleServo(14, -1, 3)
227 |
228 | elif 'lookright' == command_input:
229 | P_sc.singleServo(14, 1, 3)
230 |
231 | elif 'LRstop' in command_input:
232 | P_sc.stopWiggle()
233 |
234 |
235 | elif 'up' == command_input:
236 | T_sc.singleServo(11, -1, 3)
237 |
238 | elif 'down' == command_input:
239 | T_sc.singleServo(11, 1, 3)
240 |
241 | elif 'UDstop' in command_input:
242 | T_sc.stopWiggle()
243 |
244 |
245 | elif 'handup' == command_input:
246 | # H1_sc.singleServo(12, 1, 7)
247 |
248 | H2_sc.singleServo(13, -1, 7)
249 |
250 | elif 'handdown' == command_input:
251 | # H1_sc.singleServo(12, -1, 7)
252 |
253 | H2_sc.singleServo(13, 1, 7)
254 |
255 | elif 'HAstop' in command_input:
256 | # H1_sc.stopWiggle()
257 | H2_sc.stopWiggle()
258 |
259 | elif 'armup' == command_input:
260 | H1_sc.singleServo(12, 1, 7)
261 |
262 | # H2_sc.singleServo(13, 1, 7)
263 |
264 | elif 'armdown' == command_input:
265 | H1_sc.singleServo(12, -1, 7)
266 |
267 | # H2_sc.singleServo(13, -1, 7)
268 |
269 | elif 'Armstop' in command_input:
270 | H1_sc.stopWiggle()
271 | # H2_sc.stopWiggle()
272 |
273 | elif 'grab' == command_input:
274 | G_sc.singleServo(15, 1, 3)
275 |
276 | elif 'loose' == command_input:
277 | G_sc.singleServo(15, -1, 3)
278 |
279 | elif 'stop' == command_input:
280 | G_sc.stopWiggle()
281 |
282 | elif 'home' == command_input:
283 | P_sc.moveServoInit([11])
284 | T_sc.moveServoInit([14])
285 | H1_sc.moveServoInit([12])
286 | H2_sc.moveServoInit([13])
287 | G_sc.moveServoInit([15])
288 |
289 |
290 | def configPWM(command_input, response):
291 | global init_pwm0, init_pwm1, init_pwm2, init_pwm3, init_pwm4
292 | if 'SiLeft' == command_input:
293 | init_pwm0 += 1
294 | scGear.setPWM(0,init_pwm0)
295 | elif 'SiRight' == command_input:
296 | init_pwm0 -= 1
297 | scGear.setPWM(0,-init_pwm0)
298 | elif 'PWM0MS' == command_input:
299 | scGear.initConfig(0,init_pwm0,1)
300 | replace_num('init_pwm0 = ', init_pwm0)
301 |
302 | elif 'PWM1MS' == command_input:
303 | init_pwm1 = P_sc.lastPos[1]
304 | P_sc.initConfig(1,P_sc.lastPos[1],1)
305 | replace_num('init_pwm1 = ', P_sc.lastPos[1])
306 |
307 | elif 'PWM2MS' == command_input:
308 | init_pwm2 = T_sc.lastPos[2]
309 | T_sc.initConfig(2,T_sc.lastPos[2],1)
310 | print('LLLLLS',T_sc.lastPos[2])
311 | replace_num('init_pwm2 = ', T_sc.lastPos[2])
312 |
313 | elif 'PWM3MS' == command_input:
314 | init_pwm3 = H_sc.lastPos[3]
315 | H1_sc.initConfig(3,H1_sc.lastPos[3],1)
316 | replace_num('init_pwm3 = ', H_sc.lastPos[3])
317 |
318 | elif 'PWM4MS' == command_input:
319 | init_pwm4 = G_sc.lastPos[4]
320 | G_sc.initConfig(4,G_sc.lastPos[4],1)
321 | replace_num('init_pwm4 = ', G_sc.lastPos[4])
322 |
323 | elif 'PWMINIT' == command_input:
324 | print(init_pwm1)
325 | servoPosInit()
326 |
327 | elif 'PWMD' == command_input:
328 | init_pwm0,init_pwm1,init_pwm2,init_pwm3,init_pwm4=300,300,300,300,300
329 | scGear.initConfig(0,init_pwm0,1)
330 | replace_num('init_pwm0 = ', 300)
331 |
332 | P_sc.initConfig(1,300,1)
333 | replace_num('init_pwm1 = ', 300)
334 |
335 | T_sc.initConfig(2,300,1)
336 | replace_num('init_pwm2 = ', 300)
337 |
338 | H1_sc.initConfig(3,300,1)
339 | replace_num('init_pwm3 = ', 300)
340 |
341 | G_sc.initConfig(4,300,1)
342 | replace_num('init_pwm4 = ', 300)
343 | '''
344 | def update_code():
345 | # Update local to be consistent with remote
346 | projectPath = thisPath[:-7]
347 | with open(f'{projectPath}/config.json', 'r') as f1:
348 | config = json.load(f1)
349 | if not config['production']:
350 | print('Update code')
351 | # Force overwriting local code
352 | if os.system(f'cd {projectPath} && sudo git fetch --all && sudo git reset --hard origin/master && sudo git pull') == 0:
353 | print('Update successfully')
354 | print('Restarting...')
355 | os.system('sudo reboot')
356 | '''
357 | def wifi_check():
358 | try:
359 | s =socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
360 | s.connect(("1.1.1.1",80))
361 | ipaddr_check=s.getsockname()[0]
362 | s.close()
363 | print(ipaddr_check)
364 | # update_code()
365 | if OLED_connection:
366 | screen.screen_show(2, 'IP:'+ipaddr_check)
367 | screen.screen_show(3, 'AP MODE OFF')
368 | except:
369 | ap_threading=threading.Thread(target=ap_thread) #Define a thread for data receiving
370 | ap_threading.setDaemon(True) #'True' means it is a front thread,it would close when the mainloop() closes
371 | ap_threading.start() #Thread starts
372 | if OLED_connection:
373 | screen.screen_show(2, 'AP Starting 10%')
374 | RL.setColor(0,16,50)
375 | time.sleep(1)
376 | if OLED_connection:
377 | screen.screen_show(2, 'AP Starting 30%')
378 | RL.setColor(0,16,100)
379 | time.sleep(1)
380 | if OLED_connection:
381 | screen.screen_show(2, 'AP Starting 50%')
382 | RL.setColor(0,16,150)
383 | time.sleep(1)
384 | if OLED_connection:
385 | screen.screen_show(2, 'AP Starting 70%')
386 | RL.setColor(0,16,200)
387 | time.sleep(1)
388 | if OLED_connection:
389 | screen.screen_show(2, 'AP Starting 90%')
390 | RL.setColor(0,16,255)
391 | time.sleep(1)
392 | if OLED_connection:
393 | screen.screen_show(2, 'AP Starting 100%')
394 | RL.setColor(35,255,35)
395 | if OLED_connection:
396 | screen.screen_show(2, 'IP:192.168.12.1')
397 | screen.screen_show(3, 'AP MODE ON')
398 |
399 | async def check_permit(websocket):
400 | while True:
401 | recv_str = await websocket.recv()
402 | cred_dict = recv_str.split(":")
403 | if cred_dict[0] == "admin" and cred_dict[1] == "123456":
404 | response_str = "congratulation, you have connect with server\r\nnow, you can do something else"
405 | await websocket.send(response_str)
406 | return True
407 | else:
408 | response_str = "sorry, the username or password is wrong, please submit again"
409 | await websocket.send(response_str)
410 |
411 | async def recv_msg(websocket):
412 | global speed_set, modeSelect
413 | move.setup()
414 | direction_command = 'no'
415 | turn_command = 'no'
416 |
417 | while True:
418 | response = {
419 | 'status' : 'ok',
420 | 'title' : '',
421 | 'data' : None
422 | }
423 |
424 | data = ''
425 | data = await websocket.recv()
426 | try:
427 | data = json.loads(data)
428 | except Exception as e:
429 | print('not A JSON')
430 |
431 | if not data:
432 | continue
433 |
434 | if isinstance(data,str):
435 | robotCtrl(data, response)
436 |
437 | switchCtrl(data, response)
438 |
439 | functionSelect(data, response)
440 |
441 | configPWM(data, response)
442 |
443 | if 'get_info' == data:
444 | response['title'] = 'get_info'
445 | response['data'] = [info.get_cpu_tempfunc(), info.get_cpu_use(), info.get_ram_info()]
446 |
447 | if 'wsB' in data:
448 | try:
449 | set_B=data.split()
450 | speed_set = int(set_B[1])
451 | except:
452 | pass
453 |
454 | elif 'AR' == data:
455 | modeSelect = 'AR'
456 | screen.screen_show(4, 'ARM MODE ON')
457 | try:
458 | fpv.changeMode('ARM MODE ON')
459 | except:
460 | pass
461 |
462 | elif 'PT' == data:
463 | modeSelect = 'PT'
464 | screen.screen_show(4, 'PT MODE ON')
465 | try:
466 | fpv.changeMode('PT MODE ON')
467 | except:
468 | pass
469 |
470 | #CVFL
471 | elif 'CVFL' == data:
472 | flask_app.modeselect('findlineCV')
473 |
474 | elif 'CVFLColorSet' in data:
475 | color = int(data.split()[1])
476 | flask_app.camera.colorSet(color)
477 |
478 | elif 'CVFLL1' in data:
479 | pos = int(data.split()[1])
480 | flask_app.camera.linePosSet_1(pos)
481 |
482 | elif 'CVFLL2' in data:
483 | pos = int(data.split()[1])
484 | flask_app.camera.linePosSet_2(pos)
485 |
486 | elif 'CVFLSP' in data:
487 | err = int(data.split()[1])
488 | flask_app.camera.errorSet(err)
489 |
490 | elif 'defEC' in data:#Z
491 | fpv.defaultExpCom()
492 |
493 | elif(isinstance(data,dict)):
494 | if data['title'] == "findColorSet":
495 | color = data['data']
496 | flask_app.colorFindSet(color[0],color[1],color[2])
497 |
498 | if not functionMode:
499 | if OLED_connection:
500 | screen.screen_show(5,'Functions OFF')
501 | else:
502 | pass
503 |
504 | print(data)
505 | response = json.dumps(response)
506 | await websocket.send(response)
507 |
508 | async def main_logic(websocket, path):
509 | await check_permit(websocket)
510 | await recv_msg(websocket)
511 |
512 | if __name__ == '__main__':
513 | switch.switchSetup()
514 | switch.set_all_switch_off()
515 |
516 | HOST = ''
517 | PORT = 10223 #Define port serial
518 | BUFSIZ = 1024 #Define buffer size
519 | ADDR = (HOST, PORT)
520 |
521 | global flask_app
522 | flask_app = app.webapp()
523 | flask_app.startthread()
524 |
525 | try:
526 | # global WS2812
527 | robotlight_check = robotLight.check_rpi_model()
528 | if robotlight_check == 5:
529 | print("\033[1;33m WS2812 officially does not support Raspberry Pi 5 for the time being, and the WS2812 LED cannot be used on Raspberry Pi 5.\033[0m")
530 | WS2812_mark = 0 # WS2812 not compatible
531 | else:
532 | print("WS2812 success!")
533 | WS2812_mark = 1
534 | WS2812=robotLight.RobotWS2812()
535 | WS2812.start()
536 | WS2812.breath(70,70,255)
537 | except:
538 | print('Use "sudo pip3 install rpi_ws281x" to install WS_281x package\n使用"sudo pip3 install rpi_ws281x"命令来安装rpi_ws281x')
539 | pass
540 |
541 | while 1:
542 | wifi_check()
543 | try: #Start server,waiting for client
544 | start_server = websockets.serve(main_logic, '0.0.0.0', 8888)
545 | asyncio.get_event_loop().run_until_complete(start_server)
546 | print('waiting for connection...')
547 | # print('...connected from :', addr)
548 | break
549 | except Exception as e:
550 | print(e)
551 | if WS2812_mark:
552 | WS2812.setColor(0,0,0)
553 | else:
554 | pass
555 |
556 | try:
557 | asyncio.get_event_loop().run_forever()
558 | except Exception as e:
559 | print(e)
560 | if WS2812_mark:
561 | WS2812.setColor(0,0,0)
562 | else:
563 | pass
564 | move.destroy()
565 |
--------------------------------------------------------------------------------
/server/raspi-config.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python3
2 | # File name : server.py
3 | # Description : The main program server takes control of Ultrasonic,Motor,Servo by receiving the order from the client through TCP and carrying out the corresponding operation.
4 | # Website : www.adeept.com
5 | # E-mail : support@adeept.com
6 | # Author : William
7 | # Date : 2018/10/12
8 |
9 | import socket
10 | import time
11 | import Adafruit_PCA9685
12 | import os
13 |
14 |
15 | pwm = Adafruit_PCA9685.PCA9685() #Ultrasonic Control
16 | pwm.set_pwm_freq(50)
17 |
18 | def replace_num(initial,new_num): #Call this function to replace data in '.txt' file
19 | global r
20 | newline=""
21 | str_num=str(new_num)
22 | with open("config.txt","r") as f:
23 | for line in f.readlines():
24 | if(line.find(initial) == 0):
25 | line = initial+"%s" %(str_num+"\n")
26 | newline += line
27 | with open("config.txt","w") as f:
28 | f.writelines(newline)
29 |
30 | def num_import_int(initial): #Call this function to import data from '.txt' file
31 | global r
32 | with open("config.txt") as f:
33 | for line in f.readlines():
34 | if(line.find(initial) == 0):
35 | r=line
36 | begin=len(list(initial))
37 | snum=r[begin:]
38 | n=int(snum)
39 | return n
40 |
41 | #L0
42 | L0_MAX = num_import_int('L0_MAX:')
43 | L0_MIN = num_import_int('L0_MIN:')
44 | L0_ST1 = num_import_int('L0_ST1:')
45 | L0_ST2 = num_import_int('L0_ST2:')
46 | L0_ST3 = num_import_int('L0_ST3:')
47 | L0_ST4 = num_import_int('L0_ST4:')
48 | L0_ST5 = num_import_int('L0_ST5:')
49 | L0_ST6 = num_import_int('L0_ST6:')
50 | L0_ST7 = num_import_int('L0_ST7:')
51 | L0_ST8 = num_import_int('L0_ST8:')
52 | L0_ST9 = num_import_int('L0_ST9:')
53 | L0_ST10 = num_import_int('L0_ST10:')
54 | #L1
55 | L1_MAX = num_import_int('L1_MAX:')
56 | L1_MIN = num_import_int('L1_MIN:')
57 | L1_ST1 = num_import_int('L1_ST1:')
58 | L1_ST2 = num_import_int('L1_ST2:')
59 | L1_ST3 = num_import_int('L1_ST3:')
60 | L1_ST4 = num_import_int('L1_ST4:')
61 | L1_ST5 = num_import_int('L1_ST5:')
62 | L1_ST6 = num_import_int('L1_ST6:')
63 | L1_ST7 = num_import_int('L1_ST7:')
64 | L1_ST8 = num_import_int('L1_ST8:')
65 | L1_ST9 = num_import_int('L1_ST9:')
66 | L1_ST10 = num_import_int('L1_ST10:')
67 | #L2
68 | L2_MAX = num_import_int('L2_MAX:')
69 | L2_MIN = num_import_int('L2_MIN:')
70 | L2_ST1 = num_import_int('L2_ST1:')
71 | L2_ST2 = num_import_int('L2_ST2:')
72 | L2_ST3 = num_import_int('L2_ST3:')
73 | L2_ST4 = num_import_int('L2_ST4:')
74 | L2_ST5 = num_import_int('L2_ST5:')
75 | L2_ST6 = num_import_int('L2_ST6:')
76 | L2_ST7 = num_import_int('L2_ST7:')
77 | L2_ST8 = num_import_int('L2_ST8:')
78 | L2_ST9 = num_import_int('L2_ST9:')
79 | L2_ST10 = num_import_int('L2_ST10:')
80 | #L3
81 | L3_MAX = num_import_int('L3_MAX:')
82 | L3_MIN = num_import_int('L3_MIN:')
83 | L3_ST1 = num_import_int('L3_ST1:')
84 | L3_ST2 = num_import_int('L3_ST2:')
85 | L3_ST3 = num_import_int('L3_ST3:')
86 | L3_ST4 = num_import_int('L3_ST4:')
87 | L3_ST5 = num_import_int('L3_ST5:')
88 | L3_ST6 = num_import_int('L3_ST6:')
89 | L3_ST7 = num_import_int('L3_ST7:')
90 | L3_ST8 = num_import_int('L3_ST8:')
91 | L3_ST9 = num_import_int('L3_ST9:')
92 | L3_ST10 = num_import_int('L3_ST10:')
93 | #L4
94 | L4_MAX = num_import_int('L4_MAX:')
95 | L4_MIN = num_import_int('L4_MIN:')
96 | L4_ST1 = num_import_int('L4_ST1:')
97 | L4_ST2 = num_import_int('L4_ST2:')
98 | L4_ST3 = num_import_int('L4_ST3:')
99 | L4_ST4 = num_import_int('L4_ST4:')
100 | L4_ST5 = num_import_int('L4_ST5:')
101 | L4_ST6 = num_import_int('L4_ST6:')
102 | L4_ST7 = num_import_int('L4_ST7:')
103 | L4_ST8 = num_import_int('L4_ST8:')
104 | L4_ST9 = num_import_int('L4_ST9:')
105 | L4_ST10 = num_import_int('L4_ST10:')
106 | #L5
107 | L5_MAX = num_import_int('L5_MAX:')
108 | L5_MIN = num_import_int('L5_MIN:')
109 | L5_ST1 = num_import_int('L5_ST1:')
110 | L5_ST2 = num_import_int('L5_ST2:')
111 | L5_ST3 = num_import_int('L5_ST3:')
112 | L5_ST4 = num_import_int('L5_ST4:')
113 | L5_ST5 = num_import_int('L5_ST5:')
114 | L5_ST6 = num_import_int('L5_ST6:')
115 | L5_ST7 = num_import_int('L5_ST7:')
116 | L5_ST8 = num_import_int('L5_ST8:')
117 | L5_ST9 = num_import_int('L5_ST9:')
118 | L5_ST10 = num_import_int('L5_ST10:')
119 | #L6
120 | L6_MAX = num_import_int('L6_MAX:')
121 | L6_MIN = num_import_int('L6_MIN:')
122 | L6_ST1 = num_import_int('L6_ST1:')
123 | L6_ST2 = num_import_int('L6_ST2:')
124 | L6_ST3 = num_import_int('L6_ST3:')
125 | L6_ST4 = num_import_int('L6_ST4:')
126 | L6_ST5 = num_import_int('L6_ST5:')
127 | L6_ST6 = num_import_int('L6_ST6:')
128 | L6_ST7 = num_import_int('L6_ST7:')
129 | L6_ST8 = num_import_int('L6_ST8:')
130 | L6_ST9 = num_import_int('L6_ST9:')
131 | L6_ST10 = num_import_int('L6_ST10:')
132 | #L7
133 | L7_MAX = num_import_int('L7_MAX:')
134 | L7_MIN = num_import_int('L7_MIN:')
135 | L7_ST1 = num_import_int('L7_ST1:')
136 | L7_ST2 = num_import_int('L7_ST2:')
137 | L7_ST3 = num_import_int('L7_ST3:')
138 | L7_ST4 = num_import_int('L7_ST4:')
139 | L7_ST5 = num_import_int('L7_ST5:')
140 | L7_ST6 = num_import_int('L7_ST6:')
141 | L7_ST7 = num_import_int('L7_ST7:')
142 | L7_ST8 = num_import_int('L7_ST8:')
143 | L7_ST9 = num_import_int('L7_ST9:')
144 | L7_ST10 = num_import_int('L7_ST10:')
145 | #L8
146 | L8_MAX = num_import_int('L8_MAX:')
147 | L8_MIN = num_import_int('L8_MIN:')
148 | L8_ST1 = num_import_int('L8_ST1:')
149 | L8_ST2 = num_import_int('L8_ST2:')
150 | L8_ST3 = num_import_int('L8_ST3:')
151 | L8_ST4 = num_import_int('L8_ST4:')
152 | L8_ST5 = num_import_int('L8_ST5:')
153 | L8_ST6 = num_import_int('L8_ST6:')
154 | L8_ST7 = num_import_int('L8_ST7:')
155 | L8_ST8 = num_import_int('L8_ST8:')
156 | L8_ST9 = num_import_int('L8_ST9:')
157 | L8_ST10 = num_import_int('L8_ST10:')
158 | #L9
159 | L9_MAX = num_import_int('L9_MAX:')
160 | L9_MIN = num_import_int('L9_MIN:')
161 | L9_ST1 = num_import_int('L9_ST1:')
162 | L9_ST2 = num_import_int('L9_ST2:')
163 | L9_ST3 = num_import_int('L9_ST3:')
164 | L9_ST4 = num_import_int('L9_ST4:')
165 | L9_ST5 = num_import_int('L9_ST5:')
166 | L9_ST6 = num_import_int('L9_ST6:')
167 | L9_ST7 = num_import_int('L9_ST6:')
168 | L9_ST8 = num_import_int('L9_ST6:')
169 | L9_ST9 = num_import_int('L9_ST6:')
170 | L9_ST10 = num_import_int('L9_ST10:')
171 | #L10
172 | L10_MAX = num_import_int('L10_MAX:')
173 | L10_MIN = num_import_int('L10_MIN:')
174 | L10_ST1 = num_import_int('L10_ST1:')
175 | L10_ST2 = num_import_int('L10_ST2:')
176 | L10_ST3 = num_import_int('L10_ST3:')
177 | L10_ST4 = num_import_int('L10_ST4:')
178 | L10_ST5 = num_import_int('L10_ST5:')
179 | L10_ST6 = num_import_int('L10_ST6:')
180 | L10_ST7 = num_import_int('L10_ST7:')
181 | L10_ST8 = num_import_int('L10_ST8:')
182 | L10_ST9 = num_import_int('L10_ST9:')
183 | L10_ST10 = num_import_int('L10_ST10:')
184 | #L11
185 | L11_MAX = num_import_int('L11_MAX:')
186 | L11_MIN = num_import_int('L11_MIN:')
187 | L11_ST1 = num_import_int('L11_ST1:')
188 | L11_ST2 = num_import_int('L11_ST2:')
189 | L11_ST3 = num_import_int('L11_ST3:')
190 | L11_ST4 = num_import_int('L11_ST4:')
191 | L11_ST5 = num_import_int('L11_ST5:')
192 | L11_ST6 = num_import_int('L11_ST6:')
193 | L11_ST7 = num_import_int('L11_ST7:')
194 | L11_ST8 = num_import_int('L11_ST8:')
195 | L11_ST9 = num_import_int('L11_ST9:')
196 | L11_ST10 = num_import_int('L11_ST10:')
197 | #L12
198 | L12_MAX = num_import_int('L12_MAX:')
199 | L12_MIN = num_import_int('L12_MIN:')
200 | L12_ST1 = num_import_int('L12_ST1:')
201 | L12_ST2 = num_import_int('L12_ST2:')
202 | L12_ST3 = num_import_int('L12_ST3:')
203 | L12_ST4 = num_import_int('L12_ST4:')
204 | L12_ST5 = num_import_int('L12_ST5:')
205 | L12_ST6 = num_import_int('L12_ST6:')
206 | L12_ST7 = num_import_int('L12_ST7:')
207 | L12_ST8 = num_import_int('L12_ST8:')
208 | L12_ST9 = num_import_int('L12_ST9:')
209 | L12_ST10 = num_import_int('L12_ST10:')
210 | #L13
211 | L13_MAX = num_import_int('L13_MAX:')
212 | L13_MIN = num_import_int('L13_MIN:')
213 | L13_ST1 = num_import_int('L13_ST1:')
214 | L13_ST2 = num_import_int('L13_ST2:')
215 | L13_ST3 = num_import_int('L13_ST3:')
216 | L13_ST4 = num_import_int('L13_ST4:')
217 | L13_ST5 = num_import_int('L13_ST5:')
218 | L13_ST6 = num_import_int('L13_ST6:')
219 | L13_ST7 = num_import_int('L13_ST7:')
220 | L13_ST8 = num_import_int('L13_ST8:')
221 | L13_ST9 = num_import_int('L13_ST9:')
222 | L13_ST10 = num_import_int('L13_ST10:')
223 | #L14
224 | L14_MAX = num_import_int('L14_MAX:')
225 | L14_MIN = num_import_int('L14_MIN:')
226 | L14_ST1 = num_import_int('L14_ST1:')
227 | L14_ST2 = num_import_int('L14_ST2:')
228 | L14_ST3 = num_import_int('L14_ST3:')
229 | L14_ST4 = num_import_int('L14_ST4:')
230 | L14_ST5 = num_import_int('L14_ST5:')
231 | L14_ST6 = num_import_int('L14_ST6:')
232 | L14_ST7 = num_import_int('L14_ST7:')
233 | L14_ST8 = num_import_int('L14_ST8:')
234 | L14_ST9 = num_import_int('L14_ST9:')
235 | L14_ST10 = num_import_int('L14_ST10:')
236 | #L15
237 | L15_MAX = num_import_int('L15_MAX:')
238 | L15_MIN = num_import_int('L15_MIN:')
239 | L15_ST1 = num_import_int('L15_ST1:')
240 | L15_ST2 = num_import_int('L15_ST2:')
241 | L15_ST3 = num_import_int('L15_ST3:')
242 | L15_ST4 = num_import_int('L15_ST4:')
243 | L15_ST5 = num_import_int('L15_ST5:')
244 | L15_ST6 = num_import_int('L15_ST6:')
245 | L15_ST7 = num_import_int('L15_ST7:')
246 | L15_ST8 = num_import_int('L15_ST8:')
247 | L15_ST9 = num_import_int('L15_ST9:')
248 | L15_ST10 = num_import_int('L15_ST10:')
249 |
250 |
251 | ip_con = ''
252 |
253 |
254 | org=425
255 |
256 | set_L = 1
257 | set_ST = 1
258 |
259 | def destroy(): #Clean up
260 | connection.close()
261 |
262 | def run(): #Main loop
263 | global org,ip_con,set_L,set_ST,r
264 | while True: #Connection
265 | s =socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
266 | s.connect(("1.1.1.1",80))
267 | ipaddr_check=s.getsockname()[0]
268 | s.close()
269 | print(ipaddr_check)
270 | print('waiting for connection...')
271 | tcpCliSock, addr = tcpSerSock.accept()#Determine whether to connect
272 | print('...connected from :', addr)
273 | pwm.set_pwm(2, 0, 0)
274 | pwm.set_pwm(1, 0, 0)
275 | pwm.set_pwm(0, 0, 0)
276 | pwm.set_pwm(15, 0, 0)
277 | break
278 |
279 | while True:
280 | data = ''
281 | data = tcpCliSock.recv(BUFSIZ).decode()
282 | if not data:
283 | continue
284 | elif 'L0' == data:
285 | set_L = 0
286 | tcpCliSock.send(('L0').encode())
287 | elif 'L1' == data:
288 | set_L = 1
289 | tcpCliSock.send(('L1').encode())
290 | elif 'L2' == data:
291 | set_L = 2
292 | tcpCliSock.send(('L2').encode())
293 | elif 'L3' == data:
294 | set_L = 3
295 | tcpCliSock.send(('L3').encode())
296 | elif 'L4' == data:
297 | set_L = 4
298 | tcpCliSock.send(('L4').encode())
299 | elif 'L5' == data:
300 | set_L = 5
301 | tcpCliSock.send(('L5').encode())
302 | elif 'L6' == data:
303 | set_L = 6
304 | tcpCliSock.send(('L6').encode())
305 | elif 'L7' == data:
306 | set_L = 7
307 | tcpCliSock.send(('L7').encode())
308 | elif 'L8' == data:
309 | set_L = 8
310 | tcpCliSock.send(('L8').encode())
311 | elif 'L9' == data:
312 | set_L = 9
313 | tcpCliSock.send(('L9').encode())
314 | elif 'L10' == data:
315 | set_L = 10
316 | tcpCliSock.send(('L10').encode())
317 | elif 'L11' == data:
318 | set_L = 11
319 | tcpCliSock.send(('L11').encode())
320 | elif 'L12' == data:
321 | set_L = 12
322 | tcpCliSock.send(('L12').encode())
323 | elif 'L13' == data:
324 | set_L = 13
325 | tcpCliSock.send(('L13').encode())
326 | elif 'L14' == data:
327 | set_L = 14
328 | tcpCliSock.send(('L14').encode())
329 | elif 'L15' == data:
330 | set_L = 15
331 | tcpCliSock.send(('L15').encode())
332 |
333 |
334 |
335 | elif 'ST1' == data:
336 | set_ST = 'ST1'
337 | pwm.set_pwm(set_L, 0, num_import_int('L%d_%s:'%(set_L,set_ST)))
338 | tcpCliSock.send(('ST1').encode())
339 | elif 'ST2' == data:
340 | set_ST = 'ST2'
341 | pwm.set_pwm(set_L, 0, num_import_int('L%d_%s:'%(set_L,set_ST)))
342 | tcpCliSock.send(('ST2').encode())
343 | elif 'ST3' == data:
344 | set_ST = 'ST3'
345 | pwm.set_pwm(set_L, 0, num_import_int('L%d_%s:'%(set_L,set_ST)))
346 | tcpCliSock.send(('ST3').encode())
347 | elif 'ST4' == data:
348 | set_ST = 'ST4'
349 | pwm.set_pwm(set_L, 0, num_import_int('L%d_%s:'%(set_L,set_ST)))
350 | tcpCliSock.send(('ST4').encode())
351 | elif 'ST5' == data:
352 | set_ST = 'ST5'
353 | pwm.set_pwm(set_L, 0, num_import_int('L%d_%s:'%(set_L,set_ST)))
354 | tcpCliSock.send(('ST5').encode())
355 | elif 'ST6' == data:
356 | set_ST = 'ST6'
357 | pwm.set_pwm(set_L, 0, num_import_int('L%d_%s:'%(set_L,set_ST)))
358 | tcpCliSock.send(('ST6').encode())
359 | elif 'ST7' == data:
360 | set_ST = 'ST7'
361 | pwm.set_pwm(set_L, 0, num_import_int('L%d_%s:'%(set_L,set_ST)))
362 | tcpCliSock.send(('ST7').encode())
363 | elif 'ST8' == data:
364 | set_ST = 'ST8'
365 | pwm.set_pwm(set_L, 0, num_import_int('L%d_%s:'%(set_L,set_ST)))
366 | tcpCliSock.send(('ST8').encode())
367 | elif 'ST9' == data:
368 | set_ST = 'ST9'
369 | pwm.set_pwm(set_L, 0, num_import_int('L%d_%s:'%(set_L,set_ST)))
370 | tcpCliSock.send(('ST9').encode())
371 | elif 'ST10' == data:
372 | set_ST = 'ST10'
373 | pwm.set_pwm(set_L, 0, num_import_int('L%d_%s:'%(set_L,set_ST)))
374 | tcpCliSock.send(('ST10').encode())
375 | elif 'ST11' == data:
376 | set_ST = 'ST11'
377 | pwm.set_pwm(set_L, 0, num_import_int('L%d_%s:'%(set_L,set_ST)))
378 | tcpCliSock.send(('ST11').encode())
379 | elif 'ST12' == data:
380 | set_ST = 'ST12'
381 | pwm.set_pwm(set_L, 0, num_import_int('L%d_%s:'%(set_L,set_ST)))
382 | tcpCliSock.send(('ST12').encode())
383 | elif 'ST13' == data:
384 | set_ST = 'ST13'
385 | pwm.set_pwm(set_L, 0, num_import_int('L%d_%s:'%(set_L,set_ST)))
386 | tcpCliSock.send(('ST13').encode())
387 | elif 'ST14' == data:
388 | set_ST = 'ST14'
389 | pwm.set_pwm(set_L, 0, num_import_int('L%d_%s:'%(set_L,set_ST)))
390 | tcpCliSock.send(('ST14').encode())
391 | elif 'MIN' == data:
392 | set_ST = 'MIN'
393 | pwm.set_pwm(set_L, 0, num_import_int('L%d_%s:'%(set_L,set_ST)))
394 | tcpCliSock.send(('MIN').encode())
395 | elif 'MAX' == data:
396 | set_ST = 'MAX'
397 | pwm.set_pwm(set_L, 0, num_import_int('L%d_%s:'%(set_L,set_ST)))
398 | tcpCliSock.send(('MAX').encode())
399 |
400 |
401 |
402 | elif 'add' == data:
403 | org+=1
404 | pwm.set_pwm(set_L, 0, org)
405 | send_pwm=str(org)
406 | tcpCliSock.send(send_pwm.encode())
407 | continue
408 |
409 | elif 'sub' == data: #Camera Adjustment
410 | org-=1
411 | pwm.set_pwm(set_L, 0, org)
412 | send_pwm=str(org)
413 | tcpCliSock.send(send_pwm.encode())
414 | continue
415 |
416 | elif 'config' == data:
417 | replace_num(('L%d_%s:'%(set_L,set_ST)),org)
418 |
419 | elif 'reset' == data:
420 | replace_num(('L%d_%s:'%(set_L,set_ST)),org)
421 |
422 | elif 'save' == data:
423 | replace_num(('L%d_%s:'%(set_L,set_ST)),org)
424 |
425 | elif 'run' in data:
426 | set_list=data.split()
427 | try:
428 | setps = int(set_list[1])
429 | time_get = round(float(set_list[2]),1)
430 | print(setps)
431 | print(time_get)
432 | for i in range (1,(setps+1)):
433 | pwm.set_pwm(set_L, 0, num_import_int('L%d_ST%d:'%(set_L,i)))
434 | time.sleep(time_get)
435 | except:
436 | print('wrong args')
437 | pass
438 |
439 | elif 'all' in data:
440 | try:
441 | set_list=data.split()
442 | setps = int(set_list[1])
443 | time_get = round(float(set_list[2]),1)
444 | print(setps)
445 | print(time_get)
446 | for i in range (1,(setps+1)):
447 | for x in range (0,16):
448 | pwm.set_pwm(x, 0, num_import_int('L%d_ST%d:'%(x,i)))
449 | time.sleep(time_get)
450 | except:
451 | print('wrong args')
452 | pass
453 |
454 | elif 'frame' in data:
455 | try:
456 | for i in range (0,16):
457 | pwm.set_pwm(i, 0, num_import_int('L%d_%s:'%(i,set_ST)))
458 | except:
459 | print('wrong args')
460 | pass
461 |
462 | elif 'stop' in data:
463 | pwm.set_pwm(2, 0, 0)
464 | pwm.set_pwm(1, 0, 0)
465 | pwm.set_pwm(0, 0, 0)
466 | pwm.set_pwm(15, 0, 0)
467 | pwm.set_pwm(14, 0, 0)
468 | pwm.set_pwm(13, 0, 0)
469 | pwm.set_pwm(12, 0, 0)
470 | pwm.set_pwm(11, 0, 0)
471 | pwm.set_pwm(10, 0, 0)
472 | pwm.set_pwm(9, 0, 0)
473 | pwm.set_pwm(8, 0, 0)
474 | pwm.set_pwm(7, 0, 0)
475 | pwm.set_pwm(6, 0, 0)
476 | pwm.set_pwm(5, 0, 0)
477 | pwm.set_pwm(4, 0, 0)
478 | pwm.set_pwm(3, 0, 0)
479 |
480 |
481 | else:
482 | try:
483 | org = int(data)
484 | print(org)
485 | pwm.set_pwm(set_L, 0, org)
486 | except:
487 | pass
488 |
489 |
490 |
491 |
492 |
493 | if __name__ == '__main__':
494 | HOST = ''
495 | PORT = 10223 #Define port serial
496 | BUFSIZ = 1024 #Define buffer size
497 | ADDR = (HOST, PORT)
498 |
499 | tcpSerSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
500 | tcpSerSock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
501 | tcpSerSock.bind(ADDR)
502 | tcpSerSock.listen(5)
503 | #Start server,waiting for client
504 | try:
505 | run()
506 |
507 | except KeyboardInterrupt:
508 | pwm.set_pwm(2, 0, 0)
509 | pwm.set_pwm(1, 0, 0)
510 | pwm.set_pwm(0, 0, 0)
511 | pwm.set_pwm(15, 0, 0)
512 | pwm.set_pwm(14, 0, 0)
513 | pwm.set_pwm(13, 0, 0)
514 | pwm.set_pwm(12, 0, 0)
515 | pwm.set_pwm(11, 0, 0)
516 | pwm.set_pwm(10, 0, 0)
517 | pwm.set_pwm(9, 0, 0)
518 | pwm.set_pwm(8, 0, 0)
519 | pwm.set_pwm(7, 0, 0)
520 | pwm.set_pwm(6, 0, 0)
521 | pwm.set_pwm(5, 0, 0)
522 | pwm.set_pwm(4, 0, 0)
523 | pwm.set_pwm(3, 0, 0)
524 |
525 | destroy()
526 |
--------------------------------------------------------------------------------
/server/robotLight.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # File name : robotLight.py
3 | # Website : www.adeept.com
4 | # Author : Adeept
5 | # Date : 2025/05/15
6 | import time
7 | import sys
8 | from gpiozero import PWMOutputDevice as PWM
9 | from rpi_ws281x import *
10 | import threading
11 | import spidev
12 | import numpy
13 | from numpy import sin, cos, pi
14 | def check_rpi_model():
15 | _, result = run_command("cat /proc/device-tree/model |awk '{print $3}'")
16 | result = result.strip()
17 | if result == '3':
18 | return 3
19 | elif result == '4':
20 | return 4
21 | elif result == '5':
22 | return 5
23 | else:
24 | return None
25 |
26 | def run_command(cmd=""):
27 | import subprocess
28 | p = subprocess.Popen(
29 | cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
30 | result = p.stdout.read().decode('utf-8')
31 | status = p.poll()
32 | return status, result
33 |
34 |
35 | def map(x, in_min, in_max, out_min, out_max):
36 | return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min
37 |
38 |
39 | class RobotWS2812(threading.Thread):
40 | def __init__(self, *args, **kwargs):
41 | self.LED_COUNT = 16 # Number of LED pixels.
42 | self.LED_PIN = 12 # GPIO pin connected to the pixels (18 uses PWM!).
43 | self.LED_FREQ_HZ = 800000 # LED signal frequency in hertz (usually 800khz)
44 | self.LED_DMA = 10 # DMA channel to use for generating signal (try 10)
45 | self.LED_BRIGHTNESS = 255 # Set to 0 for darkest and 255 for brightest
46 | self.LED_INVERT = False # True to invert the signal (when using NPN transistor level shift)
47 | self.LED_CHANNEL = 0 # set to '1' for GPIOs 13, 19, 41, 45 or 53
48 |
49 | self.colorBreathR = 0
50 | self.colorBreathG = 0
51 | self.colorBreathB = 0
52 | self.breathSteps = 10
53 |
54 |
55 | self.lightMode = 'none' #'none' 'police' 'breath'
56 |
57 |
58 | # Create NeoPixel object with appropriate configuration.
59 | self.strip = Adafruit_NeoPixel(self.LED_COUNT, self.LED_PIN, self.LED_FREQ_HZ, self.LED_DMA, self.LED_INVERT, self.LED_BRIGHTNESS, self.LED_CHANNEL)
60 | # Intialize the library (must be called once before other functions).
61 | self.strip.begin()
62 |
63 | super(RobotWS2812, self).__init__(*args, **kwargs)
64 | self.__flag = threading.Event()
65 | self.__flag.clear()
66 |
67 | # Define functions which animate LEDs in various ways.
68 | def set_all_led_color_data(self, R, G, B):
69 | """Wipe color across display a pixel at a time."""
70 | color = Color(int(R),int(G),int(B))
71 | for i in range(self.strip.numPixels()):
72 | self.strip.setPixelColor(i, color)
73 | self.strip.show()
74 |
75 | def setSomeColor(self, R, G, B, ID):
76 | color = Color(int(R),int(G),int(B))
77 | for i in ID:
78 | self.strip.setPixelColor(i, color)
79 | self.strip.show()
80 |
81 | def pause(self):
82 | self.lightMode = 'none'
83 | self.set_all_led_color_data(0,0,0)
84 | self.__flag.clear()
85 |
86 | def resume(self):
87 | self.__flag.set()
88 |
89 | def led_close(self):
90 | self.lightMode = 'none'
91 | self.set_all_led_color_data(0,0,0)
92 | self.__flag.clear()
93 | def police(self):
94 | self.lightMode = 'police'
95 | self.resume()
96 |
97 |
98 | def policeProcessing(self):
99 | while self.lightMode == 'police':
100 | for i in range(0,3):
101 | self.setSomeColor(0,0,255,[0,1,2,3,4,5,6,7,8,9,10,11])
102 | self.set_all_led_color_data(0,0,255)
103 | time.sleep(0.05)
104 | self.setSomeColor(0,0,0,[0,1,2,3,4,5,6,7,8,9,10,11])
105 | self.set_all_led_color_data(0,0,0)
106 | time.sleep(0.05)
107 | if self.lightMode != 'police':
108 | break
109 | time.sleep(0.1)
110 | for i in range(0,3):
111 | self.setSomeColor(255,0,0,[0,1,2,3,4,5,6,7,8,9,10,11])
112 | self.set_all_led_color_data(255,0,0)
113 | time.sleep(0.05)
114 | self.setSomeColor(0,0,0,[0,1,2,3,4,5,6,7,8,9,10,11])
115 | self.set_all_led_color_data(0,0,0)
116 | time.sleep(0.05)
117 | time.sleep(0.1)
118 |
119 |
120 | def breath(self, R_input, G_input, B_input):
121 | self.lightMode = 'breath'
122 | self.colorBreathR = R_input
123 | self.colorBreathG = G_input
124 | self.colorBreathB = B_input
125 | self.resume()
126 |
127 |
128 | def breathProcessing(self):
129 | while self.lightMode == 'breath':
130 | for i in range(0,self.breathSteps):
131 | if self.lightMode != 'breath':
132 | break
133 | self.set_all_led_color_data(self.colorBreathR*i/self.breathSteps, self.colorBreathG*i/self.breathSteps, self.colorBreathB*i/self.breathSteps)
134 | time.sleep(0.03)
135 | for i in range(0,self.breathSteps):
136 | if self.lightMode != 'breath':
137 | break
138 | self.set_all_led_color_data(self.colorBreathR-(self.colorBreathR*i/self.breathSteps), self.colorBreathG-(self.colorBreathG*i/self.breathSteps), self.colorBreathB-(self.colorBreathB*i/self.breathSteps))
139 | time.sleep(0.03)
140 |
141 | def lightChange(self):
142 | if self.lightMode == 'none':
143 | self.pause()
144 | elif self.lightMode == 'police':
145 | self.policeProcessing()
146 | elif self.lightMode == 'breath':
147 | self.breathProcessing()
148 |
149 |
150 | def run(self):
151 | while 1:
152 | self.__flag.wait()
153 | self.lightChange()
154 | pass
155 |
156 |
157 |
158 |
159 |
160 | class Adeept_SPI_LedPixel(threading.Thread):
161 | def __init__(self, count = 8, bright = 255, sequence='GRB', bus = 0, device = 0, *args, **kwargs):
162 | self.set_led_type(sequence)
163 | self.set_led_count(count)
164 | self.set_led_brightness(bright)
165 | self.led_begin(bus, device)
166 | self.lightMode = 'none'
167 | self.colorBreathR = 0
168 | self.colorBreathG = 0
169 | self.colorBreathB = 0
170 | self.breathSteps = 10
171 |
172 |
173 | self.rainbow_r = 0
174 | self.rainbow_g = 0
175 | self.rainbow_b = 00
176 |
177 | self.colorFlowingR = 0
178 | self.colorFlowingG = 0
179 | self.colorFlowingB = 0
180 |
181 | self.set_all_led_color(0,0,0)
182 | super(Adeept_SPI_LedPixel, self).__init__(*args, **kwargs)
183 | self.__flag = threading.Event()
184 | self.__flag.clear()
185 | def led_begin(self, bus = 0, device = 0):
186 | self.bus = bus
187 | self.device = device
188 | try:
189 | self.spi = spidev.SpiDev()
190 | self.spi.open(self.bus, self.device)
191 | self.spi.mode = 0
192 | self.led_init_state = 1
193 | except OSError:
194 | print("Please check the configuration in /boot/firmware/config.txt.")
195 | if self.bus == 0:
196 | print("You can turn on the 'SPI' in 'Interface Options' by using 'sudo raspi-config'.")
197 | print("Or make sure that 'dtparam=spi=on' is not commented, then reboot the Raspberry Pi. Otherwise spi0 will not be available.")
198 | else:
199 | print("Please add 'dtoverlay=spi{}-2cs' at the bottom of the /boot/firmware/config.txt, then reboot the Raspberry Pi. otherwise spi{} will not be available.".format(self.bus, self.bus))
200 | self.led_init_state = 0
201 |
202 | def check_spi_state(self):
203 | return self.led_init_state
204 |
205 | def spi_gpio_info(self):
206 | if self.bus == 0:
207 | print("SPI0-MOSI: GPIO10(WS2812-PIN) SPI0-MISO: GPIO9 SPI0-SCLK: GPIO11 SPI0-CE0: GPIO8 SPI0-CE1: GPIO7")
208 | elif self.bus == 1:
209 | print("SPI1-MOSI: GPIO20(WS2812-PIN) SPI1-MISO: GPIO19 SPI1-SCLK: GPIO21 SPI1-CE0: GPIO18 SPI1-CE1: GPIO17 SPI0-CE1: GPIO16")
210 | elif self.bus == 2:
211 | print("SPI2-MOSI: GPIO41(WS2812-PIN) SPI2-MISO: GPIO40 SPI2-SCLK: GPIO42 SPI2-CE0: GPIO43 SPI2-CE1: GPIO44 SPI2-CE1: GPIO45")
212 | elif self.bus == 3:
213 | print("SPI3-MOSI: GPIO2(WS2812-PIN) SPI3-MISO: GPIO1 SPI3-SCLK: GPIO3 SPI3-CE0: GPIO0 SPI3-CE1: GPIO24")
214 | elif self.bus == 4:
215 | print("SPI4-MOSI: GPIO6(WS2812-PIN) SPI4-MISO: GPIO5 SPI4-SCLK: GPIO7 SPI4-CE0: GPIO4 SPI4-CE1: GPIO25")
216 | elif self.bus == 5:
217 | print("SPI5-MOSI: GPIO14(WS2812-PIN) SPI5-MISO: GPIO13 SPI5-SCLK: GPIO15 SPI5-CE0: GPIO12 SPI5-CE1: GPIO26")
218 | elif self.bus == 6:
219 | print("SPI6-MOSI: GPIO20(WS2812-PIN) SPI6-MISO: GPIO19 SPI6-SCLK: GPIO21 SPI6-CE0: GPIO18 SPI6-CE1: GPIO27")
220 |
221 | def led_close(self):
222 | self.set_all_led_rgb([0,0,0])
223 | self.spi.close()
224 |
225 | def set_led_count(self, count):
226 | self.led_count = count
227 | self.led_color = [0,0,0] * self.led_count
228 | self.led_original_color = [0,0,0] * self.led_count
229 |
230 | def set_led_type(self, rgb_type):
231 | try:
232 | led_type = ['RGB','RBG','GRB','GBR','BRG','BGR']
233 | led_type_offset = [0x06,0x09,0x12,0x21,0x18,0x24]
234 | index = led_type.index(rgb_type)
235 | self.led_red_offset = (led_type_offset[index]>>4) & 0x03
236 | self.led_green_offset = (led_type_offset[index]>>2) & 0x03
237 | self.led_blue_offset = (led_type_offset[index]>>0) & 0x03
238 | return index
239 | except ValueError:
240 | self.led_red_offset = 1
241 | self.led_green_offset = 0
242 | self.led_blue_offset = 2
243 | return -1
244 |
245 | def set_led_brightness(self, brightness):
246 | self.led_brightness = brightness
247 | for i in range(self.led_count):
248 | self.set_led_rgb_data(i, self.led_original_color)
249 |
250 | def set_ledpixel(self, index, r, g, b):
251 | p = [0,0,0]
252 | p[self.led_red_offset] = round(r * self.led_brightness / 255)
253 | p[self.led_green_offset] = round(g * self.led_brightness / 255)
254 | p[self.led_blue_offset] = round(b * self.led_brightness / 255)
255 | self.led_original_color[index*3+self.led_red_offset] = r
256 | self.led_original_color[index*3+self.led_green_offset] = g
257 | self.led_original_color[index*3+self.led_blue_offset] = b
258 | for i in range(3):
259 | self.led_color[index*3+i] = p[i]
260 |
261 | def set_led_color_data(self, index, r, g, b):
262 | self.set_ledpixel(index, r, g, b)
263 |
264 | def set_led_rgb_data(self, index, color):
265 | self.set_ledpixel(index, color[0], color[1], color[2])
266 |
267 | def set_led_color(self, index, r, g, b):
268 | self.set_ledpixel(index, r, g, b)
269 | self.show()
270 |
271 | def set_led_rgb(self, index, color):
272 | self.set_led_rgb_data(index, color)
273 | self.show()
274 |
275 | def set_all_led_color_data(self, r, g, b):
276 | for i in range(self.led_count):
277 | self.set_led_color_data(i, r, g, b)
278 |
279 | def set_all_led_rgb_data(self, color):
280 | for i in range(self.led_count):
281 | self.set_led_rgb_data(i, color)
282 |
283 | def set_all_led_color(self, r, g, b):
284 | for i in range(self.led_count):
285 | self.set_led_color_data(i, r, g, b)
286 | self.show()
287 |
288 | def set_all_led_rgb(self, color):
289 | for i in range(self.led_count):
290 | self.set_led_rgb_data(i, color)
291 | self.show()
292 |
293 |
294 | def write_ws2812_numpy8(self):
295 | d = numpy.array(self.led_color).ravel() #Converts data into a one-dimensional array
296 | tx = numpy.zeros(len(d)*8, dtype=numpy.uint8) #Each RGB color has 8 bits, each represented by a uint8 type data
297 | for ibit in range(8): #Convert each bit of data to the data that the spi will send
298 | tx[7-ibit::8]=((d>>ibit)&1)*0x78 + 0x80 #T0H=1,T0L=7, T1H=5,T1L=3 #0b11111000 mean T1(0.78125us), 0b10000000 mean T0(0.15625us)
299 | if self.led_init_state != 0:
300 | if self.bus == 0:
301 | self.spi.xfer(tx.tolist(), int(8/1.25e-6)) #Send color data at a frequency of 6.4Mhz
302 | else:
303 | self.spi.xfer(tx.tolist(), int(8/1.0e-6)) #Send color data at a frequency of 8Mhz
304 |
305 | def write_ws2812_numpy4(self):
306 | d=numpy.array(self.led_color).ravel()
307 | tx=numpy.zeros(len(d)*4, dtype=numpy.uint8)
308 | for ibit in range(4):
309 | tx[3-ibit::4]=((d>>(2*ibit+1))&1)*0x60 + ((d>>(2*ibit+0))&1)*0x06 + 0x88
310 | if self.led_init_state != 0:
311 | if self.bus == 0:
312 | self.spi.xfer(tx.tolist(), int(4/1.25e-6))
313 | else:
314 | self.spi.xfer(tx.tolist(), int(4/1.0e-6))
315 |
316 | def show(self, mode = 1):
317 | if mode == 1:
318 | write_ws2812 = self.write_ws2812_numpy8
319 | else:
320 | write_ws2812 = self.write_ws2812_numpy4
321 | write_ws2812()
322 |
323 | def wheel(self, pos):
324 | if pos < 85:
325 | return [(255 - pos * 3), (pos * 3), 0]
326 | elif pos < 170:
327 | pos = pos - 85
328 | return [0, (255 - pos * 3), (pos * 3)]
329 | else:
330 | pos = pos - 170
331 | return [(pos * 3), 0, (255 - pos * 3)]
332 |
333 | def hsv2rgb(self, h, s, v):
334 | h = h % 360
335 | rgb_max = round(v * 2.55)
336 | rgb_min = round(rgb_max * (100 - s) / 100)
337 | i = round(h / 60)
338 | diff = round(h % 60)
339 | rgb_adj = round((rgb_max - rgb_min) * diff / 60)
340 | if i == 0:
341 | r = rgb_max
342 | g = rgb_min + rgb_adj
343 | b = rgb_min
344 | elif i == 1:
345 | r = rgb_max - rgb_adj
346 | g = rgb_max
347 | b = rgb_min
348 | elif i == 2:
349 | r = rgb_min
350 | g = rgb_max
351 | b = rgb_min + rgb_adj
352 | elif i == 3:
353 | r = rgb_min
354 | g = rgb_max - rgb_adj
355 | b = rgb_max
356 | elif i == 4:
357 | r = rgb_min + rgb_adj
358 | g = rgb_min
359 | b = rgb_max
360 | else:
361 | r = rgb_max
362 | g = rgb_min
363 | b = rgb_max - rgb_adj
364 | return [r, g, b]
365 |
366 | def police(self):
367 | self.lightMode = 'police'
368 | self.resume()
369 |
370 | def breath(self, R_input, G_input, B_input):
371 | self.lightMode = 'breath'
372 | self.colorBreathR = R_input
373 | self.colorBreathG = G_input
374 | self.colorBreathB = B_input
375 | self.resume()
376 |
377 | def rainbow(self, R_input, G_input, B_input):
378 | self.lightMode = 'rainbow'
379 | self.rainbow_r = R_input
380 | self.rainbow_g = G_input
381 | self.rainbow_b = B_input
382 | self.resume()
383 |
384 | def flowing(self, R_input, G_input, B_input):
385 | self.lightMode = 'flowing'
386 | self.colorFlowingR = R_input
387 | self.colorFlowingG = G_input
388 | self.colorFlowingB = B_input
389 | self.resume()
390 |
391 | def resume(self):
392 | self.__flag.set()
393 |
394 |
395 |
396 | def pause(self):
397 | self.lightMode = 'none'
398 | self.set_all_led_color_data(0,0,0)
399 | self.__flag.clear()
400 |
401 | def breathProcessing(self):
402 | while self.lightMode == 'breath':
403 | for i in range(0,self.breathSteps):
404 | if self.lightMode != 'breath':
405 | break
406 | self.set_all_led_color(self.colorBreathR*i/self.breathSteps, self.colorBreathG*i/self.breathSteps, self.colorBreathB*i/self.breathSteps)
407 | time.sleep(0.03)
408 | for i in range(0,self.breathSteps):
409 | if self.lightMode != 'breath':
410 | break
411 | self.set_all_led_color(self.colorBreathR-(self.colorBreathR*i/self.breathSteps), self.colorBreathG-(self.colorBreathG*i/self.breathSteps), self.colorBreathB-(self.colorBreathB*i/self.breathSteps))
412 | time.sleep(0.03)
413 |
414 | def policeProcessing(self):
415 | while self.lightMode == 'police':
416 | for i in range(0,3):
417 | self.set_all_led_color_data(0,0,255)
418 | self.show()
419 | time.sleep(0.05)
420 | self.set_all_led_color_data(0,0,0)
421 | self.show()
422 | time.sleep(0.05)
423 | if self.lightMode != 'police':
424 | break
425 | time.sleep(0.1)
426 | for i in range(0,3):
427 | self.set_all_led_color_data(255,0,0)
428 | self.show()
429 | time.sleep(0.05)
430 | self.set_all_led_color_data(0,0,0)
431 | self.show()
432 | time.sleep(0.05)
433 | time.sleep(0.1)
434 |
435 | def rainbowProcessing(self):
436 | while self.lightMode == 'rainbow':
437 | for i in range(self.led_count):
438 | self.rainbow_r = self.rainbow_r + i * 10
439 | self.rainbow_g = self.rainbow_g + i * 10
440 | self.rainbow_b = self.rainbow_b + i * 10
441 | if self.rainbow_r > 255:
442 | self.rainbow_r -= 255
443 | if self.rainbow_g > 255:
444 | self.rainbow_g -= 255
445 | if self.rainbow_b > 255:
446 | self.rainbow_b -= 255
447 | self.set_led_color(i, self.rainbow_r + i * 10,self.rainbow_g,self.rainbow_b)
448 | self.show()
449 | self.lightMode = 'none'
450 |
451 | def flowingProcessing(self):
452 | while self.lightMode == 'flowing':
453 | self.set_all_led_rgb_data([0, 0, 0])
454 | for i in range(self.led_count):
455 | self.set_led_color(i, self.colorFlowingR,self.rainbow_g,self.colorFlowingR)
456 | time.sleep(0.2)
457 | self.show()
458 | time.sleep(0.2)
459 |
460 |
461 | def lightChange(self):
462 | if self.lightMode == 'none':
463 | self.pause()
464 | elif self.lightMode == 'police':
465 | self.policeProcessing()
466 | elif self.lightMode == 'breath':
467 | self.breathProcessing()
468 | elif self.lightMode == 'rainbow':
469 | self.rainbowProcessing()
470 | elif self.lightMode == 'flowing':
471 | self.flowingProcessing()
472 |
473 | def run(self):
474 | while 1:
475 | self.__flag.wait()
476 | self.lightChange()
477 | pass
478 |
479 |
480 |
481 | if __name__ == '__main__':
482 | import time
483 | import os
484 | print("spidev version is ", spidev.__version__)
485 | print("spidev device as show:")
486 |
487 | led = Adeept_SPI_LedPixel(8, 255) # Use MOSI for /dev/spidev0 to drive the lights
488 | try:
489 | if led.check_spi_state() != 0:
490 | led.set_led_count(8)
491 | led.set_all_led_color_data(255, 0, 0)
492 | led.show()
493 | time.sleep(0.5)
494 | led.set_all_led_rgb_data([0, 255, 0])
495 | led.show()
496 | time.sleep(0.5)
497 | led.set_all_led_color(0, 0, 255)
498 | time.sleep(0.5)
499 | led.set_all_led_rgb([0, 255, 255])
500 | time.sleep(0.5)
501 |
502 | led.set_led_count(12)
503 | led.set_all_led_color_data(255, 255, 0)
504 | for i in range(255):
505 | led.set_led_brightness(i)
506 | led.show()
507 | time.sleep(0.005)
508 | for i in range(255):
509 | led.set_led_brightness(255-i)
510 | led.show()
511 | time.sleep(0.005)
512 |
513 | led.set_led_brightness(20)
514 | while True:
515 | for j in range(255):
516 | for i in range(led.led_count):
517 | led.set_led_rgb_data(i, led.wheel((round(i * 255 / led.led_count) + j)%256))
518 | led.show()
519 | time.sleep(0.002)
520 | else:
521 | led.led_close()
522 | except KeyboardInterrupt:
523 | led.led_close()
524 |
--------------------------------------------------------------------------------