Repository: RealCorebb/bbPOV-P Branch: main Commit: 57612c10df30 Files: 30 Total size: 103.6 KB Directory structure: gitextract_fwat9f3h/ ├── .gitignore ├── API/ │ ├── NewConvert/ │ │ └── NewConvert.py │ ├── Serverless/ │ │ ├── app.py │ │ ├── requirements.txt │ │ └── serverless.yml │ ├── convert.py │ ├── convertAPI.py │ ├── screen.py │ └── sender.py ├── Arduino/ │ ├── HardwareTest/ │ │ ├── DivSpeedtest/ │ │ │ └── DivSpeedtest.ino │ │ ├── FreeRTOS/ │ │ │ └── FreeRTOS.ino │ │ ├── ImgDivSpeedtest/ │ │ │ ├── ImgDivSpeedtest.ino │ │ │ └── webpage.h │ │ ├── JPEGDEC/ │ │ │ └── JPEGDEC.ino │ │ ├── MultiThreadDivSpeedtest/ │ │ │ └── MultiThreadDivSpeedtest.ino │ │ ├── NeoPixelBitmap/ │ │ │ └── NeoPixelBitmap.ino │ │ ├── NeoPixelFunLoop/ │ │ │ └── NeoPixelFunLoop.ino │ │ ├── NeoPixelRainbow/ │ │ │ └── NeoPixelRainbow.ino │ │ ├── NeoPixelStatic/ │ │ │ └── NeoPixelStatic.ino │ │ ├── SDMMC_Test/ │ │ │ └── SDMMC_Test.ino │ │ ├── TCPReceive/ │ │ │ └── TCPReceive.ino │ │ ├── UDPReceive/ │ │ │ └── UDPReceive.ino │ │ ├── WebServer/ │ │ │ ├── WebServer.ino │ │ │ └── data/ │ │ │ ├── .exclude.files │ │ │ └── index.htm │ │ └── strandtest/ │ │ └── strandtest.ino │ └── bbPOV-P/ │ ├── bbPOV-P.ino │ ├── webpage.h │ └── webpage.html └── README.md ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ API/Serverless/.env Arduino/HardwareTest/NeoPixelRainbow/NeoPixelRainbow.ino.esp32.bin *.jpg *.bmp *.gif *.bmp *.bmp *.png API/magic.gif *.bin API/sb.py *.bmp API/sb.txt *.mov *.mp4 ================================================ FILE: API/NewConvert/NewConvert.py ================================================ from dearpygui.core import * from dearpygui.simple import * import numpy as np import os import math import time import cv2 from dearpygui.core import * from dearpygui.simple import * #配置 NUMPIXELS = 80 #单边LED数量 Div = 320 #1圈分割数 Bright = 60 #輝度 Led0Bright = 15 #中心LEDの輝度 [%] last_time = time.time() #Global gammaCorrection = False identity = np.arange(256, dtype = np.dtype('uint8')) gammatable = np.array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 11, 11, 11, 12, 12, 13, 13, 14, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 22, 22, 23, 23, 24, 25, 25, 26, 26, 27, 28, 28, 29, 30, 30, 31, 32, 33, 33, 34, 35, 35, 36, 37, 38, 39, 39, 40, 41, 42, 43, 43, 44, 45, 46, 47, 48, 49, 50, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 71, 72, 73, 74, 75, 76, 77, 78, 80, 81, 82, 83, 84, 86, 87, 88, 89, 91, 92, 93, 94, 96, 97, 98, 100, 101, 102, 104, 105, 106, 108, 109, 110, 112, 113, 115, 116, 118, 119, 121, 122, 123, 125, 126, 128, 130, 131, 133, 134, 136, 137, 139, 140, 142, 144, 145, 147, 149, 150, 152, 154, 155, 157, 159, 160, 162, 164, 166, 167, 169, 171, 173, 175, 176, 178, 180, 182, 184, 186, 187, 189, 191, 193, 195, 197, 199, 201, 203, 205, 207, 209, 211, 213, 215, 217, 219, 221, 223, 225, 227, 229, 231, 233, 235, 238, 240, 242, 244, 246, 248, 251, 253, 255]) lut = np.dstack((identity, identity, gammatable)) media_path = "" save_path = "" def polarConv(imgOrgin,outputName): global gammaCorrection h = imgOrgin.shape[0] #帧尺寸 w = imgOrgin.shape[1] #画像縮小 imgRedu = cv2.resize(imgOrgin,(math.floor((NUMPIXELS * 2 -1)/h *w), NUMPIXELS * 2 -1)) #顺时针旋转90度 因为下一步的极坐标转换的0度是正东方向,而我们的POV正北方向为0度 imgRedu = cv2.rotate(imgRedu,cv2.ROTATE_90_CLOCKWISE) polar_image = cv2.warpPolar(imgRedu,(NUMPIXELS , Div ), (imgRedu.shape[1]/2,imgRedu.shape[0]/2) ,min(imgRedu.shape[0], imgRedu.shape[1]) / 2, 0) for i in range(NUMPIXELS): #亮度处理 polar_image[:,i,0] = polar_image[:,i,0] * ((100 - Led0Bright) / NUMPIXELS * i + Led0Bright) / 100 * Bright /100 polar_image[:,i,1] = polar_image[:,i,1] * ((100 - Led0Bright) / NUMPIXELS * i + Led0Bright) / 100 * Bright /100 polar_image[:,i,2] = polar_image[:,i,2] * ((100 - Led0Bright) / NUMPIXELS * i + Led0Bright) / 100 * Bright /100 #polar_image[:,i,2] = hsv[:,i,2] * ((100 - Led0Bright) / NUMPIXELS * i + Led0Bright) / 100 * Bright /100 if(gammaCorrection): polar_image = cv2.LUT(polar_image, lut) cv2.imwrite(outputName+'.jpg',polar_image,[int(cv2.IMWRITE_JPEG_QUALITY), 100]+[int(cv2.IMWRITE_JPEG_OPTIMIZE), True]) frameNum = 0 def start_convert(): global frameNum startTime = time.time() if (media_path.endswith(".jpg") or media_path.endswith(".png") or media_path.endswith(".bmp")): frame = cv2.imread(media_path) polarConv(frame,save_path+'\\'+str(0)) else: media = cv2.VideoCapture(media_path) while True: ret, frame = media.read() if ret == False: frameNum = 0 break polarConv(frame,save_path+'\\'+str(frameNum)) frameNum=frameNum+1 print(time.time() - startTime) def file_picker(sender, data): open_file_dialog(callback=apply_selected_file, extensions=".*,.gif,.jpg,.png,.mp4,.avi,.mov") def directory_picker(sender, data): select_directory_dialog(callback=apply_selected_directory) def apply_selected_directory(sender, data): global save_path log_debug(data) # so we can see what is inside of data directory = data[0] folder = data[1] set_value("directory", directory) save_path = f"{directory}" print(save_path) def apply_selected_file(sender, data): global media_path log_debug(data) # so we can see what is inside of data directory = data[0] file = data[1] set_value("file_path", f"{directory}\\{file}") media_path = f"{directory}\\{file}" print(media_path) def gamma_switch(sender,data): global gammaCorrection gammaCorrection = get_value("Gamma Correction") print(gammaCorrection) with window("Main"): add_button("Select Image or Video", callback=file_picker) add_text("Input Path: ", color=[128, 255, 0]) add_same_line() add_label_text("##filepath", source="file_path", color=[0, 255, 0]) add_button("Select Output Folder", callback=directory_picker) add_text("Output Folder: " , color=[0, 255, 255]) add_same_line() add_label_text("##dir", source="directory", color=[128, 255, 255]) add_checkbox("Gamma Correction",default_value=gammaCorrection,callback=gamma_switch) add_button("Go!",callback=start_convert,width=100,height=50) add_text("Ctrl + Click to diretly edit:" , color=[200,150,255]) add_slider_int("single-sided LEDs",default_value=NUMPIXELS,max_value=200) add_slider_int("Divide",default_value=Div,max_value=1000) add_slider_int("Center Brightness",default_value=Led0Bright,max_value=100) add_slider_int("Edge Brightness",default_value=Bright,max_value=100) add_text("Author: Corebb" , color=[255,255,0]) add_drawing("Drawing_1", width=256, height=256) add_same_line() add_drawing("Drawing_2", width=256, height=256) def resource_path(relative_path): """ Get absolute path to resource, works for dev and for PyInstaller """ try: # PyInstaller creates a temp folder and stores path in _MEIPASS base_path = sys._MEIPASS except Exception: base_path = os.path.abspath(".") return os.path.join(base_path, relative_path) set_main_window_size(800, 800) set_main_window_title("bbPOV-P Converter") draw_image("Drawing_1", resource_path('data/Corebb.jpg'), [0, 0], pmax=[256,256], uv_min=[0, 0], uv_max=[1, 1], tag="image") draw_image("Drawing_2", resource_path('data/logo.jpg'), [0, 0], pmax=[256,256], uv_min=[0, 0], uv_max=[1, 1], tag="image2") set_theme("Cherry") start_dearpygui(primary_window="Main") ================================================ FILE: API/Serverless/app.py ================================================ #Based on homemadegarbage.com #Thanks for the knowledge #Developed by Corebb import numpy as np import os import math from PIL import Image import base64 from io import BytesIO import flask from flask import request,json,make_response import gzip app = flask.Flask(__name__) data = [] @app.route("/") def index(): return "Hello Flask" #画像変換関数 def polarConv(imgOrgin, frame,NUMPIXELS,Div): h = imgOrgin.height #帧尺寸 w = imgOrgin.width #画像縮小 imgRedu = imgOrgin.resize((math.floor((NUMPIXELS * 2 -1)/h *w), NUMPIXELS * 2 -1)) #imgRedu.save(str(frame)+'.png') #输出缩小后的原图像 imgArray=np.array(imgRedu) #縮小画像中心座標 h2 = imgRedu.height w2 = imgRedu.width wC = math.floor(w2 / 2) hC = math.floor(h2 / 2) #極座標変換画像準備 imgPolar = Image.new('RGB', (NUMPIXELS, Div)) #極座標変換 for j in range(0, Div): for i in range(0, hC+1): #座標色取得 rP = imgArray[hC + math.ceil(i * math.cos(2*math.pi/Div*j)), wC - math.ceil(i * math.sin(2*math.pi/Div*j)), 0] gP = imgArray[hC + math.ceil(i * math.cos(2*math.pi/Div*j)), wC - math.ceil(i * math.sin(2*math.pi/Div*j)), 1] bP = imgArray[hC + math.ceil(i * math.cos(2*math.pi/Div*j)), wC - math.ceil(i * math.sin(2*math.pi/Div*j)), 2] imgPolar.putpixel((i,j), (rP, gP, bP)) buffered = BytesIO() imgPolar.save(buffered,format="BMP") #输出极坐标变换后的图像 data.append(base64.b64encode(buffered.getvalue()).decode('utf-8')) @app.route('/', methods=['POST']) def convert(): data.clear() img = request.form['img'] NUMPIXELS = int(request.form['NUMPIXELS']) #半径灯条数 Div = int(request.form['Div']) #1圈分割数 im = Image.open(BytesIO(base64.b64decode(img))) print(im.is_animated) print(im.n_frames) Frame=im.n_frames for i in range(Frame): #输出每一帧 frame = im.convert('RGBA') #如果是RGB的话,有的透明背景GIF不兼容 polarConv(frame, i, NUMPIXELS, Div) if i != Frame-1: im.seek(im.tell()+1) response = make_response(json.dumps(data)) response.headers['Content-Type'] = 'application/json' return response ================================================ FILE: API/Serverless/requirements.txt ================================================ Flask==1.1.2 numpy==1.17.2 Pillow==6.2.1 ================================================ FILE: API/Serverless/serverless.yml ================================================ # serverless.yml component: flask name: flashDemo org: orgDemo app: appDemo stage: dev inputs: src: hook: 'pip -V' dist: ./ exclude: - .env region: ap-guangzhou runtime: Python3.6 apigatewayConf: protocols: - http - https environment: release ================================================ FILE: API/convert.py ================================================ #Based on homemadegarbage.com #Thanks for the knowledge #Developed by Corebb import numpy as np import os import math from PIL import Image #配置 #Frame = 5 #指定帧数量 NUMPIXELS = 80 #单边LED数量 Div = 320#1圈分割数 Bright = 60 #輝度 Led0Bright = 15 #中心LEDの輝度 [%] gif_file_name = "jellyfish.gif" im = Image.open(gif_file_name) print(im.is_animated) print(im.n_frames) Frame=im.n_frames #画像変換関数 def polarConv(imgOrgin, frame): h = imgOrgin.height #帧尺寸 w = imgOrgin.width #画像縮小 imgRedu = imgOrgin.resize((math.floor((NUMPIXELS * 2 -1)/h *w), NUMPIXELS * 2 -1)).rotate(180) #imgRedu.save(str(frame)+'.png') #输出缩小后的原图像 imgArray=np.array(imgRedu) #縮小画像中心座標 h2 = imgRedu.height w2 = imgRedu.width wC = math.floor(w2 / 2) hC = math.floor(h2 / 2) #極座標変換画像準備 imgPolar = Image.new('RGB', (NUMPIXELS, Div)) #極座標変換 for j in range(0, Div): for i in range(0, hC+1): #座標色取得 rP = int(imgArray[hC + math.ceil(i * math.cos(2*math.pi/Div*j)), wC - math.ceil(i * math.sin(2*math.pi/Div*j)), 0] * ((100 - Led0Bright) / NUMPIXELS * i + Led0Bright) / 100 * Bright /100) gP = int(imgArray[hC + math.ceil(i * math.cos(2*math.pi/Div*j)), wC - math.ceil(i * math.sin(2*math.pi/Div*j)), 1] * ((100 - Led0Bright) / NUMPIXELS * i + Led0Bright) / 100 * Bright /100) bP = int(imgArray[hC + math.ceil(i * math.cos(2*math.pi/Div*j)), wC - math.ceil(i * math.sin(2*math.pi/Div*j)), 2] * ((100 - Led0Bright) / NUMPIXELS * i + Led0Bright) / 100 * Bright /100) imgPolar.putpixel((i,j), (rP, gP, bP)) imgPolar.save(str(frame)+'.jpg',quality=95, optimize=True) #输出极坐标变换后的图像 for i in range(Frame): #输出每一帧 frame = im.convert('RGBA') #如果是RGB的话,有的透明背景GIF不兼容 polarConv(frame, i) if i != Frame-1: im.seek(im.tell()+1) ================================================ FILE: API/convertAPI.py ================================================ #Based on homemadegarbage.com #Thanks for the knowledge #Developed by Corebb import numpy as np import os import math from PIL import Image import base64 from io import BytesIO import flask from flask import request,json,make_response import gzip app = flask.Flask(__name__) data = [] #画像変換関数 def polarConv(imgOrgin, frame,NUMPIXELS,Div): h = imgOrgin.height #帧尺寸 w = imgOrgin.width #画像縮小 imgRedu = imgOrgin.resize((math.floor((NUMPIXELS * 2 -1)/h *w), NUMPIXELS * 2 -1)) #imgRedu.save(str(frame)+'.png') #输出缩小后的原图像 imgArray=np.array(imgRedu) #縮小画像中心座標 h2 = imgRedu.height w2 = imgRedu.width wC = math.floor(w2 / 2) hC = math.floor(h2 / 2) #極座標変換画像準備 imgPolar = Image.new('RGB', (NUMPIXELS, Div)) #極座標変換 for j in range(0, Div): for i in range(0, hC+1): #座標色取得 rP = imgArray[hC + math.ceil(i * math.cos(2*math.pi/Div*j)), wC - math.ceil(i * math.sin(2*math.pi/Div*j)), 0] gP = imgArray[hC + math.ceil(i * math.cos(2*math.pi/Div*j)), wC - math.ceil(i * math.sin(2*math.pi/Div*j)), 1] bP = imgArray[hC + math.ceil(i * math.cos(2*math.pi/Div*j)), wC - math.ceil(i * math.sin(2*math.pi/Div*j)), 2] imgPolar.putpixel((i,j), (rP, gP, bP)) buffered = BytesIO() imgPolar.save(buffered,format="BMP") #输出极坐标变换后的图像 data.append(base64.b64encode(buffered.getvalue()).decode('utf-8')) @app.route('/', methods=['POST']) def convert(): data.clear() gif_file_name = request.files['img'] NUMPIXELS = int(request.form['NUMPIXELS']) #半径灯条数 Div = int(request.form['Div']) #1圈分割数 im = Image.open(gif_file_name) print(im.is_animated) print(im.n_frames) Frame=im.n_frames for i in range(Frame): #输出每一帧 frame = im.convert('RGBA') #如果是RGB的话,有的透明背景GIF不兼容 polarConv(frame, i, NUMPIXELS, Div) if i != Frame-1: im.seek(im.tell()+1) content = gzip.compress(json.dumps(data).encode('utf8'),5) response = make_response(content) response.headers['Content-Type'] = 'application/json' response.headers['Content-length'] = len(content) response.headers['Content-Encoding'] = 'gzip' return response app.run() ================================================ FILE: API/screen.py ================================================ #Based on homemadegarbage.com #Thanks for the knowledge #Developed by Corebb import numpy as np import os import math from PIL import Image from PIL import ImageGrab from datetime import datetime import cv2 #配置 #Frame = 5 #指定帧数量 NUMPIXELS = 80 #单边LED数量 Div = 360 #1圈分割数 Bright = 100 #輝度 Led0Bright = 3 #中心LEDの輝度 [%] i = 0 #画像変換関数 def polarConv(imgOrgin, frame): h = imgOrgin.height #帧尺寸 w = imgOrgin.width #画像縮小 # imgRedu = imgOrgin.resize((math.floor((NUMPIXELS * 2 -1)/h *w), NUMPIXELS * 2 -1)) # imgRedu = cv2.cvtColor(np.array(imgRedu), cv2.COLOR_BGR2GRAY) #polar_image = cv2.warpPolar(imgRedu,(NUMPIXELS , Div ), (w/2,h/2) ,min(h, w) / 2, 0) #cv2.imwrite('sb.jpg',polar_image) dateTimeObj = datetime.now() print(dateTimeObj) while 1: #捕捉屏幕 frame = ImageGrab.grab(bbox=(100,100,160,160)) polarConv(frame, i) #frame.save('1.bmp') ================================================ FILE: API/sender.py ================================================ import tkinter as tk from tkinter import ttk from tkinter import * import numpy as np import os import math from mss import mss import time from threading import Thread import cv2 import time import tkinter.font as font import socket import requests #配置 NUMPIXELS = 80 #单边LED数量 Div = 320 #1圈分割数 Bright = 50 #輝度 Led0Bright = 15 #中心LEDの輝度 [%] last_time = time.time() MAX_FPS=38 MIN_FRAME_TIME=1/MAX_FPS #Global running = False posX = 0 posY = 0 posX2 = 160 posY2 = 160 TCP_IP = '10.0.0.212' TCP_PORT = 22333 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) def resource_path(relative_path): """ Get absolute path to resource, works for dev and for PyInstaller """ try: # PyInstaller creates a temp folder and stores path in _MEIPASS base_path = sys._MEIPASS except Exception: base_path = os.path.abspath(".") return os.path.join(base_path, relative_path) def polarConv(imgOrgin): h = imgOrgin.height #帧尺寸 w = imgOrgin.width #画像縮小 imgRedu = cv2.resize(np.array(imgOrgin),(math.floor((NUMPIXELS * 2 -1)/h *w), NUMPIXELS * 2 -1)) #顺时针旋转90度 因为下一步的极坐标转换的0度是正东方向,而我们的POV正北方向为0度 imgRedu = cv2.rotate(imgRedu,cv2.ROTATE_90_CLOCKWISE) polar_image = cv2.warpPolar(imgRedu,(NUMPIXELS , Div ), (imgRedu.shape[1]/2,imgRedu.shape[0]/2) ,min(imgRedu.shape[0], imgRedu.shape[1]) / 2, 0) for i in range(NUMPIXELS): #亮度处理 polar_image[:,i,0] = polar_image[:,i,0] * ((100 - Led0Bright) / NUMPIXELS * i + Led0Bright) / 100 * Bright /100 polar_image[:,i,1] = polar_image[:,i,1] * ((100 - Led0Bright) / NUMPIXELS * i + Led0Bright) / 100 * Bright /100 polar_image[:,i,2] = polar_image[:,i,2] * ((100 - Led0Bright) / NUMPIXELS * i + Led0Bright) / 100 * Bright /100 #polar_image[:,i,2] = hsv[:,i,2] * ((100 - Led0Bright) / NUMPIXELS * i + Led0Bright) / 100 * Bright /100 #cv2.imwrite(outputName+'.jpg',polar_image,[int(cv2.IMWRITE_JPEG_OPTIMIZE), True]) ret,img_encode = cv2.imencode('.jpg',polar_image,[int(cv2.IMWRITE_JPEG_QUALITY), 50]+[int(cv2.IMWRITE_JPEG_OPTIMIZE), True]) data = np.array(img_encode) stringData = data.tobytes() print(str(len(stringData))) s.send(str.encode(str(len(stringData)).ljust(5)+'\r')); s.sendall(stringData) def capture(): global posX global posY global posX2 global posY2 global last_time while running: #if(s.recv(1).decode("utf-8") == "N"): #捕捉屏幕 start = time.time() frame = mss().grab({'top': posY, 'left': posX, 'width': posX2-posX, 'height': posY2-posY}) polarConv(frame) print('FPS:'+str(int(1 / (time.time()-last_time)))) last_time=time.time() time.sleep(max(0, MIN_FRAME_TIME - (time.time() - start))) def startCapture(): global running alpha = 0 running=True s.connect((TCP_IP, TCP_PORT)) t = Thread (target = capture) t.start() def stopCapture(): global running running=False class Main(tk.Tk): def __init__(self): tk.Tk.__init__(self) icon = """ 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 """ iconImg=PhotoImage(data=icon) self.wm_iconphoto(True, iconImg) self.title('bbPOV-P Sender') self.configure(background='#222222') self.resizable(0,0) w = 200 h = 100 ws = self.winfo_screenwidth() hs = self.winfo_screenheight() x = (ws/2) - (w/2) y = (hs/2) - (h/2) self.geometry('%dx%d+%d+%d' % (w, h, x, y)) self.floater = CaptureArea(self) ip = tk.Entry(self,justify='center',bg="#222222",highlightbackground="white",fg="white") ip.insert(0,'IP地址') buttonFont = font.Font(family="微软雅黑",size=16) start = tk.Button(self, text="开始", command=startCapture , bg="green",fg="white") stop = tk.Button(self, text="停止", command=stopCapture , bg="red",fg="white") start['font'] = buttonFont stop['font'] = buttonFont ip.pack(pady=10,anchor="center") start.pack(padx=10,pady=5,ipadx=10,ipady=5,side="left") stop.pack(padx=10,pady=5,ipadx=10,ipady=5,side="left") class ResizingCanvas(tk.Canvas): def __init__(self, parent, **kwargs): tk.Canvas.__init__(self, parent, **kwargs) self.bind("", self.on_resize) self.height = self.winfo_reqheight() self.width = self.winfo_reqwidth() def on_resize(self,event): # determine the ratio of old width/height to new width/height wscale = event.width/self.width hscale = event.height/self.height self.width = event.width self.height = event.height # rescale all the objects self.scale("all", 0, 0, wscale, hscale) class CaptureArea(tk.Toplevel): def __init__(self, *args, **kwargs): tk.Toplevel.__init__(self, *args, **kwargs) self.overrideredirect(1) self.attributes("-alpha", 0.3) self.attributes("-transparentcolor", 'purple') self.attributes("-topmost", True) myCanvas = ResizingCanvas(self, bg="purple", height=300, width=300,highlightthickness=8, highlightbackground="red") myCanvas.pack(fill=tk.BOTH, expand=tk.YES) self.move = tk.Label(self, bitmap="gray25") self.move.place(x=0,y=0,height=8,width=8) self.move.bind("", self.start_move) self.move.bind("", self.stop_move) self.move.bind("", self.do_move) self.grip = ttk.Sizegrip(self) self.grip.place(height=8,width=8,relx=1.0, rely=1.0, anchor="se") self.grip.bind("", self.OnMotion) def OnMotion(self, event): global posX2 global posY2 x1 = self.winfo_pointerx() y1 = self.winfo_pointery() x0 = self.winfo_rootx() y0 = self.winfo_rooty() posX2 = x0+self.winfo_width()-8 posY2 = y0+self.winfo_height()-8 self.geometry("%sx%s" % ((x1-x0),(y1-y0))) return def start_move(self, event): self.x = event.x self.y = event.y def stop_move(self, event): self.x = None self.y = None def do_move(self, event): global posX global posY global posX2 global posY2 deltax = event.x - self.x deltay = event.y - self.y x = self.winfo_x() + deltax y = self.winfo_y() + deltay posX = self.winfo_rootx()+8 posY = self.winfo_rooty()+8 posX2 = x+self.winfo_width()-8 posY2 = y+self.winfo_height()-8 self.geometry(f"+{x}+{y}") app=Main() app.mainloop() ================================================ FILE: Arduino/HardwareTest/DivSpeedtest/DivSpeedtest.ino ================================================ #include #include #include #include #include #include #include #include "SD_MMC.h" #include "JPEGDEC.h" #include #include "soc/timer_group_struct.h" #include "soc/timer_group_reg.h" //显示相关 #define PixelCount 80 //单边LED数量 #define LedStripCount 2 //LED条数 uint32_t Frame = 0; byte Hall = 0; //到达顶端的霍尔传感器代号 uint32_t Div = 360; //一些机制需要用到的全局变量 Ticker hallHit; JPEGDEC jpeg; File myfile; AsyncWebServer server(80); int numRot= 0; int numDiv = 0; int stateDiv = 0; int spinstae = 1; volatile unsigned long rotTime, timeOld, timeNow, opeTime, spinTime; NeoPixelBus strip2(PixelCount); NeoPixelBus strip(PixelCount); //Adafruit_DotStar_VSPI stripA(PixelCount,DOTSTAR_BRG); //CRGB leds[PixelCount]; AsyncWebSocket ws("/ws"); RgbColor black(0); void RotCountCommon(){ static unsigned long last_interrupt_time = 0; unsigned long interrupt_time = millis(); //deBounce,as the signal not stable sometimes 去抖动 if (interrupt_time - last_interrupt_time > 20) { numDiv=0; timeNow = micros(); rotTime = timeNow - timeOld; timeOld = timeNow; //Serial.println("RotCount"); } last_interrupt_time = interrupt_time; } void setup() { pinMode(34,INPUT); pinMode(35,INPUT); Serial.begin(115200); if(!SD_MMC.begin("/sdcard")){ Serial.println("Card Mount Failed"); } WiFi.mode(WIFI_AP); WiFi.softAP("bbPOV-P"); MDNS.begin("bbPOV"); MDNS.addService("bbPOV", "tcp", 80); strip.Begin(); strip.Show(); strip2.Begin(32,25,33,26); strip2.Show(); //stripA.begin(); // Initialize pins for output //stripA.show(); // Turn all LEDs off ASAP // FastLED.addLeds(leds, PixelCount); // FastLED.show(); hallHit.attach(0.033,RotCountCommon); Serial.println("Setup Done"); xTaskCreatePinnedToCore( webloop , "webloop" , 1000 // Stack size , NULL , 2 // Priority , NULL , 0); xTaskCreatePinnedToCore( ledloop , "ledloop" , 1000 // Stack size , NULL , 5 // Priority , NULL , 1); } void loop() { //AsyncElegantOTA.loop(); } void ledloop(void *pvParameters) { for (;;) { TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE; TIMERG0.wdt_feed=1; TIMERG0.wdt_wprotect=0; if(stateDiv == 1 && micros() - timeOld > (rotTime / (Div/LedStripCount)) * (numDiv)){ stateDiv = 0; } if(stateDiv == 0 && micros() - timeOld < (rotTime / (Div/LedStripCount)) * (numDiv + 1 )){ // long stripshowtime=micros(); stateDiv = 1; // long donetime=micros(); // switch(Hall){ // case 0: strip.ClearTo(black); strip2.ClearTo(black); // long nowtime=micros(); RgbColor Divcolor (0,0,0); if(numDiv%3==0) // CHOU = CRGB::Red; Divcolor.R=16; if(numDiv%3==1) //CHOU = CRGB::Green; Divcolor.G=16; if(numDiv%3==2) // CHOU = CRGB::Blue; Divcolor.B=16; for(int i = 0; i < PixelCount; i++){ strip.SetPixelColor(i, Divcolor); strip2.SetPixelColor(i, Divcolor); } // Serial.printf("FUcking setpixel tiime:%d",int(micros()-nowtime)); // FastLED.show(); strip.Show(); strip2.Show(); // stripA.show(); // break; /* case 1: strip.ClearTo(black); strip2.ClearTo(black); for(int i = 0; i < PixelCount; i++){ strip2.SetPixelColor(i, RgbColor(uint8_t((imgBuffer[numDiv][i] & 0xF800)>>8),uint8_t((imgBuffer[numDiv][i] & 0x07C0)>>3),uint8_t((imgBuffer[numDiv][i] & 0x001F)<<3))); strip.SetPixelColor(i, RgbColor(uint8_t((imgBuffer[numDiv+Div/LedStripCount][i] & 0xF800)>>8),uint8_t((imgBuffer[numDiv+Div/LedStripCount][i] & 0x07C0)>>3),uint8_t((imgBuffer[numDiv+Div/LedStripCount][i] & 0x001F)<<3))); } strip2.Show(); strip.Show(); break; } */ numDiv++; if(numDiv >= (Div / LedStripCount)) numDiv = 0; // donetime=micros()-donetime; //Serial.printf("FUcking done tiime:%d",int(donetime)); // stripshowtime=micros()-stripshowtime; // Serial.printf("FUcking stripshow tiime:%d",int(stripshowtime)); } if(stateDiv == 0 ){ //strip.ClearTo(black); /// strip.Show(); // strip2.ClearTo(black); // strip2.Show(); } } } void webloop(void *pvParameters) { server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) { request->send(200, "text/plain", "Hi! I am bbPOV-P."); }); AsyncElegantOTA.begin(&server); // Start ElegantOTA server.serveStatic("/", SD_MMC, "/"); server.begin(); Serial.println("HTTP server started"); vTaskDelete(NULL); } ================================================ FILE: Arduino/HardwareTest/FreeRTOS/FreeRTOS.ino ================================================ // the setup function runs once when you press reset or power the board TaskHandle_t loop1Handle,loop2Handle; #include "soc/timer_group_struct.h" #include "soc/timer_group_reg.h" void setup() { // initialize serial communication at 115200 bits per second: Serial.begin(115200); // Now set up two tasks to run independently. xTaskCreatePinnedToCore( loop1 , "loop1" // A name just for humans , 1024 // This stack size can be checked & adjusted by reading the Stack Highwater , NULL , 20 // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest. , &loop1Handle , 0); xTaskCreatePinnedToCore( loop2 , "loop2" , 1024 // Stack size , NULL , 20 // Priority , &loop2Handle , 0); // Now the task scheduler, which takes over control of scheduling individual tasks, is automatically started. } void loop() { // Empty. Things are done in Tasks. } void loop1(void *pvParameters) // This is a task. { for (;;) { TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE; TIMERG0.wdt_feed=1; TIMERG0.wdt_wprotect=0; Serial.println("loop1"); Serial.println("loop1Done"); } } void loop2(void *pvParameters) // This is a task. { for (;;) { TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE; TIMERG0.wdt_feed=1; TIMERG0.wdt_wprotect=0; Serial.println("loop2"); Serial.println("loop2Done"); } } ================================================ FILE: Arduino/HardwareTest/ImgDivSpeedtest/ImgDivSpeedtest.ino ================================================ #include Ticker hallHit; #include #include #include #include #include #include #include #include "SD_MMC.h" #include "JPEGDEC.h" #include "soc/timer_group_struct.h" #include "soc/timer_group_reg.h" #include #include "webpage.h" //显示相关 #define PixelCount 80 //单边LED数量 #define LedStripCount 2 //LED条数 #define BufferNum 2 #define Div 320 #define MaxStreamBuffer 10*1024 #define OFFSET_34 0 #define OFFSET_35 0 uint16_t (*imgBuffer)[320][PixelCount]; uint8_t streamBuffer[MaxStreamBuffer]; //一些机制需要用到的全局变量 JPEGDEC jpeg; File root; File dir; File myfile; TaskHandle_t nextFileHandle; int bufferRot=-1; WebServer server(80); int numRot= 0; int numDiv = 0; int stateDiv = 0; int spinstae = 1; volatile unsigned long rotTime, timeOld, timeNow, opeTime, spinTime; NeoPixelBus strip2(PixelCount); NeoPixelBus strip(PixelCount); DynamicJsonDocument doc(4096); JsonArray avaliableMedia = doc.to(); int displayMode = 0; int curMedia = 0; WiFiServer tcpStream; //声明服务器对象 WiFiClient client; bool autoNext = true; RgbColor black(0); void IRAM_ATTR RotCount(){ static unsigned long last_interrupt_time = 0; unsigned long interrupt_time = millis(); //deBounce,as the signal not stable sometimes 去抖动 if (interrupt_time - last_interrupt_time > 20) { numDiv = 0; bufferRot++; if(bufferRot>=BufferNum-1) bufferRot=0; timeNow = micros(); rotTime = timeNow - timeOld; timeOld = timeNow; xTaskNotifyGive( nextFileHandle ); } last_interrupt_time = interrupt_time; } void setup() { pinMode(34,INPUT); pinMode(35,INPUT); Serial.begin(115200); if(imgBuffer = (uint16_t(*)[320][PixelCount]) calloc(PixelCount*Div*BufferNum,sizeof(uint16_t))) Serial.println("Alloc IMG Memory OK"); if(!SD_MMC.begin("/sdcard",true)){ Serial.println("Card Mount Failed"); } /* WiFi.mode(WIFI_AP); WiFi.softAP("bbPOV-P"); MDNS.begin("bbPOV"); MDNS.addService("bbPOV", "tcp", 80);*/ WiFi.begin("Hollyshit_A", "00197633"); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); server.on("/", []() { server.send_P(200, "text/html", index_html); }); server.on("/avaliableMedia", []() { String json; serializeJson(doc, json); server.send(200, "text/plain", json); }); server.on("/changeMedia",[]() { int mediaID = server.arg(0).toInt(); Serial.println(mediaID); dir=SD_MMC.open("/bbPOV-P/"+avaliableMedia[mediaID].as()); server.send(200, "text/plain", "OK"); }); server.on("/changeAutoNext",[]() { autoNext = !autoNext; if(autoNext) server.send(200, "text/plain", "True"); else server.send(200, "text/plain", "False"); }); ElegantOTA.begin(&server); server.begin(); Serial.println("HTTP server started"); tcpStream.begin(22333); //服务器启动监听端口号22333 strip.Begin(); strip.Show(); strip2.Begin(32,25,33,26); strip2.Show(); long lTime; root=SD_MMC.open("/bbPOV-P"); while(true){ File entry = root.openNextFile(); if(!entry) break; if(entry.isDirectory()){ avaliableMedia.add(String(entry.name()).substring(9)); } } dir=SD_MMC.open("/bbPOV-P/"+avaliableMedia[0].as()); if (jpeg.open("", myOpen, myClose, myRead, mySeek, JPEGDraw)) { lTime = micros(); if (jpeg.decode(0,0,0)) { lTime = micros() - lTime; Serial.printf("Successfully decoded image in %d us\n", (int)lTime); } jpeg.close(); } bufferRot=0; hallHit.attach(0.04,RotCount); attachInterrupt(35, RotCount, FALLING ); xTaskCreatePinnedToCore( nextFile , "nextFile" , 5000 // Stack size , NULL , 4 // Priority , &nextFileHandle , 0); xTaskCreatePinnedToCore( webloop , "webloop" , 5000 // Stack size , NULL , 2 // Priority , NULL , 0); Serial.println("Setup Done"); vTaskPrioritySet(NULL, 5); } void loop() { if(stateDiv == 1 && micros() - timeOld > (rotTime / Div) * (numDiv)){ stateDiv = 0; } if(stateDiv == 0 && micros() - timeOld < (rotTime / Div) * (numDiv + 1 )){ stateDiv = 1; // long donetime=micros(); int showNumDiv = numDiv; if(showNumDiv
>8),uint8_t((color & 0x07C0)>>3),uint8_t((color & 0x001F)<<3))); strip2.SetPixelColor(i, RgbColor(uint8_t((color2 & 0xF800)>>8),uint8_t((color2 & 0x07C0)>>3),uint8_t((color2 & 0x001F)<<3))); } } else{ for(int i = 0; i < PixelCount; i++){ uint16_t color = imgBuffer[bufferRot][showNumDiv][i]; uint16_t color2 = imgBuffer[bufferRot][showNumDiv-Div/LedStripCount][i]; strip.SetPixelColor(i, RgbColor(uint8_t((color & 0xF800)>>8),uint8_t((color & 0x07C0)>>3),uint8_t((color & 0x001F)<<3))); strip2.SetPixelColor(i, RgbColor(uint8_t((color2 & 0xF800)>>8),uint8_t((color2 & 0x07C0)>>3),uint8_t((color2 & 0x001F)<<3))); } } strip.Show(); strip2.Show(); numDiv++; if(numDiv == (Div / LedStripCount)){ bufferRot++; if(bufferRot>=BufferNum-1) bufferRot=0; xTaskNotifyGive( nextFileHandle ); } if(numDiv >= Div) numDiv=0; /* if(stateDiv == 0 ){ strip.ClearTo(black); strip.Show(); strip2.ClearTo(black); strip2.Show(); }*/ } } void webloop(void *pvParameters) { for (;;) { TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE; TIMERG0.wdt_feed=1; TIMERG0.wdt_wprotect=0; server.handleClient(); } } void * myOpen(const char *filename, int32_t *size) { Serial.print("Open:"); myfile = dir.openNextFile(); if(!myfile){ if(autoNext){ curMedia++; if(curMedia>=avaliableMedia.size()) curMedia=0; dir=SD_MMC.open("/bbPOV-P/"+avaliableMedia[curMedia].as()); } else dir.rewindDirectory(); myfile = dir.openNextFile(); } Serial.println(myfile.name()); *size = myfile.size(); return &myfile; } void myClose(void *handle) { if (myfile) myfile.close(); } int32_t myRead(JPEGFILE *handle, uint8_t *buffer, int32_t length) { if (!myfile) return 0; return myfile.read(buffer, length); } int32_t mySeek(JPEGFILE *handle, int32_t position) { if (!myfile) return 0; return myfile.seek(position); } int JPEGDraw(JPEGDRAW *pDraw) { // Serial.printf("jpeg draw: x,y=%d,%d, cx,cy = %d,%d\n",pDraw->x, pDraw->y, pDraw->iWidth, pDraw->iHeight); //Serial.printf("Before Pixel 80 = 0x%04x\n", pDraw->pPixels[80]); int sdbufferRot = bufferRot+1; if(sdbufferRot >= BufferNum-1) sdbufferRot=0; int pixels=pDraw->iWidth*pDraw->iHeight; memcpy(&imgBuffer[sdbufferRot][pDraw->y][pDraw->x],pDraw->pPixels,sizeof(uint16_t)*pixels); // Serial.println(ESP.getFreeHeap()); return 1; } void nextFile(void *pvParameters){ for (;;) { TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE; TIMERG0.wdt_feed=1; TIMERG0.wdt_wprotect=0; client = tcpStream.available(); //尝试建立客户对象 // client.setNoDelay(true); if (client) //如果当前客户可用 { Serial.println("[Client connected]"); while (client.connected()) //如果客户端处于连接状态 { TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE; TIMERG0.wdt_feed=1; TIMERG0.wdt_wprotect=0; ulTaskNotifyTake( pdTRUE, portMAX_DELAY ); if (client.available()) //如果有可读数据 { String buff = client.readStringUntil('\r'); int len = buff.toInt(); client.readBytes(streamBuffer,len); if (jpeg.openRAM(streamBuffer, len, JPEGDraw)) { // Serial.printf("Image size: %d x %d, orientation: %d, bpp: %d\n", jpeg.getWidth(), // jpeg.getHeight(), jpeg.getOrientation(), jpeg.getBpp()); if (jpeg.decode(0,0,0)) { // full sized decode } jpeg.close(); } } } // client.stop(); //结束当前连接: // Serial.println("[Client disconnected]"); } else{ ulTaskNotifyTake( pdTRUE, portMAX_DELAY ); // Serial.println("File"); //long lTime=micros(); if (jpeg.open("", myOpen, myClose, myRead, mySeek, JPEGDraw)) { if (jpeg.decode(0,0,0)) { // lTime = micros() - lTime; Serial.println("Successfully decoded "); } jpeg.close(); } } } } ================================================ FILE: Arduino/HardwareTest/ImgDivSpeedtest/webpage.h ================================================ const char index_html[] PROGMEM = R"rawliteral(
bbPOV-P
⏸️

可用图像:

)rawliteral"; ================================================ FILE: Arduino/HardwareTest/JPEGDEC/JPEGDEC.ino ================================================ #include "SD_MMC.h" #include "JPEGDEC.h" JPEGDEC jpeg; File myfile; void * myOpen(const char *filename, int32_t *size) { Serial.println("Open"); myfile = SD_MMC.open(filename); *size = myfile.size(); return &myfile; } void myClose(void *handle) { if (myfile) myfile.close(); } int32_t myRead(JPEGFILE *handle, uint8_t *buffer, int32_t length) { if (!myfile) return 0; return myfile.read(buffer, length); } int32_t mySeek(JPEGFILE *handle, int32_t position) { if (!myfile) return 0; return myfile.seek(position); } uint16_t (*imgBuffer)[80]; uint16_t (*imgBuffer2)[80]; // Function to draw pixels to the display int JPEGDraw(JPEGDRAW *pDraw) { Serial.printf("jpeg draw: x,y=%d,%d, cx,cy = %d,%d\n",pDraw->x, pDraw->y, pDraw->iWidth, pDraw->iHeight); //Serial.printf("Before Pixel 80 = 0x%04x\n", pDraw->pPixels[80]); int pixels=pDraw->iWidth*pDraw->iHeight; if(pDraw->x+pDraw->y*80+pixels>=360*80){ pixels=pDraw->x+pDraw->y*80+pixels-360*80; } else{ memcpy(&imgBuffer[pDraw->y][pDraw->x],pDraw->pPixels,sizeof(uint16_t)*pixels); // Serial.println(ESP.getFreeHeap()); } return 1; } void setup() { pinMode(2, INPUT_PULLUP); Serial.begin(115200); if(imgBuffer = (uint16_t(*)[80]) calloc(80*360,sizeof(uint16_t))) Serial.println("Alloc memory1 OK"); else Serial.println("FUC KXJP"); if(imgBuffer2 = (uint16_t(*)[80]) calloc(80*360,sizeof(uint16_t))) Serial.println("Alloc memory2 OK"); else Serial.println("FUC KPLY"); if(!SD_MMC.begin("/sdcard",true)){ Serial.println("Card Mount Failed"); } Serial.println("setup done"); } /* setup() */ void loop() { long lTime; if (jpeg.open("/sb.jpg", myOpen, myClose, myRead, mySeek, JPEGDraw)) { Serial.println("Successfully opened JPEG image"); Serial.printf("Image size: %d x %d, orientation: %d, bpp: %d\n", jpeg.getWidth(), jpeg.getHeight(), jpeg.getOrientation(), jpeg.getBpp()); if (jpeg.hasThumb()) Serial.printf("Thumbnail present: %d x %d\n", jpeg.getThumbWidth(), jpeg.getThumbHeight()); lTime = micros(); if (jpeg.decode(0,0,0)) { lTime = micros() - lTime; Serial.printf("Successfully decoded image in %d us\n", (int)lTime); } jpeg.close(); } Serial.printf("After Pixel 80 = 0x%04x\n", imgBuffer[160][50]); Serial.printf("\n\navailable heap in main %i\n", ESP.getFreeHeap()); Serial.printf("biggest free block: %i\n\”", heap_caps_get_largest_free_block(MALLOC_CAP_8BIT)); delay(10000); } ================================================ FILE: Arduino/HardwareTest/MultiThreadDivSpeedtest/MultiThreadDivSpeedtest.ino ================================================ #include #include #include #include #include #include #include #include "SD_MMC.h" #include "JPEGDEC.h" #include #include "soc/timer_group_struct.h" #include "soc/timer_group_reg.h" //显示相关 #define PixelCount 80 //单边LED数量 #define LedStripCount 2 //LED条数 uint32_t Frame = 0; byte Hall = 0; //到达顶端的霍尔传感器代号 uint32_t Div = 320; //一些机制需要用到的全局变量 Ticker hallHit; JPEGDEC jpeg; File myfile; AsyncWebServer server(80); int numRot= 0; int numDiv = 0; int stateDiv = 0; int spinstae = 1; volatile unsigned long rotTime, timeOld, timeNow, opeTime, spinTime; NeoPixelBus strip2(PixelCount); NeoPixelBus strip(PixelCount); //Adafruit_DotStar_VSPI stripA(PixelCount,DOTSTAR_BRG); //CRGB leds[PixelCount]; AsyncWebSocket ws("/ws"); RgbColor black(0); void RotCountCommon(){ static unsigned long last_interrupt_time = 0; unsigned long interrupt_time = millis(); //deBounce,as the signal not stable sometimes 去抖动 if (interrupt_time - last_interrupt_time > 20) { numDiv=0; timeNow = micros(); rotTime = timeNow - timeOld; timeOld = timeNow; //Serial.println("RotCount"); } last_interrupt_time = interrupt_time; } TaskHandle_t loop1Handle,loop2Handle,loopSetledHandle; void setup() { pinMode(34,INPUT); pinMode(35,INPUT); Serial.begin(115200); WiFi.mode(WIFI_AP); WiFi.softAP("bbPOV-P"); MDNS.begin("bbPOV"); MDNS.addService("bbPOV", "tcp", 80); server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) { request->send(200, "text/plain", "Hi! I am bbPOV-P."); }); AsyncElegantOTA.begin(&server); // Start ElegantOTA if(!SD_MMC.begin("/sdcard")){ Serial.println("Card Mount Failed"); } server.serveStatic("/", SD_MMC, "/"); server.begin(); Serial.println("HTTP server started"); strip.Begin(); strip.Show(); strip2.Begin(32,25,33,26); strip2.Show(); RgbColor Divcolor (0,20,0); for(int i = 0; i < PixelCount; i++){ strip.SetPixelColor(i, Divcolor); strip2.SetPixelColor(i, Divcolor); } //stripA.begin(); // Initialize pins for output //stripA.show(); // Turn all LEDs off ASAP // FastLED.addLeds(leds, PixelCount); // FastLED.show(); hallHit.attach(0.033,RotCountCommon); Serial.println("Setup Done"); xTaskCreatePinnedToCore( loop1 , "loop1" // A name just for humans , 5000 // This stack size can be checked & adjusted by reading the Stack Highwater , NULL , 5 // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest. , &loop1Handle , 1); xTaskCreatePinnedToCore( loop2 , "loop2" , 5000 // Stack size , NULL , 5 // Priority , &loop2Handle , 1); xTaskCreatePinnedToCore( loopSetled , "loopSetled" , 10000 // Stack size , NULL , 5 // Priority , &loopSetledHandle , 1); } void loop() { //AsyncElegantOTA.loop(); //Serial.println("mainloop"); } void loopSetled(void *pvParameters){ for (;;) { TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE; TIMERG0.wdt_feed=1; TIMERG0.wdt_wprotect=0; if(stateDiv == 1 && micros() - timeOld > (rotTime / (Div/LedStripCount)) * (numDiv)){ stateDiv = 0; } if(stateDiv == 0 && micros() - timeOld < (rotTime / (Div/LedStripCount)) * (numDiv + 1 )){ stateDiv = 1; // long donetime=micros(); // switch(Hall){ // case 0: strip.ClearTo(black); strip2.ClearTo(black); RgbColor Divcolor (0,0,0); if(numDiv%3==0) // CHOU = CRGB::Red; Divcolor.R=16; if(numDiv%3==1) //CHOU = CRGB::Green; Divcolor.G=16; if(numDiv%3==2) // CHOU = CRGB::Blue; Divcolor.B=16; // long nowtime=micros(); for(int i = 0; i < PixelCount; i++){ strip.SetPixelColor(i, Divcolor); strip2.SetPixelColor(i, Divcolor); } // Serial.printf("FUcking setpixel tiime:%d",int(micros()-nowtime)); // FastLED.show(); //stripshowtime=micros(); //strip.Show(); //strip2.Show(); xTaskNotifyGive( loop1Handle ); xTaskNotifyGive( loop2Handle ); //ulTaskNotifyTake( pdTRUE, portMAX_DELAY ); // ulTaskNotifyTake( pdTRUE, portMAX_DELAY ); // stripshowtime=micros()-stripshowtime; // Serial.printf("FUcking stripshow tiime:%d",int(stripshowtime)); // stripA.show(); // break; /* case 1: strip.ClearTo(black); strip2.ClearTo(black); for(int i = 0; i < PixelCount; i++){ strip2.SetPixelColor(i, RgbColor(uint8_t((imgBuffer[numDiv][i] & 0xF800)>>8),uint8_t((imgBuffer[numDiv][i] & 0x07C0)>>3),uint8_t((imgBuffer[numDiv][i] & 0x001F)<<3))); strip.SetPixelColor(i, RgbColor(uint8_t((imgBuffer[numDiv+Div/LedStripCount][i] & 0xF800)>>8),uint8_t((imgBuffer[numDiv+Div/LedStripCount][i] & 0x07C0)>>3),uint8_t((imgBuffer[numDiv+Div/LedStripCount][i] & 0x001F)<<3))); } strip2.Show(); strip.Show(); break; } */ numDiv++; if(numDiv >= (Div / LedStripCount)) numDiv = 0; // donetime=micros()-donetime; //Serial.printf("FUcking done tiime:%d",int(donetime)); } if(stateDiv == 0 ){ strip.ClearTo(black); strip2.ClearTo(black); } } } void loop1(void *pvParameters) // This is a task. { for (;;) { TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE; TIMERG0.wdt_feed=1; TIMERG0.wdt_wprotect=0; ulTaskNotifyTake( pdTRUE, portMAX_DELAY ); //long stripshowtime=micros(); //Serial.println("Strip1 Show"); strip.Show(); // Serial.printf("[1]:%d\n",int(micros()-stripshowtime)); //Serial.println("[Strip1 Done]"); //stripshowtime=micros()-stripshowtime; // Serial.printf("[strip1]:%d",int(stripshowtime)); //ESP_LOGD("[1]:%ld\n",micros()-stripshowtime); } } void loop2(void *pvParameters) // This is a task. { for (;;) { TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE; TIMERG0.wdt_feed=1; TIMERG0.wdt_wprotect=0; ulTaskNotifyTake( pdTRUE, portMAX_DELAY ); // long stripshowtime=micros(); //Serial.println("Strip2 Show"); strip2.Show(); // Serial.printf("[2]:%d\n",int(micros()-stripshowtime)); // xTaskNotifyGive( loopSetledHandle ); // Serial.println("[Strip2 Done]"); // stripshowtime=micros()-stripshowtime; // Serial.printf("[strip2]:%d",int(stripshowtime)); //Serial.printf("[2]:%d\n",int(micros()-stripshowtime)); // ESP_LOGD("[2]:%ld\n",micros()-stripshowtime); } } ================================================ FILE: Arduino/HardwareTest/NeoPixelBitmap/NeoPixelBitmap.ino ================================================ // NeoPixelBuffer // This example will animate pixels using a bitmap stored on a SD card // // // This will demonstrate the use of the NeoBitmapFile object // NOTE: The images provided in the example directory should be copied to // the root of the SD card so the below code will find it. // NOTE: This sample and the included images were built for a 144 pixel strip so // running this with a smaller string may not look as interesting. Try providing // your own 24 bit bitmap for better results. #include #include #include #include #include "SD_MMC.h" const uint16_t PixelCount = 32; #include "SD_MMC.h" NeoPixelBrightnessBus strip2(PixelCount); NeoPixelBrightnessBus strip(PixelCount); NeoBitmapFile image; File bitmapFile; void setup() { pinMode(2, INPUT_PULLUP); delay(3000); Serial.begin(115200); if(!SD_MMC.begin("/sdcard",true)){ Serial.println("Card Mount Failed"); return; } strip.Begin(); strip.SetBrightness(10); strip.Show(); strip2.Begin(32,25,33,26); strip2.SetBrightness(10); strip2.Show(); // open the file bitmapFile = SD_MMC.open("/1.bmp", "r"); image.Begin(bitmapFile); image.Blt(strip, 0, 1, 1, 32); strip.SetBrightness(1); strip.Show(); image.Blt(strip2, 0, 1, 280, 32); strip2.SetBrightness(10); strip2.Show(); Serial.println(millis()); } void loop() { /* bitmapFile = SD_MMC.open("/1.bmp", "r"); image.Begin(bitmapFile); image.Blt(strip, 0, 1, 1, 32); strip.Show(); image.Blt(strip2, 0, 1, 280, 32); strip2.Show(); Serial.println(millis()); bitmapFile = SD_MMC.open("/2.bmp", "r"); image.Begin(bitmapFile); image.Blt(strip, 0, 0, 1, 32); strip.Show(); image.Blt(strip2, 0, 1, 280, 32); strip2.Show(); Serial.println(millis()); */ } ================================================ FILE: Arduino/HardwareTest/NeoPixelFunLoop/NeoPixelFunLoop.ino ================================================ // NeoPixelFunLoop // This example will move a trail of light around a series of pixels. // A ring formation of pixels looks best. // The trail will have a slowly fading tail. // // This will demonstrate the use of the NeoPixelAnimator. // It shows the advanced use an animation to control the modification and // starting of other animations. // It also shows the normal use of animating colors. // It also demonstrates the ability to share an animation channel rather than // hard code them to pixels. // #include #include #include #include #include "SD_MMC.h" AsyncWebServer server(80); #include #include const uint16_t PixelCount = 32; // make sure to set this to the number of pixels in your strip const uint16_t PixelPin = 2; // make sure to set this to the correct pin, ignored for Esp8266 const uint16_t AnimCount = PixelCount / 4 * 2 + 1; // we only need enough animations for the tail and one extra const uint16_t PixelFadeDuration = 200; // third of a second // one second divide by the number of pixels = loop once a second const uint16_t NextPixelMoveDuration = 500 / PixelCount; // how fast we move through the pixels NeoGamma colorGamma; NeoPixelBus strip2(PixelCount); NeoPixelBus strip(PixelCount); // For Esp8266, the Pin is omitted and it uses GPIO3 due to DMA hardware use. // There are other Esp8266 alternative methods that provide more pin options, but also have // other side effects. // for details see wiki linked here https://github.com/Makuna/NeoPixelBus/wiki/ESP8266-NeoMethods // what is stored for state is specific to the need, in this case, the colors and // the pixel to animate; // basically what ever you need inside the animation update function struct MyAnimationState { RgbColor StartingColor; RgbColor EndingColor; uint16_t IndexPixel; // which pixel this animation is effecting }; NeoPixelAnimator animations(AnimCount); // NeoPixel animation management object MyAnimationState animationState[AnimCount]; uint16_t frontPixel = 0; // the front of the loop RgbColor frontColor; // the color at the front of the loop void SetRandomSeed() { uint32_t seed; // random works best with a seed that can use 31 bits // analogRead on a unconnected pin tends toward less than four bits seed = analogRead(0); delay(1); for (int shifts = 3; shifts < 31; shifts += 3) { seed ^= analogRead(0) << shifts; delay(1); } // Serial.println(seed); randomSeed(seed); } void FadeOutAnimUpdate(const AnimationParam& param) { // this gets called for each animation on every time step // progress will start at 0.0 and end at 1.0 // we use the blend function on the RgbColor to mix // color based on the progress given to us in the animation RgbColor updatedColor = RgbColor::LinearBlend( animationState[param.index].StartingColor, animationState[param.index].EndingColor, param.progress); // apply the color to the strip strip.SetPixelColor(animationState[param.index].IndexPixel, colorGamma.Correct(updatedColor)); strip2.SetPixelColor(animationState[param.index].IndexPixel, colorGamma.Correct(updatedColor)); } void LoopAnimUpdate(const AnimationParam& param) { // wait for this animation to complete, // we are using it as a timer of sorts if (param.state == AnimationState_Completed) { // done, time to restart this position tracking animation/timer animations.RestartAnimation(param.index); // pick the next pixel inline to start animating // frontPixel = (frontPixel + 1) % PixelCount; // increment and wrap if (frontPixel == 0) { // we looped, lets pick a new front color frontColor = HslColor(random(360) / 360.0f, 1.0f, 0.25f); } uint16_t indexAnim; // do we have an animation available to use to animate the next front pixel? // if you see skipping, then either you are going to fast or need to increase // the number of animation channels if (animations.NextAvailableAnimation(&indexAnim, 1)) { animationState[indexAnim].StartingColor = frontColor; animationState[indexAnim].EndingColor = RgbColor(0, 0, 0); animationState[indexAnim].IndexPixel = frontPixel; animations.StartAnimation(indexAnim, PixelFadeDuration, FadeOutAnimUpdate); } } } void setup() { Serial.begin(115200); WiFi.mode(WIFI_AP); WiFi.softAP("bbPOV-P"); server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) { request->send(200, "text/plain", "Hi! I am ESP32."); }); AsyncElegantOTA.begin(&server); // Start ElegantOTA if(!SD_MMC.begin("/sdcard")){ Serial.println("Card Mount Failed"); // return; } server.serveStatic("/", SD_MMC, "/"); server.begin(); Serial.println("HTTP server started"); strip2.Begin(32,25,33,26); strip.Begin(); SetRandomSeed(); // we use the index 0 animation to time how often we move to the next // pixel in the strip animations.StartAnimation(0, NextPixelMoveDuration, LoopAnimUpdate); } void loop() { // this is all that is needed to keep it running // and avoiding using delay() is always a good thing for // any timing related routines animations.UpdateAnimations(); strip.Show(); strip2.Show(); AsyncElegantOTA.loop(); } ================================================ FILE: Arduino/HardwareTest/NeoPixelRainbow/NeoPixelRainbow.ino ================================================ #include #include #include #include #include #include AsyncWebServer server(80); const uint16_t PixelCount = 80; #include "SD_MMC.h" NeoPixelBrightnessBus strip2(PixelCount); NeoPixelBrightnessBus strip(PixelCount); RgbColor color; uint8_t pos; AsyncWebSocket ws("/ws"); void IRAM_ATTR RotCount1() { static unsigned long last_interrupt_time = 0; unsigned long interrupt_time = millis(); //deBounce,as the signal not stable sometimes 去抖动 if (interrupt_time - last_interrupt_time > 20) { Serial.println("RotCount1"); } last_interrupt_time = interrupt_time; } void IRAM_ATTR RotCount2() { static unsigned long last_interrupt_time = 0; unsigned long interrupt_time = millis(); if (interrupt_time - last_interrupt_time > 20) { Serial.println("RotCount2"); } last_interrupt_time = interrupt_time; } void setup() { pinMode(34, INPUT); pinMode(35, INPUT); pinMode(2, INPUT_PULLUP); pinMode(4, INPUT_PULLUP); pinMode(15, INPUT_PULLUP); pinMode(13, INPUT_PULLUP); pinMode(12, INPUT_PULLUP); Serial.begin(115200); WiFi.mode(WIFI_AP); WiFi.softAP("bbPOV-P"); MDNS.begin("bbclock"); MDNS.addService("bbclock", "tcp", 80); server.on("/", HTTP_GET, [](AsyncWebServerRequest * request) { request->send(200, "text/plain", "Hi! I am ESP32."); }); AsyncElegantOTA.begin(&server); // Start ElegantOTA if (!SD_MMC.begin("/sdcard")) { Serial.println("Card Mount Failed"); // return; server.on("/fuck", HTTP_GET, [](AsyncWebServerRequest * request) { request->send(200, "text/plain", "Fuck."); }); } server.serveStatic("/", SD_MMC, "/"); server.begin(); Serial.println("HTTP server started"); strip.Begin(); strip.SetBrightness(16); strip.Show(); strip2.Begin(32, 25, 33, 26); strip2.SetBrightness(16); strip2.Show(); Serial.println("Setup Done"); attachInterrupt(34, RotCount1, FALLING ); attachInterrupt(35, RotCount2, FALLING ); } int Rainbowperiod = 5; unsigned long Rainbowtime_now = 0; uint16_t j = 0; void loop() { AsyncElegantOTA.loop(); if (millis() > Rainbowtime_now + Rainbowperiod) { Rainbowtime_now = millis(); if (j < 256 * 5) j++; else j = 0; for (uint16_t i = 0; i < PixelCount; i++) { // generate a value between 0~255 according to the position of the pixel // along the strip pos = ((i * 256 / PixelCount) + j) & 0xFF; // calculate the color for the ith pixel color = Wheel( pos ); // set the color of the ith pixel strip.SetPixelColor(i, color); strip2.SetPixelColor(i, color); } strip.Show(); strip2.Show(); } } // Input a value 0 to 255 to get a color value. // The colours are a transition r - g - b - back to r. RgbColor Wheel(uint8_t WheelPos) { WheelPos = 255 - WheelPos; if (WheelPos < 85) { return RgbColor(255 - WheelPos * 3, 0, WheelPos * 3); } else if (WheelPos < 170) { WheelPos -= 85; return RgbColor(0, WheelPos * 3, 255 - WheelPos * 3); } else { WheelPos -= 170; return RgbColor(WheelPos * 3, 255 - WheelPos * 3, 0); } } ================================================ FILE: Arduino/HardwareTest/NeoPixelStatic/NeoPixelStatic.ino ================================================ #include #include #include #include AsyncWebServer server(80); #include const uint16_t PixelCount = 4; NeoPixelBus strip2(PixelCount); NeoPixelBus strip(PixelCount); #define colorSaturation 128 RgbColor red(colorSaturation, 0, 0); RgbColor green(0, colorSaturation, 0); RgbColor blue(0, 0, colorSaturation); RgbColor white(colorSaturation); RgbColor black(0); void setup() { Serial.begin(115200); WiFi.mode(WIFI_AP); WiFi.softAP("bbPOV-P"); server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) { request->send(200, "text/plain", "Hi! I am ESP32."); }); AsyncElegantOTA.begin(&server); // Start ElegantOTA server.begin(); Serial.println("HTTP server started"); strip2.Begin(32,25,33,26); strip.Begin(); strip.SetPixelColor(0, red); strip.SetPixelColor(1, green); strip.SetPixelColor(2, blue); strip.SetPixelColor(3, white); strip.Show(); } void loop() { AsyncElegantOTA.loop(); } ================================================ FILE: Arduino/HardwareTest/SDMMC_Test/SDMMC_Test.ino ================================================ /* * Connect the SD card to the following pins: * * SD Card | ESP32 //Actually all add 1K pull up except the CLK/VSS/VDD * D2 12 * D3 13 * CMD 15 * VSS GND * VDD 3.3V * CLK 14 * VSS GND * D0 2 (add 1K pull up after flashing) * D1 4 */ #include "FS.h" #include "SD_MMC.h" File root; void setup(){ pinMode(15, INPUT_PULLUP); pinMode(2, INPUT_PULLUP); pinMode(4, INPUT_PULLUP); pinMode(12, INPUT_PULLUP); pinMode(13, INPUT_PULLUP); Serial.begin(115200); if(!SD_MMC.begin("/sdcard",true)){ Serial.println("Card Mount Failed"); return; } uint8_t cardType = SD_MMC.cardType(); if(cardType == CARD_NONE){ Serial.println("No SD_MMC card attached"); return; } Serial.print("SD_MMC Card Type: "); if(cardType == CARD_MMC){ Serial.println("MMC"); } else if(cardType == CARD_SD){ Serial.println("SDSC"); } else if(cardType == CARD_SDHC){ Serial.println("SDHC"); } else { Serial.println("UNKNOWN"); } uint64_t cardSize = SD_MMC.cardSize() / (1024 * 1024); Serial.printf("SD_MMC Card Size: %lluMB\n", cardSize); Serial.printf("Total space: %lluMB\n", SD_MMC.totalBytes() / (1024 * 1024)); Serial.printf("Used space: %lluMB\n", SD_MMC.usedBytes() / (1024 * 1024)); root=SD_MMC.open("/"); } void loop(){ File file = root.openNextFile(); Serial.println(file.name()); if(!file){ root.rewindDirectory(); } } ================================================ FILE: Arduino/HardwareTest/TCPReceive/TCPReceive.ino ================================================ #include const char *ssid = "Hollyshit_A"; const char *password = "00197633"; WiFiServer server; //声明服务器对象 #include JPEGDEC jpeg; int JPEGDraw(JPEGDRAW *pDraw) { // do nothing return 1; // continue decode } void setup() { Serial.begin(115200); Serial.println(); WiFi.mode(WIFI_STA); // WiFi.setSleep(false); //关闭STA模式下wifi休眠,提高响应速度 WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println("Connected"); Serial.print("IP Address:"); Serial.println(WiFi.localIP()); server.begin(22333); //服务器启动监听端口号22333 } uint8_t streamBuffer[15*1024]; void loop() { WiFiClient client = server.available(); //尝试建立客户对象 if (client) //如果当前客户可用 { Serial.println("[Client connected]"); while (client.connected()) //如果客户端处于连接状态 { if (client.available()) //如果有可读数据 { String buff = client.readStringUntil('\r'); int len = buff.toInt(); client.readBytes(streamBuffer,len); if(streamBuffer[len-2]==0xFF && streamBuffer[len-1]==0xD9){ //JPG结尾 if (jpeg.openRAM(streamBuffer, len, JPEGDraw)) { Serial.printf("Image size: %d x %d, orientation: %d, bpp: %d\n", jpeg.getWidth(), jpeg.getHeight(), jpeg.getOrientation(), jpeg.getBpp()); if (jpeg.decode(0,0,0)) { // full sized decode } jpeg.close(); } } } } // client.stop(); //结束当前连接: // Serial.println("[Client disconnected]"); } } ================================================ FILE: Arduino/HardwareTest/UDPReceive/UDPReceive.ino ================================================ #include "WiFi.h" #include "AsyncUDP.h" const char * ssid = "Hollyshit_A"; const char * password = "00197633"; AsyncUDP udp; void setup() { Serial.begin(115200); WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); if (WiFi.waitForConnectResult() != WL_CONNECTED) { Serial.println("WiFi Failed"); while(1) { delay(1000); } } if(udp.listen(1234)) { Serial.print("UDP Listening on IP: "); Serial.println(WiFi.localIP()); udp.onPacket([](AsyncUDPPacket packet) { Serial.print("UDP Packet Type: "); Serial.print(packet.isBroadcast()?"Broadcast":packet.isMulticast()?"Multicast":"Unicast"); Serial.print(", From: "); Serial.print(packet.remoteIP()); Serial.print(":"); Serial.print(packet.remotePort()); Serial.print(", To: "); Serial.print(packet.localIP()); Serial.print(":"); Serial.print(packet.localPort()); Serial.print(", Length: "); Serial.print(packet.length()); Serial.print(", Data: "); Serial.write(packet.data(), packet.length()); Serial.println(); //reply to the client packet.printf("Got %u bytes of data", packet.length()); }); } } void loop() { delay(1000); //Send broadcast udp.broadcast("Anyone here?"); } ================================================ FILE: Arduino/HardwareTest/WebServer/WebServer.ino ================================================ #include #ifdef ESP32 #include #include "SD_MMC.h" #include #include #include #elif defined(ESP8266) #include #include #include #endif #include #include JPEGDEC jpeg; int JPEGDraw(JPEGDRAW *pDraw) { // do nothing return 1; // continue decode } // SKETCH BEGIN AsyncWebServer server(80); AsyncWebSocket ws("/ws"); AsyncEventSource events("/events"); void onWsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len){ if(type == WS_EVT_CONNECT){ Serial.printf("ws[%s][%u] connect\n", server->url(), client->id()); client->printf("Hello Client %u :)", client->id()); client->ping(); } else if(type == WS_EVT_DISCONNECT){ Serial.printf("ws[%s][%u] disconnect\n", server->url(), client->id()); } else if(type == WS_EVT_ERROR){ Serial.printf("ws[%s][%u] error(%u): %s\n", server->url(), client->id(), *((uint16_t*)arg), (char*)data); } else if(type == WS_EVT_PONG){ Serial.printf("ws[%s][%u] pong[%u]: %s\n", server->url(), client->id(), len, (len)?(char*)data:""); } else if(type == WS_EVT_DATA){ AwsFrameInfo * info = (AwsFrameInfo*)arg; String msg = ""; if(info->final && info->index == 0 && info->len == len){ //the whole message is in a single frame and we got all of it's data // Serial.printf("ws[%s][%u] %s-message[%llu]: ", server->url(), client->id(), (info->opcode == WS_TEXT)?"text":"binary", info->len); if(info->opcode == WS_TEXT){ for(size_t i=0; i < info->len; i++) { msg += (char) data[i]; } } else { char buff[3]; for(size_t i=0; i < info->len; i++) { sprintf(buff, "%02x ", (uint8_t) data[i]); msg += buff ; } } // Serial.printf("%s\n",msg.c_str()); if(info->opcode == WS_TEXT) client->text("I got your text message"); else client->binary("I got your binary message"); } else { //message is comprised of multiple frames or the frame is split into multiple packets if(info->index == 0){ // if(info->num == 0) // Serial.printf("ws[%s][%u] %s-message start\n", server->url(), client->id(), (info->message_opcode == WS_TEXT)?"text":"binary"); // Serial.printf("ws[%s][%u] frame[%u] start[%llu]\n", server->url(), client->id(), info->num, info->len); } // Serial.printf("ws[%s][%u] frame[%u] %s[%llu - %llu]: ", server->url(), client->id(), info->num, (info->message_opcode == WS_TEXT)?"text":"binary", info->index, info->index + len); if(info->opcode == WS_TEXT){ for(size_t i=0; i < len; i++) { msg += (char) data[i]; } } else { char buff[3]; for(size_t i=0; i < len; i++) { sprintf(buff, "%02x ", (uint8_t) data[i]); msg += buff ; } } // Serial.printf("%s\n",msg.c_str()); if((info->index + len) == info->len){ // Serial.printf("ws[%s][%u] frame[%u] end[%llu]\n", server->url(), client->id(), info->num, info->len); if(info->final){ // Serial.printf("ws[%s][%u] %s-message end\n", server->url(), client->id(), (info->message_opcode == WS_TEXT)?"text":"binary"); if(info->message_opcode == WS_TEXT) client->text("I got your text message"); else client->binary("I got your binary message"); } } } } } const char* ssid = "Hollyshit_A"; const char* password = "00197633"; const char * hostName = "esp-async"; const char* http_username = "admin"; const char* http_password = "admin"; void setup(){ Serial.begin(115200); Serial.setDebugOutput(true); WiFi.mode(WIFI_AP_STA); WiFi.softAP(hostName); WiFi.begin(ssid, password); if (WiFi.waitForConnectResult() != WL_CONNECTED) { Serial.printf("STA: Failed!\n"); WiFi.disconnect(false); delay(1000); WiFi.begin(ssid, password); } //Send OTA events to the browser ArduinoOTA.onStart([]() { events.send("Update Start", "ota"); }); ArduinoOTA.onEnd([]() { events.send("Update End", "ota"); }); ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { char p[32]; sprintf(p, "Progress: %u%%\n", (progress/(total/100))); events.send(p, "ota"); }); ArduinoOTA.onError([](ota_error_t error) { if(error == OTA_AUTH_ERROR) events.send("Auth Failed", "ota"); else if(error == OTA_BEGIN_ERROR) events.send("Begin Failed", "ota"); else if(error == OTA_CONNECT_ERROR) events.send("Connect Failed", "ota"); else if(error == OTA_RECEIVE_ERROR) events.send("Recieve Failed", "ota"); else if(error == OTA_END_ERROR) events.send("End Failed", "ota"); }); ArduinoOTA.setHostname(hostName); ArduinoOTA.begin(); MDNS.addService("http","tcp",80); if(!SD_MMC.begin("/sdcard",true)){ Serial.println("Card Mount Failed"); } ws.onEvent(onWsEvent); server.addHandler(&ws); events.onConnect([](AsyncEventSourceClient *client){ client->send("hello!",NULL,millis(),1000); }); server.addHandler(&events); server.on("/heap", HTTP_GET, [](AsyncWebServerRequest *request){ request->send(200, "text/plain", String(ESP.getFreeHeap())); }); server.serveStatic("/", SD_MMC, "/").setDefaultFile("index.htm"); server.onNotFound([](AsyncWebServerRequest *request){ }); server.onFileUpload(handleUpload); server.onRequestBody([](AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total){ if(!index) Serial.printf("BodyStart: %u\n", total); Serial.printf("%s", (const char*)data); if(index + len == total) Serial.printf("BodyEnd: %u\n", total); }); server.begin(); } void loop(){ ArduinoOTA.handle(); ws.cleanupClients(); } uint8_t streamBuffer[10*1024]; long lTime; void handleUpload(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final){ if(!index){ lTime=micros(); Serial.println((String)"UploadStart: " + filename); // open the file on first call and store the file handle in the request object //request->_tempFile = SD_MMC.open("/bbPOV-P/Stream/"+filename, "w"); } if(len) { //Serial.print("index:"); //Serial.println(index); // Serial.print("len:"); // Serial.println(len); memcpy(&streamBuffer[index],data,len); // stream the incoming chunk to the opened file // request->_tempFile.write(data,len); } if(final){ Serial.print("All length:"); Serial.println(index+len); if (jpeg.openRAM(streamBuffer, index+len, JPEGDraw)) { Serial.printf("Image size: %d x %d, orientation: %d, bpp: %d\n", jpeg.getWidth(), jpeg.getHeight(), jpeg.getOrientation(), jpeg.getBpp()); if (jpeg.decode(0,0,0)) { // full sized decode lTime = micros() - lTime; Serial.printf("Total time %d us\n", (int)lTime); } jpeg.close(); } // close the file handle as the upload is now done //request->_tempFile.close(); // request->send(200); } } ================================================ FILE: Arduino/HardwareTest/WebServer/data/.exclude.files ================================================ /*.js.gz /.exclude.files ================================================ FILE: Arduino/HardwareTest/WebServer/data/index.htm ================================================ WebSocketTester

    
$
================================================ FILE: Arduino/HardwareTest/strandtest/strandtest.ino ================================================ // Simple strand test for Adafruit Dot Star RGB LED strip. // This is a basic diagnostic tool, NOT a graphics demo...helps confirm // correct wiring and tests each pixel's ability to display red, green // and blue and to forward data down the line. By limiting the number // and color of LEDs, it's reasonably safe to power a couple meters off // the Arduino's 5V pin. DON'T try that with other code! #include #include #include #include #include // Because conditional #includes don't work w/Arduino sketches... #include // COMMENT OUT THIS LINE FOR GEMMA OR TRINKET //#include // ENABLE THIS LINE FOR GEMMA OR TRINKET #define NUMPIXELS 80 // Number of LEDs in strip // Here's how to control the LEDs from any two pins: #define DATAPIN 23 #define CLOCKPIN 18 //Adafruit_DotStar strip(NUMPIXELS, DATAPIN, CLOCKPIN, DOTSTAR_BRG); // The last parameter is optional -- this is the color data order of the // DotStar strip, which has changed over time in different production runs. // Your code just uses R,G,B colors, the library then reassigns as needed. // Default is DOTSTAR_BRG, so change this if you have an earlier strip. // Hardware SPI is a little faster, but must be wired to specific pins // (Arduino Uno = pin 11 for data, 13 for clock, other boards are different). Adafruit_DotStar_VSPI strip(NUMPIXELS, DOTSTAR_BRG); AsyncWebServer server(80); void setup() { WiFi.mode(WIFI_AP); WiFi.softAP("bbPOV-P"); server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) { request->send(200, "text/plain", "Hi! I am bbPOV-P."); }); AsyncElegantOTA.begin(&server); server.begin(); Serial.println("HTTP server started"); strip.begin(); // Initialize pins for output strip.show(); // Turn all LEDs off ASAP } // Runs 10 LEDs at a time along strip, cycling through red, green and blue. // This requires about 200 mA for all the 'on' pixels + 1 mA per 'off' pixel. int head = 0, tail = -10; // Index of first 'on' and 'off' pixels uint32_t color = 0xFF0000; // 'On' color (starts red) void loop() { AsyncElegantOTA.loop(); strip.setPixelColor(head, color); // 'On' pixel at head strip.setPixelColor(tail, 0); // 'Off' pixel at tail strip.show(); // Refresh strip delay(20); // Pause 20 milliseconds (~50 FPS) if(++head >= NUMPIXELS) { // Increment head index. Off end of strip? head = 0; // Yes, reset head index to start if((color >>= 8) == 0) // Next color (R->G->B) ... past blue now? color = 0xFF0000; // Yes, reset to red } if(++tail >= NUMPIXELS) tail = 0; // Increment, reset tail index } ================================================ FILE: Arduino/bbPOV-P/bbPOV-P.ino ================================================ #include #include #include #include #include #include #include #include "SD_MMC.h" #include "JPEGDEC.h" #include "soc/timer_group_struct.h" #include "soc/timer_group_reg.h" #include #include "webpage.h" //显示相关 #define PixelCount 80 //单边LED数量 #define LedStripCount 2 //LED条数 #define BufferNum 2 #define Div 320 #define MaxStreamBuffer 10*1024 #define OFFSET_34 0 #define OFFSET_35 0 uint16_t (*imgBuffer)[320][PixelCount]; uint8_t streamBuffer[MaxStreamBuffer]; //一些机制需要用到的全局变量 JPEGDEC jpeg; File root; File dir; File myfile; TaskHandle_t nextFileHandle; int bufferRot=-1; WebServer server(80); int numRot= 0; int numDiv = 0; int stateDiv = 0; int spinstae = 1; volatile unsigned long rotTime, timeOld, timeNow, opeTime, spinTime; NeoPixelBus strip2(PixelCount); NeoPixelBus strip(PixelCount); DynamicJsonDocument doc(4096); JsonArray avaliableMedia = doc.to(); int displayMode = 0; int curMedia = 0; WiFiServer tcpStream; //声明服务器对象 WiFiClient client; bool autoNext = true; RgbColor black(0); void IRAM_ATTR RotCount(){ static unsigned long last_interrupt_time = 0; unsigned long interrupt_time = millis(); //deBounce,as the signal not stable sometimes 去抖动 if (interrupt_time - last_interrupt_time > 20) { numDiv = 0; bufferRot++; if(bufferRot>=BufferNum-1) bufferRot=0; timeNow = micros(); rotTime = timeNow - timeOld; timeOld = timeNow; xTaskNotifyGive( nextFileHandle ); } last_interrupt_time = interrupt_time; } void setup() { pinMode(34,INPUT); pinMode(35,INPUT); Serial.begin(115200); if(imgBuffer = (uint16_t(*)[320][PixelCount]) calloc(PixelCount*Div*BufferNum,sizeof(uint16_t))) Serial.println("Alloc IMG Memory OK"); if(!SD_MMC.begin("/sdcard")){ Serial.println("Card Mount Failed"); } /* WiFi.mode(WIFI_AP); WiFi.softAP("bbPOV-P"); MDNS.begin("bbPOV"); MDNS.addService("bbPOV", "tcp", 80);*/ WiFi.begin("Hollyshit_A", "00197633"); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); server.on("/", []() { server.send_P(200, "text/html", index_html); }); server.on("/avaliableMedia", []() { String json; serializeJson(doc, json); server.send(200, "text/plain", json); }); server.on("/changeMedia",[]() { int mediaID = server.arg(0).toInt(); Serial.println(mediaID); dir=SD_MMC.open("/bbPOV-P/"+avaliableMedia[mediaID].as()); server.send(200, "text/plain", "OK"); }); server.on("/changeAutoNext",[]() { autoNext = !autoNext; if(autoNext) server.send(200, "text/plain", "True"); else server.send(200, "text/plain", "False"); }); ElegantOTA.begin(&server); server.begin(); Serial.println("HTTP server started"); tcpStream.begin(22333); //服务器启动监听端口号22333 strip.Begin(); strip.Show(); strip2.Begin(32,25,33,26); strip2.Show(); long lTime; root=SD_MMC.open("/bbPOV-P"); while(true){ File entry = root.openNextFile(); if(!entry) break; if(entry.isDirectory()){ avaliableMedia.add(String(entry.name()).substring(9)); } } dir=SD_MMC.open("/bbPOV-P/"+avaliableMedia[0].as()); if (jpeg.open("", myOpen, myClose, myRead, mySeek, JPEGDraw)) { lTime = micros(); if (jpeg.decode(0,0,0)) { lTime = micros() - lTime; Serial.printf("Successfully decoded image in %d us\n", (int)lTime); } jpeg.close(); } bufferRot=0; attachInterrupt(35, RotCount, FALLING ); xTaskCreatePinnedToCore( nextFile , "nextFile" , 5000 // Stack size , NULL , 4 // Priority , &nextFileHandle , 0); xTaskCreatePinnedToCore( webloop , "webloop" , 5000 // Stack size , NULL , 2 // Priority , NULL , 0); Serial.println("Setup Done"); vTaskPrioritySet(NULL, 5); } void loop() { if(stateDiv == 1 && micros() - timeOld > (rotTime / Div) * (numDiv)){ stateDiv = 0; } if(stateDiv == 0 && micros() - timeOld < (rotTime / Div) * (numDiv + 1 )){ stateDiv = 1; // long donetime=micros(); int showNumDiv = numDiv; if(showNumDiv
>8),uint8_t((color & 0x07C0)>>3),uint8_t((color & 0x001F)<<3))); strip2.SetPixelColor(i, RgbColor(uint8_t((color2 & 0xF800)>>8),uint8_t((color2 & 0x07C0)>>3),uint8_t((color2 & 0x001F)<<3))); } } else{ for(int i = 0; i < PixelCount; i++){ uint16_t color = imgBuffer[bufferRot][showNumDiv][i]; uint16_t color2 = imgBuffer[bufferRot][showNumDiv-Div/LedStripCount][i]; strip.SetPixelColor(i, RgbColor(uint8_t((color & 0xF800)>>8),uint8_t((color & 0x07C0)>>3),uint8_t((color & 0x001F)<<3))); strip2.SetPixelColor(i, RgbColor(uint8_t((color2 & 0xF800)>>8),uint8_t((color2 & 0x07C0)>>3),uint8_t((color2 & 0x001F)<<3))); } } strip.Show(); strip2.Show(); numDiv++; if(numDiv == (Div / LedStripCount)){ bufferRot++; if(bufferRot>=BufferNum-1) bufferRot=0; xTaskNotifyGive( nextFileHandle ); } if(numDiv >= Div) numDiv=0; /* if(stateDiv == 0 ){ strip.ClearTo(black); strip.Show(); strip2.ClearTo(black); strip2.Show(); }*/ } } void webloop(void *pvParameters) { for (;;) { TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE; TIMERG0.wdt_feed=1; TIMERG0.wdt_wprotect=0; server.handleClient(); } } void * myOpen(const char *filename, int32_t *size) { // Serial.println("Open"); myfile = dir.openNextFile(); if(!myfile){ if(autoNext){ curMedia++; if(curMedia>=avaliableMedia.size()) curMedia=0; dir=SD_MMC.open("/bbPOV-P/"+avaliableMedia[curMedia].as()); } else dir.rewindDirectory(); myfile = dir.openNextFile(); } // Serial.println(myfile.name()); *size = myfile.size(); return &myfile; } void myClose(void *handle) { if (myfile) myfile.close(); } int32_t myRead(JPEGFILE *handle, uint8_t *buffer, int32_t length) { if (!myfile) return 0; return myfile.read(buffer, length); } int32_t mySeek(JPEGFILE *handle, int32_t position) { if (!myfile) return 0; return myfile.seek(position); } int JPEGDraw(JPEGDRAW *pDraw) { // Serial.printf("jpeg draw: x,y=%d,%d, cx,cy = %d,%d\n",pDraw->x, pDraw->y, pDraw->iWidth, pDraw->iHeight); //Serial.printf("Before Pixel 80 = 0x%04x\n", pDraw->pPixels[80]); int sdbufferRot = bufferRot+1; if(sdbufferRot >= BufferNum-1) sdbufferRot=0; int pixels=pDraw->iWidth*pDraw->iHeight; memcpy(&imgBuffer[sdbufferRot][pDraw->y][pDraw->x],pDraw->pPixels,sizeof(uint16_t)*pixels); // Serial.println(ESP.getFreeHeap()); return 1; } void nextFile(void *pvParameters){ for (;;) { TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE; TIMERG0.wdt_feed=1; TIMERG0.wdt_wprotect=0; client = tcpStream.available(); //尝试建立客户对象 // client.setNoDelay(true); if (client) //如果当前客户可用 { Serial.println("[Client connected]"); while (client.connected()) //如果客户端处于连接状态 { TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE; TIMERG0.wdt_feed=1; TIMERG0.wdt_wprotect=0; ulTaskNotifyTake( pdTRUE, portMAX_DELAY ); if (client.available()) //如果有可读数据 { String buff = client.readStringUntil('\r'); int len = buff.toInt(); client.readBytes(streamBuffer,len); if (jpeg.openRAM(streamBuffer, len, JPEGDraw)) { // Serial.printf("Image size: %d x %d, orientation: %d, bpp: %d\n", jpeg.getWidth(), // jpeg.getHeight(), jpeg.getOrientation(), jpeg.getBpp()); if (jpeg.decode(0,0,0)) { // full sized decode } jpeg.close(); } } } // client.stop(); //结束当前连接: // Serial.println("[Client disconnected]"); } else{ ulTaskNotifyTake( pdTRUE, portMAX_DELAY ); // Serial.println("File"); //long lTime=micros(); if (jpeg.open("", myOpen, myClose, myRead, mySeek, JPEGDraw)) { if (jpeg.decode(0,0,0)) { // lTime = micros() - lTime; // Serial.printf("Successfully decoded image in %d us\n", (int)lTime); } jpeg.close(); } } } } ================================================ FILE: Arduino/bbPOV-P/webpage.h ================================================ const char index_html[] PROGMEM = R"rawliteral(
bbPOV-P
⏸️

可用图像:

)rawliteral"; ================================================ FILE: Arduino/bbPOV-P/webpage.html ================================================
bbPOV-P
⏸️

