bitter

  • 2024-09-27
  • 加入了学习《【Follow me第二季第1期】任务提交》,观看 【Follow me第二季第1期】任务提交

  • 2024-09-01
  • 发表了主题帖: 【Follow me第二季第1期】任务提交

    本帖最后由 bitter 于 2024-9-27 21:48 编辑 【Follow me第二季第1期】任务提交 很高兴能够参加本期由得捷电子和eeworld社区共同举办得本次【Follow me第二季第1期】活动,想想前前后后也参加过好几次follow me活动了,这次应该是第三次了,还是很感谢得捷电子和eeworld社区提供的机会,期待后续活动再能出现一些有意思的板子~ 由于最近比较忙,收到板子后也是拖了比较长的时间直到最后几天才开始相关的活动,时间比较匆忙,完成的不是很好,希望各位审核大大能够手下留情、高抬贵手。 物料清单 我购买物料为活动必备物料开发板、推荐物料舵机、排针,还有一个传感器适配器,还以为是传感器本身,到手一看才发生是一个适配器。   物料展示      项目视频演示 【Follow me第二季第1期】任务提交-【Follow me第二季第1期】任务提交-EEWORLD大学堂 入门任务:开发环境搭建,板载LED点亮 按照Arduino | Adafruit Circuit Playground Express | Adafruit Learning System里的教程一步一步搭建arduino开发环境,并点亮板载LED。 官网下载IDE,https://www.arduino.cc/en/software 安装完成后,打开IDE,点击Tools->Board->Boards Manager,安装Arduino SAMD 安装完成后输入示例代码,使用MicroUSB 线连接开发板,选择对应得端口,点击upload即可烧录程序,观察到如下输出即代表烧录成功。 烧录成功后,重启开发板可以看到开发板上得红灯开始闪烁。 // the setup function runs once when you press reset or power the board void setup() { // initialize digital pin 13 as an output. pinMode(13, OUTPUT); } // the loop function runs over and over again forever void loop() { digitalWrite(13, HIGH); // turn the LED on (HIGH is the voltage level) delay(1000); // wait for a second digitalWrite(13, LOW); // turn the LED off by making the voltage LOW delay(1000); // wait for a second }  演示图片:   软件流程图:   基础任务一:控制板载炫彩LED,跑马灯点亮和颜色变换 在本次任务中,我们使用到了Mini NeoPixel LED,需要借助Adafruit NeoPixel Library这个库。下载完成后,点击->Sketch->Include Library->Add .ZIP Library…,将对应得库文件导入即可。 #include <Adafruit_NeoPixel.h> #define PIN 8 // 定义按钮引脚 #define BUTTON_COLOR 4 // 调节亮度 Adafruit_NeoPixel strip = Adafruit_NeoPixel(10, PIN, NEO_GRB + NEO_KHZ400); int currentColor = 0; int brightness = 50; void setup() { pinMode(BUTTON_COLOR, INPUT); // 设置按钮 strip.begin(); strip.setBrightness(brightness); strip.show(); } void loop() { // 检查按钮状态 checkButtons(); // 执行当前效果 switch (currentColor) { case 0: colorWipe(strip.Color(255, 0, 0), 50); break; case 1: colorWipe(strip.Color(0, 255, 0), 50); break; case 2: colorWipe(strip.Color(0, 0, 255), 50); break; case 3: colorWipe(strip.Color(0, 0, 0, 255), 50); break; } } bool checkButtons() { bool buttonPressed = false; static int lastButtonState = LOW; int buttonState = digitalRead(BUTTON_COLOR); if (buttonState == HIGH && lastButtonState == LOW) { delay(50); if (buttonState == HIGH && lastButtonState == LOW) { currentColor = (currentColor + 1)%4; buttonPressed = true; } } lastButtonState = buttonState; return buttonPressed; } void colorWipe(uint32_t c, uint8_t wait) { for (uint16_t i = 0; i < strip.numPixels(); i++) { strip.setPixelColor(i, c); strip.show(); if (checkButtons()) return; // 如果按钮被按下,则中断循环 } }   该程序主要是实现了每按一次按钮后,彩色LED在红、绿、蓝和灭四种状态转换。 演示图片:            软件流程图:   基础任务二:监测环境温度和光线,通过板载LED展示舒适程度 在本次任务中,我们除了需要使用上一个任务使用得Mini NeoPixel LED,还额外需要使用温度传感器和光传感器,需要借助Adafruit_CircuitPlayground这个库。安装方式按上一个任务将对应得库文件添加即可。 #include <Adafruit_CircuitPlayground.h> void setup() { CircuitPlayground.begin(); Serial.begin(921600); } void loop() { displayTemperature(); delay(250); displayBrightness(); delay(250); } void displayTemperature() { uint8_t ledCount; float temperature = CircuitPlayground.temperature(); uint32_t color; Serial.println("current temperature is"); Serial.println(temperature); ledCount= (int)temperature/5; color = CircuitPlayground.colorWheel((11-ledCount)*25); for (int i = 0; i < 10; i++) { if (i < ledCount) { CircuitPlayground.setPixelColor(9 - i, color); } else { CircuitPlayground.setPixelColor(9 - i, 0); // 关闭LED } } } void displayBrightness() { uint16_t brightness = CircuitPlayground.lightSensor(); uint8_t overallBrightness = map(brightness, 0, 500, 0, 100); Serial.println("current brightness is"); Serial.println(brightness); CircuitPlayground.setBrightness(overallBrightness); //调整所有灯珠亮度 }   该程序将通过串口实时输出当前的温度和环境亮度。根据当前温度将会实时点亮不同个数的LED并显示不同颜色;根据当前的环境亮度将会调整所有LED的亮度。 演示图片:             软件流程图:     基础任务三:接近检测——设定安全距离并通过板载LED展示,检测到入侵时,发起声音报警 在本次任务中,使用了Mini NeoPixel LED、红外发射器和接收器,还有蜂鸣器。 #include <Adafruit_CircuitPlayground.h> #define SAFE_DISTANCE 450 const int alertTone = 1000; const int irTransmitterPin = 25; const int irReceiverPin = A10; void setup() { CircuitPlayground.begin(); Serial.begin(921600); pinMode(irReceiverPin, INPUT); pinMode(irTransmitterPin, OUTPUT); } void loop() { sendIRPulse(); int distance = analogRead(irReceiverPin); displayDistance(distance); checkForIntrusion(distance); delay(300); } void displayDistance(int distance) { int ledCount = map(distance, 290, SAFE_DISTANCE, 1, 10); uint32_t color; Serial.print("Distance: "); Serial.print(distance); Serial.print(", LED Count: "); Serial.println(ledCount); color = CircuitPlayground.colorWheel((11-ledCount)*25); for (int i = 0; i < 10; i++) { if (i < ledCount) { CircuitPlayground.setPixelColor(i, color); } else { CircuitPlayground.setPixelColor(i, 0); } } } void checkForIntrusion(int distance) { if (distance > SAFE_DISTANCE) { Serial.println("Intrusion detected!"); playAlertTone(); } } void sendIRPulse() { for (int i = 0; i < 32; i++) { digitalWrite(irTransmitterPin, HIGH); delayMicroseconds(13); digitalWrite(irTransmitterPin, LOW); delayMicroseconds(13); } } void playAlertTone() { CircuitPlayground.playTone(alertTone, 1000); }   在靠近的过程中将逐渐点亮不同个数的LED并显示不同颜色,超过安全范围时蜂鸣器将会发出警告。 演示图片:       软件流程图:   进阶任务:制作不倒翁——展示不倒翁运动过程中的不同灯光效果 由于条件有限,没办法制作相应的不倒翁,所以我实际上是用板载陀螺仪检测板子的姿态,然后给出对应的灯光效果:即往哪边倾斜就点亮哪一边的LED,水平则全部点亮。 #include <Adafruit_CircuitPlayground.h> #include <math.h> void setup() { CircuitPlayground.begin(); Serial.begin(921600); } void loop() { float x = CircuitPlayground.motionX(); float y = CircuitPlayground.motionY(); float z = CircuitPlayground.motionZ(); int ledToLight = -1; Serial.print("X: "); Serial.print(x); Serial.print(" - Y: "); Serial.print(y); Serial.print(" - Z: "); Serial.print(z); z -= 9.8; if(abs(x)<2 && abs(y)<2 && abs(z)<2) ledToLight = -1; else if(y<-2 && abs(x)<2) ledToLight = 0; else if(y<-2 && x>2) ledToLight = 1; else if(x>2 && abs(y)<2) ledToLight = 2; else if(x>2 && y>2) ledToLight = 3; else if(y>2 && abs(x)<2) ledToLight = 4; else if(y>2 && x<-2) ledToLight = 6; else if(x<-2 && abs(y)<2) ledToLight = 7; else if(x<-2 && y<-2) ledToLight = 8; uint8_t color= map( ledToLight, 0, 9, 0, 255); if (ledToLight == -1) { for (int i = 0; i < 10; i++) { CircuitPlayground.setPixelColor(i, CircuitPlayground.colorWheel(85)); //水平时都点亮 } } else { for (int i = 0; i < 10; i++) { if (i == ledToLight || (ledToLight == 4 && i == 5) || (ledToLight == 0 && i == 9)) { CircuitPlayground.setPixelColor(i, CircuitPlayground.colorWheel(color));//点亮对应位置的 } else { CircuitPlayground.setPixelColor(i, 0); } } } Serial.print(" - LED To Light: "); Serial.println(ledToLight); delay(100); } 演示图片:                   软件流程图:   创意任务二:章鱼哥——章鱼哥的触角根据环境声音的大小,章鱼哥的触角可舒展或者收缩 由于时间和外部条件的限制,没有制作章鱼模型。本次任务是使用麦克风识别环境音量,根据环境音量的大小点亮不同个数的LED并显示不同颜色。除此之外,根据环境音量的变化逆时针或顺时针旋转舵机。 #include <Adafruit_CircuitPlayground.h> #include <Servo.h> float SoundLevel,lastsoundLevel; // 舵机定义 const int servoPin = A3; // 舵机连接的引脚 Servo myServo; int Speed=90; void setup() { CircuitPlayground.begin(); Serial.begin(921600); myServo.attach(servoPin); myServo.write(Speed); } void loop() { uint32_t color; int ledCount; float soundLevel = CircuitPlayground.mic.soundPressureLevel(10); ledCount = map(soundLevel, 50, 100, 0, 10); color = CircuitPlayground.colorWheel((11-ledCount)*25); Serial.print("Raw Sound Level: "); Serial.println(soundLevel); for (int i = 0; i < 10; i++) { if (i < ledCount) { CircuitPlayground.setPixelColor(i, color); } else { CircuitPlayground.setPixelColor(i, 0); } } if(fabs((lastsoundLevel-soundLevel))>1) { static uint8_t i=0; if(i++ % 2) Speed -= (int)(lastsoundLevel-soundLevel); else Speed += (int)(lastsoundLevel-soundLevel); } else Speed = 90; lastsoundLevel = soundLevel; myServo.write(Speed); Serial.print("Speed:"); Serial.println(Speed); delay(200); } 演示图片:       软件流程图:   项目总结 总的来说,由于时间匆忙,没有很深入的了解这款开发板,但是即使是在有限的条件下也了解了这块板子的多样性和强大功能。第一次使用Arduino,也学会了很多。 最后,感谢得捷电子和eeworld社区提供的机会,期待后续活动!    

  • 加入了学习《Follow me第二季第一期 任务演示》,观看 Follow me第二季第一期 任务演示

  • 加入了学习《Follow me第二季第1期》,观看 创意任务二:章鱼哥

  • 加入了学习《FollowMe 第二季: 1 Adafruit Circuit Playground Express及任务讲解》,观看 Adafruit Circuit Playground Express 及任务讲解

  • 2024-08-31
  • 加入了学习《【Follow me第二季第1期】全部任务演示》,观看 全部任务演示2.0

  • 加入了学习《【Follow me第二季第1期】任务提交-使用makecode开发(JavaScript)》,观看 【Follow me第二季第1期】任务提交-使用makecode开发(JavaScript)

  • 2024-08-29
  • 加入了学习《【Follow me第二季第1期】视频展示》,观看 得捷电子Follow me第二季第期视频展示

  • 2024-04-17
  • 加入了学习《泰克MSO6B探索营:应用案例深度解析》,观看 通用串行总线USB技术演进及测试方案

  • 2024-03-14
  • 回复了主题帖: 【Luckfox幸狐 RV1103】——文件传输+SDK 环境部署

    Jacktang 发表于 2024-3-14 07:34 文件传输+SDK 环境部署  之后下面准备怎么整 网友们都说内置的NOR FLASH 太小了,所以下一步打算使用SD卡烧录,连接摄像头,跑一下RKNN推理测试

  • 2024-03-12
  • 发表了主题帖: 【Luckfox幸狐 RV1103】——文件传输+SDK 环境部署

    一、文件传输 Win +R 在 Windows 地址栏输入 \\172.32.0.93,用户名为 root,密码为 luckfox。 拖动文件到想要存放的目录,完成传输。 二、SDK 环境部署 首先安装依赖环境。 sudo apt update sudo apt-get install -y git ssh make gcc gcc-multilib g++-multilib module-assistant expect g++ gawk texinfo libssl-dev bison flex fakeroot cmake unzip gperf autoconf device-tree-compiler libncurses5-dev pkg-config bc python-is-python3 passwd openssl openssh-server openssh-client vim file cpio rsync 获取最新的 SDK。 git clone https://gitee.com/LuckfoxTECH/luckfox-pico.git 在luckfox-pico根目录,输入 ./build.sh 按照对应的硬件选择,即可进行编译。

  • 发表了主题帖: 【Luckfox幸狐 RV1103】——ADB 登录+串口登录

    ADB 登录 下载 ADB 安装包, 右键我的电脑属性—>高级系统设置—>环境变量, 系统变量—>编辑—>将adb解压路径新建进去。 登录之前配置 RNDIS 虚拟网口,可以参考之前的文章。 使用adb connect 172.32.0.93命令连接 Luckfox Pico 。 使用adb devices命令查看 ADB 设备。 使用adb -s 172.32.0.93:5555 shell命令登录到开发板。 串口登录 根据原理图,将UART2_TX和UART2_RX与串口调试工具连接,使用串口调试助手连接。 打开串口调试助手,选择对应测串口,设置串口的波特率波特率为115200。 点击OK,按下回车,输入登录名:root 和登录密码:luckfox 就可以登陆了。

  • 2024-03-04
  • 加入了学习《泰克MSO6B探索营》,观看 如何完成AI芯片电源噪声测试

  • 加入了学习《泰克MSO6B探索营》,观看 MSO6B系列低噪声演示

  • 加入了学习《泰克MSO6B探索营》,观看 MSO6B-360度介绍

  • 加入了学习《泰克MSO6B探索营》,观看 工程师说走就走的旅行

  • 2024-02-25
  • 回复了主题帖: 【得捷电子Follow me第4期】扩展U8G2移植支持LCD显示

    厉害厉害,学习了  

  • 加入了学习《 【得捷电子Follow me第4期】》,观看 【得捷Follow me第4期】入门任务:开发环境搭建

  • 加入了学习《【得捷Follow me第4期】项目总结》,观看 【得捷Follow me第4期】项目总结

  • 2024-02-24
  • 发表了主题帖: 【得捷Follow me第4期】项目总结

    本帖最后由 bitter 于 2024-2-24 23:47 编辑 【得捷Follow me第4期】项目总结 很高兴能参加得捷电子Follow me第4期活动。 一、任务实现视频 【得捷Follow me第4期】项目总结-【得捷Follow me第4期】项目总结-EEWORLD大学堂 二、项目任务总结报告 1.入门任务:开发环境搭建,BLINK,驱动液晶显示器进行显示(没有则串口HelloWorld) 硬件环境 W5500-EVB-PICO(主控) AdafruitSharp Memory Display(显示) 根据相关资料,显示模块是通过SPI接口操作的,所以需要选定主控合适的引脚与显示模块引脚连接,完成spi驱动,选择以下引脚向连接。 W5500-EVB-PICO AdafruitSharp Memory Display GPIO13 CS GPIO14 CLK GPIO15 DI GND GND 3V3 VIN 软件环境 下载Thonny:Thonny, Python IDE for beginners 安装完成后,打开,点击右下角对应的端口即可。 下载固件: Circuitpython:W5500-EVB-Pico Download (circuitpython.org) MicroPython:MicroPython - Python for microcontrollers 将开发板通过micro USB线接电脑,按住BOOTSEL键后再短按一下RUN键,最后松开BOOTSEL键,电脑会将开发板识别成U盘。 将前面下载好的固件复制到此U盘,复制完成后开发板会自动重启,至此固件烧录完成。 下载库文件:Libraries (circuitpython.org) 这里需要注意,我们应该选择与之前下载的固件版本对应的库下载。 将下载的压缩包解压,并将需要的库文件复制到CIRCUITPY的盘符的lib文件夹下。 这里需要将font5x8.bin文件放入CIRCUITPY的盘符下,否则后续使用将报错。 相关代码 屏幕显示相关文字,并且每0.5s闪烁LED灯。 import time import board import busio import digitalio import adafruit_sharpmemorydisplay def led_flush(): led.value = not led.value time.sleep(0.5) def clear_disp(): # Clear the display. Always call show after changing pixels to make the display # update visible! display.fill(1) display.show() def disp_helloworld(): print("hello world") display.fill(1) display.text(" hello world!", 30, 50, 0) display.show() if __name__ == '__main__': led = digitalio.DigitalInOut(board.GP25) led.direction = digitalio.Direction.OUTPUT # Initialize SPI bus and control pins spi = busio.SPI(board.GP14, MOSI=board.GP15) scs = digitalio.DigitalInOut(board.GP13) # inverted chip select # pass in the display size, width and height, as well # display = adafruit_sharpmemorydisplay.SharpMemoryDisplay(spi, scs, 96, 96) display = adafruit_sharpmemorydisplay.SharpMemoryDisplay(spi, scs, 144, 168) clear_disp() disp_helloworld() while True: led_flush()   2.基础任务一:完成主控板W5500初始化(静态IP配置),并能使用局域网电脑ping通,同时W5500可以ping通互联网站点;通过抓包软件(Wireshark、Sniffer等)抓取本地PC的ping报文,展示并分析。 实现过程 将以下库文件复制到CIRCUITPY的盘符的lib文件夹下。 根据相关资料,RP2040与W5500引脚连接如下: 将W5500-EVB-PICO接入网络,并确保与本机IP地址处于同一网段。 查询本机IP地址为192.168.6.4 配置w5500的IP地址为192.168.6.100,网关为192.168.6.1 效果图 本地PC Ping W5500-EVB-PICO 抓包软件Wireshark抓取本地PC的ping报文 相关代码 屏幕初始化 def init(): led = digitalio.DigitalInOut(board.GP25) led.direction = digitalio.Direction.OUTPUT # Initialize SPI bus and control pins spi = busio.SPI(board.GP14, MOSI=board.GP15) scs = digitalio.DigitalInOut(board.GP13) # inverted chip select # pass in the display size, width and height, as well # display = adafruit_sharpmemorydisplay.SharpMemoryDisplay(spi, scs, 96, 96) display = adafruit_sharpmemorydisplay.SharpMemoryDisplay(spi, scs, 144, 168) return led,display w5500初始化 def init_w5500(ip, subnet, gateway, dns): ##SPI0 SPI0_SCK = board.GP18 SPI0_TX = board.GP19 SPI0_RX = board.GP16 SPI0_CSn = board.GP17 ##reset W5x00_RSTn = board.GP20 print("Wiznet5k Ping Test (no DHCP)") ethernetRst = digitalio.DigitalInOut(W5x00_RSTn) ethernetRst.direction = digitalio.Direction.OUTPUT # For Adafruit Ethernet FeatherWing cs = digitalio.DigitalInOut(SPI0_CSn) # For Particle Ethernet FeatherWing # cs = digitalio.DigitalInOut(board.D5) spi_bus = busio.SPI(SPI0_SCK, MOSI=SPI0_TX, MISO=SPI0_RX) # Reset W5500 first ethernetRst.value = False time.sleep(1) ethernetRst.value = True # Initialize ethernet interface without DHCP eth = WIZNET5K(spi_bus, cs, is_dhcp=False) # Set network configuration eth.ifconfig = (ip, subnet, gateway, dns) print("Chip Version:", eth.chip) print("My IP address is:", eth.pretty_ip(eth.ip_address)) return eth 完整代码 import time import board import busio import digitalio import array import struct import adafruit_sharpmemorydisplay from adafruit_wiznet5k.adafruit_wiznet5k import WIZNET5K import adafruit_wiznet5k.adafruit_wiznet5k_socket as socket IP_ADDRESS = (192, 168, 6, 100) SUBNET_MASK = (255, 255, 255, 0) GATEWAY_ADDRESS = (192, 168, 6, 1) DNS_SERVER = (8, 8, 8, 8) def init(): led = digitalio.DigitalInOut(board.GP25) led.direction = digitalio.Direction.OUTPUT # Initialize SPI bus and control pins spi = busio.SPI(board.GP14, MOSI=board.GP15) scs = digitalio.DigitalInOut(board.GP13) # inverted chip select # pass in the display size, width and height, as well # display = adafruit_sharpmemorydisplay.SharpMemoryDisplay(spi, scs, 96, 96) display = adafruit_sharpmemorydisplay.SharpMemoryDisplay(spi, scs, 144, 168) return led,display def led_flush(): led.value = not led.value time.sleep(0.5) def clear_disp(): # Clear the display. Always call show after changing pixels to make the display # update visible! display.fill(1) display.show() def init_w5500(ip, subnet, gateway, dns): ##SPI0 SPI0_SCK = board.GP18 SPI0_TX = board.GP19 SPI0_RX = board.GP16 SPI0_CSn = board.GP17 ##reset W5x00_RSTn = board.GP20 print("Wiznet5k Ping Test (no DHCP)") ethernetRst = digitalio.DigitalInOut(W5x00_RSTn) ethernetRst.direction = digitalio.Direction.OUTPUT # For Adafruit Ethernet FeatherWing cs = digitalio.DigitalInOut(SPI0_CSn) # For Particle Ethernet FeatherWing # cs = digitalio.DigitalInOut(board.D5) spi_bus = busio.SPI(SPI0_SCK, MOSI=SPI0_TX, MISO=SPI0_RX) # Reset W5500 first ethernetRst.value = False time.sleep(1) ethernetRst.value = True # Initialize ethernet interface without DHCP eth = WIZNET5K(spi_bus, cs, is_dhcp=False) # Set network configuration eth.ifconfig = (ip, subnet, gateway, dns) print("Chip Version:", eth.chip) print("My IP address is:", eth.pretty_ip(eth.ip_address)) return eth def disp_w5500(): clear_disp() display.fill(1) cst = "chip version:" + eth.chip display.text(cst, 0, 0, 0) cst = "ip:" + eth.pretty_ip(eth.ip_address) display.text(cst, 0, 10, 0) cst = "mac:" + eth.pretty_mac(eth.mac_address) display.text(cst, 0, 20, 0) display.show() if __name__ == '__main__': # 初始化led和显示模块 led,display = init() #静态初始化w5500 eth = init_w5500(IP_ADDRESS, SUBNET_MASK, GATEWAY_ADDRESS, DNS_SERVER) disp_w5500() while True: led_flush() 3.基础任务二:主控板建立TCPIP或UDP服务器,局域网PC使用TCPIP或UDP客户端进行连接并发送数据,主控板接收到数据后,送液晶屏显示(没有则通过串口打印显示);通过抓包软件抓取交互报文,展示并分析。(TCP和UDP二选一,或者全都操作) 实现过程 TCP连接过程 创建TCP服务器 使用调试工具连接 数据发送报错,不清楚是什么问题 相关代码 建立tcp服务器 def create_tcpserver(port): # Initialize a socket for our server socket.set_interface(eth) server = socket.socket() # Allocate socket for the server server_ip = None # IP address of server server_port = port # Port to listen on server.bind((server_ip, server_port)) # Bind to IP and Port server.listen() # Begin listening for incoming clients return server 完整代码 import time import board import busio import digitalio import array import struct import adafruit_sharpmemorydisplay from adafruit_wiznet5k.adafruit_wiznet5k import WIZNET5K import adafruit_wiznet5k.adafruit_wiznet5k_socket as socket IP_ADDRESS = (192, 168, 6, 100) SUBNET_MASK = (255, 255, 255, 0) GATEWAY_ADDRESS = (192, 168, 6, 1) DNS_SERVER = (8, 8, 8, 8) def init(): led = digitalio.DigitalInOut(board.GP25) led.direction = digitalio.Direction.OUTPUT # Initialize SPI bus and control pins spi = busio.SPI(board.GP14, MOSI=board.GP15) scs = digitalio.DigitalInOut(board.GP13) # inverted chip select # pass in the display size, width and height, as well # display = adafruit_sharpmemorydisplay.SharpMemoryDisplay(spi, scs, 96, 96) display = adafruit_sharpmemorydisplay.SharpMemoryDisplay(spi, scs, 144, 168) return led,display def led_flush(): led.value = not led.value time.sleep(0.5) def clear_disp(): # Clear the display. Always call show after changing pixels to make the display # update visible! display.fill(1) display.show() def init_w5500(ip, subnet, gateway, dns): ##SPI0 SPI0_SCK = board.GP18 SPI0_TX = board.GP19 SPI0_RX = board.GP16 SPI0_CSn = board.GP17 ##reset W5x00_RSTn = board.GP20 ethernetRst = digitalio.DigitalInOut(W5x00_RSTn) ethernetRst.direction = digitalio.Direction.OUTPUT # For Adafruit Ethernet FeatherWing cs = digitalio.DigitalInOut(SPI0_CSn) # For Particle Ethernet FeatherWing # cs = digitalio.DigitalInOut(board.D5) spi_bus = busio.SPI(SPI0_SCK, MOSI=SPI0_TX, MISO=SPI0_RX) # Reset W5500 first ethernetRst.value = False time.sleep(1) ethernetRst.value = True # Initialize ethernet interface without DHCP eth = WIZNET5K(spi_bus, cs, is_dhcp=False) # Set network configuration eth.ifconfig = (ip, subnet, gateway, dns) print("Chip Version:", eth.chip) print("My IP address is:", eth.pretty_ip(eth.ip_address)) return eth def disp_w5500(): clear_disp() display.fill(1) cst = "chip version:" + eth.chip display.text(cst, 0, 0, 0) cst = "ip:" + eth.pretty_ip(eth.ip_address) display.text(cst, 0, 10, 0) cst = "mac:" + eth.pretty_mac(eth.mac_address) display.text(cst, 0, 20, 0) display.show() def disp_str(s, addr): display.fill_rect(0,addr,144,10,1) display.text(s, 0, addr, 0) display.show() def create_tcpserver(port): # Initialize a socket for our server socket.set_interface(eth) server = socket.socket() # Allocate socket for the server server_ip = None # IP address of server server_port = port # Port to listen on server.bind((server_ip, server_port)) # Bind to IP and Port server.listen() # Begin listening for incoming clients return server if __name__ == '__main__': # 初始化led和显示模块 led,display = init() clear_disp() #静态初始化w5500 eth = init_w5500(IP_ADDRESS, SUBNET_MASK, GATEWAY_ADDRESS, DNS_SERVER) disp_w5500() # 创建一个tcp服务器 server = create_tcpserver(5000) conn, addr = server.accept() # Wait for a connection from a client. print("socket connected") print(addr) disp_str("TCP Server TEST", 30) disp_str('client:'+addr[0]+','+str(addr[1]), 50) disp_str('receive:', 60) linenum = 70 while True: led_flush() with server: while True: data = conn.recv(20) if data: print(data) disp_str(data.decode('utf-8'),linenum) linenum += 10 if linenum > 150: linenum = 70 4.进阶任务:从NTP服务器(注意数据交互格式的解析)同步时间,获取时间送显示屏(串口)显示。 实现过程 不知道为什么使用CircuitPython官方例程都报错 所以更换MicroPython,这里参考了@太阳上的骑士的代码 实现效果 相关代码 完整代码 from usocket import socket from machine import Pin,SPI,UART,RTC import network import time import ntptime uart = UART(0, baudrate=115200, bits=8, stop=1) #W5x00 chip init def w5x00_init(): spi=SPI(0,2_000_000, mosi=Pin(19),miso=Pin(16),sck=Pin(18)) nic = network.WIZNET5K(spi,Pin(17),Pin(20)) #spi,cs,reset pin nic.active(True) #None DHCP nic.ifconfig(('192.168.6.100','255.255.255.0','192.168.6.1','8.8.8.8')) #DHCP #nic.ifconfig('dhcp') print('IP address :', nic.ifconfig()) while not nic.isconnected(): time.sleep(1) #print(nic.regs()) def show_local_time(timezone=8): rtc = RTC() now = time.time() now += timezone * 3600 t = time.localtime(now) print(f'{t[0]} - {t[1]:02d}-{t[2]:02d} {t[3]:02d}:{t[4]:02d}:{t[5]:02d}') uart.write(f'{t[0]} - {t[1]:02d}-{t[2]:02d} {t[3]:02d}:{t[4]:02d}:{t[5]:02d}') def main(): w5x00_init() #先手动设置一个错误时间,模拟系统时间不准 rtc = RTC() rtc.datetime((2020, 1, 1, 3, 9, 0, 0, 0)) #年、月、日、星期、时、分、秒、亚秒 print('校时前系统时间:') show_local_time() #NTP校时 print('开始NTP校时...') ntptime.host = 'ntp1.aliyun.com' ntptime.settime() print(f'校时后系统时间:') show_local_time() while True: show_local_time() time.sleep(1) if __name__ == "__main__": main() 5.终极任务二:使用外部存储器,组建简易FTP文件服务器,并能正常上传下载文件。 实现过程 这里参考了@ eew_uscYT9的代码 在window的文件夹内搜索ftp服务器 将文件文件拖入其中 断开连接,重新访问 下载文件 相关代码 完整代码 # # Small ftp server for ESP8266 ans ESP32 Micropython # # Based on the work of chrisgp - Christopher Popp and pfalcon - Paul Sokolovsky # # The server accepts passive mode only. # It runs in foreground and quits, when it receives a quit command # Start the server with: # # import ftp # # Copyright (c) 2016 Christopher Popp (initial ftp server framework) # Copyright (c) 2016 Robert Hammelrath (putting the pieces together # and a few extensions) # Distributed under MIT License # import socket import network import uos import gc #from usocket import socket from machine import Pin,SPI,UART,PWM import time, network,framebuf ''' static netinfo ''' ip = '192.168.6.100' sn = '255.255.255.0' gw = '192.168.6.1' dns= '8.8.8.8' BL = 13 DC = 8 RST = 12 MOSI = 11 SCK = 10 CS = 9 netinfo=(ip, sn, gw, dns) localip = '' localport = 8000 listen_info = (localip, localport) conn_flag = False def w5x00_init(): global localip spi=SPI(0,2_000_000, mosi=Pin(19),miso=Pin(16),sck=Pin(18)) nic = network.WIZNET5K(spi,Pin(17),Pin(20)) nic.active(True) # use dhcp, if fail use static netinfo #try: # nic.ifconfig('dhcp') #except: nic.ifconfig(netinfo) localip = nic.ifconfig()[0] print('ip :', nic.ifconfig()[0]) print('sn :', nic.ifconfig()[1]) print('gw :', nic.ifconfig()[2]) print('dns:', nic.ifconfig()[3]) while not nic.isconnected(): time.sleep(1) # print(nic.regs()) print('no link') return nic def send_list_data(path, dataclient, full): try: # whether path is a directory name for fname in sorted(uos.listdir(path), key=str.lower): dataclient.sendall(make_description(path, fname, full)) except: # path may be a file name or pattern pattern = path.split("/")[-1] path = path[:-(len(pattern) + 1)] if path == "": path = "/" for fname in sorted(uos.listdir(path), key=str.lower): if fncmp(fname, pattern): dataclient.sendall(make_description(path, fname, full)) def make_description(path, fname, full): if full: stat = uos.stat(get_absolute_path(path, fname)) file_permissions = ("drwxr-xr-x" if (stat[0] & 0o170000 == 0o040000) else "-rw-r--r--") file_size = stat[6] description = "{} 1 owner group {:>10} Jan 1 2000 {}\r\n".format( file_permissions, file_size, fname) else: description = fname + "\r\n" return description def send_file_data(path, dataclient): with open(path, "rb") as file: chunk = file.read(512) while len(chunk) > 0: dataclient.sendall(chunk) chunk = file.read(512) def save_file_data(path, dataclient): with open(path, "wb") as file: chunk = dataclient.recv(512) while len(chunk) > 0: file.write(chunk) chunk = dataclient.recv(512) def get_absolute_path(cwd, payload): # Just a few special cases "..", "." and "" # If payload start's with /, set cwd to / # and consider the remainder a relative path if payload.startswith('/'): cwd = "/" for token in payload.split("/"): if token == '..': if cwd != '/': cwd = '/'.join(cwd.split('/')[:-1]) if cwd == '': cwd = '/' elif token != '.' and token != '': if cwd == '/': cwd += token else: cwd = cwd + '/' + token return cwd # compare fname against pattern. Pattern may contain # wildcards ? and *. def fncmp(fname, pattern): pi = 0 si = 0 while pi < len(pattern) and si < len(fname): if (fname[si] == pattern[pi]) or (pattern[pi] == '?'): si += 1 pi += 1 else: if pattern[pi] == '*': # recurse if (pi + 1) == len(pattern): return True while si < len(fname): if fncmp(fname[si:], pattern[pi+1:]): return True else: si += 1 return False else: return False if pi == len(pattern.rstrip("*")) and si == len(fname): return True else: return False def ftpserver(net, port=21, timeout=None): DATA_PORT = 13333 ftpsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) datasocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) ftpsocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) datasocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) ftpsocket.bind(socket.getaddrinfo("0.0.0.0", port)[0][4]) datasocket.bind(socket.getaddrinfo("0.0.0.0", DATA_PORT)[0][4]) ftpsocket.listen(1) ftpsocket.settimeout(timeout) datasocket.listen(1) datasocket.settimeout(None) msg_250_OK = '250 OK\r\n' msg_550_fail = '550 Failed\r\n' addr = net.ifconfig()[0] print("FTP Server started on ", addr) try: dataclient = None fromname = None do_run = True while do_run: cl, remote_addr = ftpsocket.accept() cl.settimeout(300) cwd = '/' try: # print("FTP connection from:", remote_addr) cl.sendall("220 Hello, this is Micropython.\r\n") while True: gc.collect() data = cl.readline().decode("utf-8").rstrip("\r\n") if len(data) <= 0: print("Client disappeared") do_run = False break command = data.split(" ")[0].upper() payload = data[len(command):].lstrip() path = get_absolute_path(cwd, payload) print("Command={}, Payload={}".format(command, payload)) if command == "USER": cl.sendall("230 Logged in.\r\n") elif command == "SYST": cl.sendall("215 UNIX Type: L8\r\n") elif command == "NOOP": cl.sendall("200 OK\r\n") elif command == "FEAT": cl.sendall("211 no-features\r\n") elif command == "PWD" or command == "XPWD": cl.sendall('257 "{}"\r\n'.format(cwd)) elif command == "CWD" or command == "XCWD": try: files = uos.listdir(path) cwd = path cl.sendall(msg_250_OK) except: cl.sendall(msg_550_fail) elif command == "CDUP": cwd = get_absolute_path(cwd, "..") cl.sendall(msg_250_OK) elif command == "TYPE": # probably should switch between binary and not cl.sendall('200 Transfer mode set\r\n') elif command == "SIZE": try: size = uos.stat(path)[6] cl.sendall('213 {}\r\n'.format(size)) except: cl.sendall(msg_550_fail) elif command == "QUIT": cl.sendall('221 Bye.\r\n') do_run = False break elif command == "PASV": cl.sendall('227 Entering Passive Mode ({},{},{}).\r\n'. format(addr.replace('.', ','), DATA_PORT >> 8, DATA_PORT % 256)) dataclient, data_addr = datasocket.accept() print("FTP Data connection from:", data_addr) DATA_PORT = 13333 active = False elif command == "PORT": items = payload.split(",") if len(items) >= 6: data_addr = '.'.join(items[:4]) # replace by command session addr if data_addr == "127.0.1.1": data_addr = remote_addr DATA_PORT = int(items[4]) * 256 + int(items[5]) dataclient = socket.socket(socket.AF_INET, socket.SOCK_STREAM) dataclient.settimeout(10) dataclient.connect((data_addr, DATA_PORT)) print("FTP Data connection with:", data_addr) cl.sendall('200 OK\r\n') active = True else: cl.sendall('504 Fail\r\n') elif command == "LIST" or command == "NLST": if not payload.startswith("-"): place = path else: place = cwd try: cl.sendall("150 Here comes the directory listing.\r\n") send_list_data(place, dataclient, command == "LIST" or payload == "-l") cl.sendall("226 Listed.\r\n") except: cl.sendall(msg_550_fail) if dataclient is not None: dataclient.close() dataclient = None elif command == "RETR": try: cl.sendall("150 Opening data connection.\r\n") send_file_data(path, dataclient) cl.sendall("226 Transfer complete.\r\n") except: cl.sendall(msg_550_fail) if dataclient is not None: dataclient.close() dataclient = None elif command == "STOR": try: cl.sendall("150 Ok to send data.\r\n") save_file_data(path, dataclient) cl.sendall("226 Transfer complete.\r\n") except: cl.sendall(msg_550_fail) if dataclient is not None: dataclient.close() dataclient = None elif command == "DELE": try: uos.remove(path) cl.sendall(msg_250_OK) except: cl.sendall(msg_550_fail) elif command == "RMD" or command == "XRMD": try: uos.rmdir(path) cl.sendall(msg_250_OK) except: cl.sendall(msg_550_fail) elif command == "MKD" or command == "XMKD": try: uos.mkdir(path) cl.sendall(msg_250_OK) except: cl.sendall(msg_550_fail) elif command == "RNFR": fromname = path cl.sendall("350 Rename from\r\n") elif command == "RNTO": if fromname is not None: try: uos.rename(fromname, path) cl.sendall(msg_250_OK) except: cl.sendall(msg_550_fail) else: cl.sendall(msg_550_fail) fromname = None elif command == "MDTM": try: tm=localtime(uos.stat(path)[8]) cl.sendall('213 {:04d}{:02d}{:02d}{:02d}{:02d}{:02d}\r\n'.format(*tm[0:6])) except: cl.sendall('550 Fail\r\n') elif command == "STAT": if payload == "": cl.sendall("211-Connected to ({})\r\n" " Data address ({})\r\n" "211 TYPE: Binary STRU: File MODE:" " Stream\r\n".format( remote_addr[0], addr)) else: cl.sendall("213-Directory listing:\r\n") send_list_data(path, cl, True) cl.sendall("213 Done.\r\n") else: cl.sendall("502 Unsupported command.\r\n") print("Unsupported command {} with payload {}".format( command, payload)) except Exception as err: print(err) finally: cl.close() cl = None except Exception as e: print(e) finally: datasocket.close() ftpsocket.close() if dataclient is not None: dataclient.close() if __name__ == "__main__": nic = w5x00_init() ftpserver(nic) 三、心得体会 很高兴能够参加本期由EEWORLD和得捷电子共同举办得捷电子Follow me第4期活动。在这次活动,我了解了如何建立TCP或UDP连接,如何从NTP服务器同步时间,如何组建简易FTP文件服务器。 最后,希望电子工程世界和得捷电子越办越好,以后能够多多的举办这样的活动,也希望大家能够从中收获满满。

最近访客

< 1/3 >

统计信息

已有43人来访过

  • 芯积分:442
  • 好友:--
  • 主题:33
  • 回复:49

留言

你需要登录后才可以留言 登录 | 注册


现在还没有留言