787|1

2

帖子

1

TA的资源

一粒金砂(中级)

楼主
 

【得捷电子Follow me第4期】任务汇总提交 [复制链接]

  本帖最后由 eew_UPQWC7 于 2024-2-26 01:01 编辑

        很幸运能够抽中本次得捷电子Follow me第4期活动的参与名额,也很惭愧这个点才提交任务,还请审核大人海谅。



 

        一、本期任务硬件简介

        1.本期主板:

 

    

        2.本期采购的辅助硬件:

        包括:Seeed的GROVE - OLED DISPLAY0.96"(原本想直接W5500-EVB-PICO上使用的,因为没有扩展版,接线不便,计划将其作为远程显示屏使用);

M5家的ATOMS3U(作为远程显示屏的控制板使用刚好有GROVE接口);ESP THREAD BORDER ROUTER/ZIGBEE(作为发送UDP数据的终端使用)。

        来个合照:

 

        二、任务实现与展示

        1.入门任务:开发环境搭建,BLINK,驱动液晶显示器进行显示(没有则串口HelloWorld)

        开发环境:

        开发环境选择cpy简单方便,按住boot键插入usb,拖拽下好的固件至u盘即可,这里下载的adafruit-circuitpython-wiznet_w5500_evb_pico-en_US-8.2.9.uf2。

        待重启后,打开thony即可轻松连接开发板编辑程序。

        任务代码(显示屏接线麻烦,再TCP任务中使用网络远程调用):

import board
import busio as io
import adafruit_ssd1306
import digitalio
import time
#blink and hello world

# bgColor=0
# SCL=board.GP1
# SDA=board.GP0
# i2c = io.I2C(SCL,SDA)
# oled = adafruit_ssd1306.SSD1306_I2C(128, 64, i2c)
# 
# oled.fill(0)
# oled.text("Hello \nWorld!", 10, 10, not bgColor, font_name='font5x8.bin', size=3)
# oled.show()
print("hellow fm4!")

led = digitalio.DigitalInOut(board.GP25)
led.direction = digitalio.Direction.OUTPUT
led.value = True

while True:
    led.value = not led.value
    time.sleep(1)

         效果展示:

          

 

        2.基础任务一:完成主控板W5500初始化(静态IP配置),并能使用局域网电脑ping通,同时W5500可以ping通互联网站点;通过抓包软件(Wireshark、Sniffer等)抓取本地PC的ping报文,展示并分析。

        注意需要在lib目录下复制好所需调用的库文件:

 

        核心代码

from w5500 import w5500
import time
import board
import digitalio


print("Task-1 Ping Test")
#通过DHCP自动获取IP
# eth=w5500(is_dhcp=True)

#静态IP
eth=w5500()

led = digitalio.DigitalInOut(board.GP25)
led.direction = digitalio.Direction.OUTPUT

while True:
    led.value = not led.value
    time.sleep(1)

print("Done!")


        效果展示:

 

        抓包分析:

        通过wireshark可以抓取到ping过程的报文,ping的过程采用ICMP协议,一组报文分为两个,首先是ping请求,然后是被ping端的回应。

 

 

        3.基础任务二:主控板建立TCPIP或UDP服务器,局域网PC使用TCPIP或UDP客户端进行连接并发送数据,主控板接收到数据后,送液晶屏显示(没有则通过串口打印显示);通过抓包软件抓取交互报文,展示并分析。(TCP和UDP二选一,或者全都操作)

        核心代码:

        接收UDP数据,并将数据同过TCP传送并显示在ATOMS3U连接的LCD。

        主板代码:

from w5500 import w5500
import time
import board
import busio as io
import digitalio
import adafruit_ssd1306
import adafruit_wiznet5k.adafruit_wiznet5k_socket as socket
import asyncio

print("Task-2 TCP UDP")

led = digitalio.DigitalInOut(board.GP25)
led.direction = digitalio.Direction.OUTPUT



#初始化网卡
eth=w5500()

socket.set_interface(eth)
#创建远程LCD TCP socket
lcd_client = socket.socket()
lcd_server_ip='192.168.1.200'
lcd_server_port = 80 
lcd_client.connect((lcd_server_ip,lcd_server_port))
print("remote lcd connected !")

def rmLcdPrint(s:str):
    lcd_client.send(s+"\n")

#创建UDP socket
server_udp = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)  # Allocate socket for the server
server_port_udp = 5000
server_udp.bind((eth.pretty_ip(eth.ip_address),server_port_udp)) # Bind to IP and Port
print("Udp listening")

def taskUdp():
    data, addr = server_udp.recvfrom(50)
    if data:
        data=data.decode('utf-8')
        echoStr=f"get udp data:{data} @ {addr[0]}:{addr[1]}\n"
        print(echoStr)
        rmLcdPrint(echoStr)
        return echoStr
    else:
        return None