可用图像:

================================================ FILE: README.md ================================================ # bbPOV-P [English](https://github.com/RealCorebb/bbPOV-P/blob/main/README_EN.md "English") A new milestone? # ⭐ 100 Stars!!! Thank You!!! 🔗[PCB工程文件地址](https://oshwhub.com/Corebb/bbpov-mcu_copy_copy_copy "PCB工程文件地址") 😄[3D模型、更详细的教程](https://www.afdian.com/@kuruibb "3D模型、更详细的教程") 🧵[Threads](https://www.threads.net/@coreoobb "@coreoobb") @coreoobb 🐧QQ 群(仅供交流,人满请加Discord):647186542 😈Discord 频道:[加入](https://discord.gg/gvbcCtdQrk "加入") ▶️视频(Video):[Youtube](https://www.youtube.com/watch?v=HpYd48YgSek&t=5s "Youtube")[ Bilibili](https://www.bilibili.com/video/BV1Wy4y1a7t6 " Bilibili") # 禁止搬运到Gitee ![image](https://github.com/RealCorebb/bbPOV-P/blob/main/IMG/logo.jpg?raw=true) 新的自我突破 # 目录结构: **API** 包含取模软件、串流软件,都在NewConvert目录下,其它为一些早期的版本 **Arduino--HardwareTest** 开发过程中用来测试LED是否正常、硬件性能的一些硬件测试的软件,最终的主程序中用不到 **Arduino--bbPOV-P** 主程序 # 依赖库 除了[NeoPixelBus](https://github.com/RealCorebb/NeoPixelBus "NeoPixelBus")需要用我修改过的版本以外,其它的一般找对应名字就能找到 # 备选LED芯片 APA102-2020(好像有的版本IC芯片比较小,PWM速度不够) 价格¥0.67 HD107S-2020(查看了Datasheet,应该是无论5050还是2020版本都有着27khz的PWM) 价格¥0.80 LC8822-2020(~~有的地方说是26khz的PWM,但Datasheet里没看到,不清楚~~已发现其就是APA107) 价格¥0.68 LC8823-2020(~~规格跟HD107S相似,但找不到购买地址~~已发现其就是HD107S又名NS107S) ![image](https://github.com/RealCorebb/bbPOV-V3/blob/main/IMG/LED_Chips.jpg?raw=true)