while True:
    taskUdp()



        atoms3U代码:

#include <M5AtomS3.h>
#include <WiFi.h>
#include <WiFiMulti.h>
#include <U8g2lib.h>

// Set the name and password of the wifi to be connected.
// 配置所连接wifi的名称和密码
const char *ssid = "OpenWrt";
const char *password = "01010101";
const uint16_t servPort = 80;
WiFiServer server(servPort);
const char *servIp = "192.168.1.200";

WiFiClient client;

const uint16_t port = 23; 

U8G2_SSD1306_128X64_NONAME_1_SW_I2C u8g2(U8G2_R0, /* clock=*/G1, /* data=*/G2, /* reset=*/U8X8_PIN_NONE); // All Boards without Reset of the Display

void lcdprint(String str)
{
  const u16_t strL = 22;
  u8g2.firstPage();
  do
  {
    if (str.length() > strL)
    {
      u8g2.setFont(u8g2_font_ncenB08_tr);
      const int row = str.length() / strL;
      for (int i = 0; i < row+1; i++)
      {
        u8g2.drawStr(0, 10 * (i + 1), str.substring(i * strL, (i + 1) * strL).c_str());
      }
    }
    else
    {
      u8g2.drawStr(0, 12, str.c_str());
    }
  } while (u8g2.nextPage());
}

void setup()
{
  Serial.begin(115200);
  u8g2.begin();
  int sum = 0;
  M5.begin(); // Init M5AtomS3.  初始化M5AtomS3
  WiFi.config(IPAddress(192, 168, 1, 200), IPAddress(192, 168, 1, 1), IPAddress(255, 255, 255, 0), IPAddress(192, 168, 1, 1));
  WiFi.begin(ssid, password);
  String msgStr;
  msgStr = "Waiting connect to WiFi: " + String(ssid);
  printf(msgStr.c_str());
  lcdprint(msgStr);

  while (WiFi.status() != WL_CONNECTED)
  {
    printf(".");
    lcdprint("...");
    delay(1000);
    sum += 1;
    if (sum == 8)
      printf("Conncet failed!\n");
    lcdprint("Conncet failed!");
  }
  char buff[100];
  sprintf(buff, "WiFi connected\nIP address: \n %s\n", WiFi.localIP().toString());
  lcdprint(buff);
  printf(buff); // The serial port outputs the IP address
                // of the M5AtomS3.  串口输出M5AtomS3的IP地址

  delay(500);
  sum = 0;
  server.begin();
  sprintf(buff, "Server started @%s:%d\n", WiFi.localIP().toString(), servPort);
  lcdprint(buff);

  // while (!client.connect(host, port))
  // {
  //   printf(
  //       "Connection failed.\nWaiting 5 seconds before retrying...\n");
  //   lcdprintf("Connection failed.\nWaiting 5 seconds before retrying...\n");
  //   delay(5000);
  //   sum += 1;
  //   if (sum > 8)
  //   {
  //     printf(
  //         "Connection failed. Time out!\n");
  //     lcdprintf("Connection failed. Time out!\n");
  //     return;
  //   }
  // }
  // sprintf(buff,"Connected to server.\n Client:%s:%d\n",client.remoteIP().toString().c_str(),client.remotePort());
  // printf(buff);
  // lcdprintf(buff);
}

void loop()
{
  WiFiClient client = server.available(); // 尝试建立客户对象
  char buff[100];
  if (client)
  {
    sprintf(buff, "%s connected", client.localIP().toString());
    lcdprint(buff);
    String readBuff; // 读取信息暂存
    while (client.connected())
    {

      if (client.available()) // 如果有可读数据
      {
        String buff = client.readStringUntil('\r');
        lcdprint(buff);
      }
    }
  }
  client.stop(); // 结束当前连接:
  sprintf(buff, "remote lcd @ %s:%d has no client connected!", servIp,servPort);
  lcdprint(buff);
  delay(1000);
}

        另外在ESP THREAD BORDER ROUTER/ZIGBEE循环发送udp数据,代码如下:

#include <Arduino.h>
#include <WiFi.h>
#include <WiFiUdp.h>

const char *ssid = "OpenWrt";
const char *password = "01010101";
const char *host = "192.168.1.255";
const u16_t udpPort= 5000;
char buffer[100];
bool status = false;
bool led_logic = false;
int countNum=0;
WiFiUDP Udp;

void setup() {
  Serial.begin(115200);
  WiFi.config(IPAddress(192, 168, 1, 150), IPAddress(192, 168, 1, 1), IPAddress(255, 255, 255, 0), IPAddress(192, 168, 1, 1));
  WiFi.begin(ssid, password);
  int sum = 0;
  while (WiFi.status() != WL_CONNECTED)
  {
    Serial.print(".");
    delay(1000);
    sum += 1;
    if (sum == 8)
      printf("Conncet failed!\n");
  }
  Udp.begin(udpPort);
  sprintf( buffer,"Udp begined @\n IP address:%s Port:%d\n", WiFi.localIP().toString(),udpPort);
  Serial.print(buffer);
}

void loop() {
  // int packetSize = Udp.parsePacket();
  Udp.beginPacket(host, udpPort); //准备发送数据
  char buff[100];
  sprintf(buff,"udp data @%s:%d, countNum=%d\n",WiFi.localIP().toString(),udpPort,countNum++);
  Udp.print(buff);    //复制数据到发送缓存
  Serial.println(buff);
  Udp.endPacket();    //发送数据
  delay(2000);

}

        效果展示:

可以看到远程显示屏分别显示了,PC发送至PICO及ESP THREAD BORDER ROUTER/ZIGBEE发送至PICO的UDP数据:

 

 

 

 

 

        抓包分析:

        可以看到UDP通信是不需求回应的,发送过程只有一帧报文。

 

        4.进阶任务:从NTP服务器(注意数据交互格式的解析)同步时间,获取时间送显示屏(串口)显示

        核心代码

# SPDX-FileCopyrightText: 2022 Scott Shawcroft for Adafruit Industries
# SPDX-License-Identifier: MIT

"""Print out time based on NTP."""
import rtc
import time
import board
import busio as io
import digitalio
import adafruit_ssd1306
import adafruit_ntp
import adafruit_wiznet5k.adafruit_wiznet5k_socket as socket
from w5500 import w5500

led = digitalio.DigitalInOut(board.GP25)
led.direction = digitalio.Direction.OUTPUT

#初始化屏幕
bgColor=0
SCL=board.GP1
SDA=board.GP0
i2c = io.I2C(SCL,SDA)
oled = adafruit_ssd1306.SSD1306_I2C(128, 64, i2c)


#初始化网卡
eth=w5500()

socket.set_interface(eth)

#创建socket
# socket= socket.socket()  # Allocate socket for the server

ntp = adafruit_ntp.NTP(socket, server="ntp.aliyun.com",tz_offset=8)

rtc.RTC().datetime = ntp.datetime


while True:
    datetime=time.localtime()
    timeStr=f"{datetime.tm_year}/{datetime.tm_mon}/{datetime.tm_mday}\n{datetime.tm_hour}:{datetime.tm_min}:{datetime.tm_sec}"
#     print(timeStr)
    oled.fill(0)
    oled.text(f'{timeStr}', 5, 5, not bgColor, font_name='font5x8.bin', size=2)
    oled.show()
    time.sleep(0.2)
    led.value = not led.value
    

        效果展示:

          5.终极任务二:使用外部存储器,组建简易FTP文件服务器,并能正常上传下载文件。

        核心代码:

from ftp_server import ftp
from sys import exit
import time
import board
import busio as io
import digitalio
import adafruit_ssd1306
import adafruit_ntp
import adafruit_wiznet5k.adafruit_wiznet5k_socket as socket
from w5500 import w5500

#初始化网卡
eth=w5500()

socket.set_interface(eth)

# my_ftp_server = ftp(socket, eth.ip,authlist={'usr1':123,'usr2':'abc'},verbose=True)
my_ftp_server = ftp(socket, eth.ip,path="/ftp/",verbose=True)
# my_ftp_server = ftp(socket, eth.ip,verbose=True)

print(my_ftp_server)

while True: # Customise your condition.
    print(f"polling:{my_ftp_server.poll()}")
    
# my_ftp_server.serve() # This will run forever

  效果展示:

    cpy环境下ftp服务器的被动模式一直未能成功,但是命令模式可以运行并传输文件,默认会下载至windows用户名文件夹:

 

 

        三、任务源码

https://download.eeworld.com.cn/detail/eew_UPQWC7/631393

补充内容 (2024-3-2 18:04): 四、对本活动的心得体会 通过本次活动学习了circuit python、树莓派pico的基本使用,了解了tcp/udp网络通信的基本原理和使用方法,收获满满!感谢主办方与赞助方共同提供的活动机会,期待eeword与得捷的下次活动。

最新回复

完成都是好样的,及学习到了知识,还收获了板板     详情 回复 发表于 2024-2-26 09:11
点赞 关注
 
 

回复
举报

6450

帖子

9

TA的资源

版主

沙发
 

完成都是好样的,及学习到了知识,还收获了板板  

个人签名

在爱好的道路上不断前进,在生活的迷雾中播撒光引

 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表