Alohaq

  • 2024-11-01
  • 加入了学习《 得捷电子Follow Me第2季第一期任务汇报》,观看 得捷电子Follow Me第4期任务汇报

  • 2024-10-23
  • 加入了学习《得捷Follow me第二季第1期视频》,观看 得捷Follow me第二季第1期视频

  • 2024-09-02
  • 加入了学习《Follow me 第二季第1期演示视频》,观看 Follow me 第二季第1期演示视频

  • 2024-09-01
  • 上传了资料: Follw Me第二季第一期全部任务源码

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

    本帖最后由 Alohaq 于 2024-11-4 13:04 编辑 一、前言 Follow me第二季第1期的用的主板为Adafruit Circuit Playground Express,其为一块一体化设计板,具有处理器、传感器、LED、USB等,非常适合用于电子产品和编程,能够让创意充分发挥。这期共有四个任务,分别为入门任务,基础任务,进阶任务和创意任务,创意任务选择了其中之一——《章鱼哥》,所有任务均已完成,视频链接为:https://training.eeworld.com.cn/video/40998。 本人这期任务所用器件如下: Adafruit Circuit Playground Express,为本期任务主板,任务必购硬件;   Round Display for Xiao(Seeed Studio),在我看来,没有显示的主板是不完整的,加上本期任务主板为圆形主板,遂配备圆形显示器,其驱动芯片为GC9A01,任务选购硬件;   自制转接板,用于将任务主板与圆形显示器组合,自制PCB打印;     SG90S,180°舵机,为创意任务《章鱼哥》配备,并配备机械手模拟触角,个人自备;   鲸鱼不倒翁一只,为进阶任务配备,个人自备;   机械手一个,模拟章鱼哥的触角,为创意任务《章鱼哥》配备,个人自备。 本人这期任务所用环境为:VScode+PlatformIO,软件开发框架为Arduino,主要依赖的驱动库为Adafruit Circuit Playground、GFX Library for Arduino,其中Adafruit Circuit Playground为官方Arduino驱动库,可以控制Adafruit Circuit Playground Express上的所有外设;GFX Library for Arduino是一个 Arduino 图形库,支持具有各种数据总线接口的各种显示器,本次用于驱动Round Display for Xiao显示板。 二、任务实现详情 2.1 入门任务 任务介绍:开发环境搭建,板载LED点亮(个人增加显示屏点亮)。 涉及器件:Adafruit Circuit Playground Express;Round Display for Xiao(Seeed Studio)。 涉及库:Adafruit Circuit Playground、GFX Library for Arduino。 具体内容: 开发环境采用VSCode+PlatformIO,其中PlatformIO为VSCode的插件,VSCode的安装不再赘述,安装完成后在扩展中搜索PaltformIO进行安装,随后新建项目,以本项目为例:Board选择Adafruit Circuit Playground Express,Framework选择Arduino,Name我命名为01_Primer_Led,可以个人选择保存路径,详情可见图2-1,随后创建即可,开发环境初步搭建完成。 图2-1 首次创建项目 接着我们再添加官方为准备的驱动库Adafruit Circuit Playground,在VSCode的标签页中选择PIO Home,然后点击侧边工具栏中的Libraries,搜索Adafruit Circuit Playground,找到后选择打开,并在进入后选择添加至工程,详情如图2-2所示。 图2-2 添加官方驱动库 添加完官方驱动库后,在源文件中包含头文件<Adafruit_CircuitPlayground.h>即可,随后进行编译,此时会发现编译不通过,如图2-3所示,有errors产出:#error TinyUsB is not selected, please select it in "Tools->Menu->USB Stack“,同时也能看出是源文件Adafruit_TinyUSB_API.cpp的29行报出。 图2-3 errors 追根溯源,打开Adafruit_TinyUSB_API.cpp,找到29行,如图2-4所示,可发现是在没有USE_TINYUSB宏定义的情况下,又宏定义了ARDUINO_ARCH_SAMD(Board选择Adafruit Circuit Playground Express时会定义该宏定义)的时候,会报出上述错误。我们可以在预编译中增加USE_TINYUSB来解决报错,也可以选择忽略Tiny USB的驱动库,两者均可在platformio.ini中实现,分别为build_flags = -D USE TINYUSB和lib_ignore = Adafruit TinyUSB Library,具体如图2-4所示,具体使用哪一个,取决于您是否需要TinyUSB,二者选其一即可,可用‘;‘进行注释。随后便可正常编译烧录。 图2-4 platformio.ini添加内容 由于该任务本人还需驱动圆形显示器,需要额外添加库,我选择的驱动库为GFX Library for Arduino,操作步骤同库Adafruit Circuit Playground,详情如图2-2所示。 图2-3 添加显示驱动库 驱动库添加完成后,在需要使用的源文件中加上头文件<Arduino_GFX_Library.h>,然后选择合适的驱动函数即可,具体见代码: #include <Adafruit_CircuitPlayground.h> #include <Arduino_GFX_Library.h> // #define GFX_BL DF_GFX_BL // default backlight pin, you may replace DF_GFX_BL to actual backlight pin Arduino_DataBus *bus = new Arduino_SWSPI(3 /* DC */, 2 /*CS*/, 10 /* SCK*/, 9 /* MOSI*/, 6 /*MISO*/); //CS A5(2) SCK A3(10) MOSI A2(9) MISO A1(6) DC A4(3) Arduino_GFX *gfx = new Arduino_GC9A01(bus, DF_GFX_RST, 0 /* rotation */, true /* IPS */); // the setup function runs once when you press reset or power the board void setup() { // initialize digital pin 13 as an output. pinMode(LED_BUILTIN, OUTPUT); gfx -> begin(); gfx->fillScreen(BLACK); gfx->setTextSize(3); gfx->setTextColor(RED); gfx->setCursor(15, 90); gfx->println("Hello World!"); gfx->println("Follow me 2-1"); delay(1000); // 5 seconds } // the loop function runs over and over again forever void loop() { digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level) delay(1000); // wait for a second digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW delay(1000); // wait for a second }   效果图: 图2-4 LED闪烁 图2-5 显示屏显示内容 2.2 基础任务一 任务介绍:控制板载炫彩LED,跑马灯点亮和颜色变换。 涉及器件:Adafruit Circuit Playground Express。 涉及库:Adafruit Circuit Playground。 具体内容:代码先是跑马灯,RGB逐一点亮,这个很好实现,for函数即可;随后是颜色变化,这里用上SIN函数加上时间,对r、g、b分别加上相位差赋值,进而实现炫彩呼吸渐变,详情见代码,代码如下: #include <Adafruit_CircuitPlayground.h> #include <math.h> // do NOT include the standard NeoPixel library void setup() { // initialize the Circuit Playground as usual // this will initialize the onboard NeoPixels as well CircuitPlayground.begin(); delay(100); // 跑马灯 for (uint8_t i=0; i<10; i++) { CircuitPlayground.setPixelColor(i, 255, 255, 255); delay(200); } } void loop() { static int time = 0; // 用于控制颜色渐变的时间变量 CircuitPlayground.clearPixels(); // 呼吸灯 for(int i=0; i<10; i++) { float angle = (float)(i + time) / 5.0 * M_PI; // 使用 sin 函数计算 RGB 颜色值 uint8_t r = (uint8_t)((sin(angle) + 1) * 127.5); uint8_t g = (uint8_t)((sin(angle + 2.0 * M_PI / 3.0) + 1) * 127.5); uint8_t b = (uint8_t)((sin(angle + 4.0 * M_PI / 3.0) + 1) * 127.5); CircuitPlayground.setPixelColor(i, r, g, b); // 设置第 i 个 LED 的颜色 } delay(50); // 延迟,用于控制动画的速度 time++; // 递增时间变量,以生成渐变效果 }   效果图: 图2-6 炫彩RGB 2.3 基础任务二 任务介绍:监测环境温度和光线,通过板载LED展示舒适程度。 涉及器件:Adafruit Circuit Playground Express。 涉及库:Adafruit Circuit Playground。 具体内容:主要利用光传感器,毕竟温度的升降较难控制且周期很长,简易利用读数,对应上0~1,该部分用于红光显示,1剩下部分分给蓝光,进而展示舒适度,这里红光表示环境很不舒适,反之越蓝越舒适。详情见代码,代码如下: #include <Adafruit_CircuitPlayground.h> void setup() { CircuitPlayground.begin(); // Serial.begin(9600); // while (!Serial); // Wait until serial console is opened // Serial.println("Ready to detection environment"); } float temp_range = 42-30; float r, b = 0; void loop() { // Serial.print("Light sensor: "); // Serial.println(CircuitPlayground.lightSensor()); // Serial.print("Temperature: "); // Serial.println(CircuitPlayground.temperature()); r = (CircuitPlayground.temperature() - 30) / temp_range; // Serial.println(r); r += (300 - CircuitPlayground.lightSensor() ) / 300.0; // Serial.println(r); if (r > 1) r = 1; b = 1 - r; CircuitPlayground.clearPixels(); for (int i = 0; i < 10; i++) { CircuitPlayground.setPixelColor(i, 255*r, 0, 255*b); } delay(500); }   效果图: 图2-7 黑暗环境下,红灯表明不舒适 2.4 基础任务三 任务介绍:接近检测——设定安全距离并通过板载LED展示,检测到入侵时,发起声音报警。 涉及器件:Adafruit Circuit Playground Express;Round Display for Xiao(Seeed Studio)。 涉及库:Adafruit Circuit Playground、GFX Library for Arduino。 具体内容: 图2-8 RX对应引脚 利用红外的TX发出38KHz的信号,模拟超声波测距,然后直接读取RX处的ADC值,码值越大,说明接收的信号越强,即物体越接近,注意不能通过RX接收处的解码芯片,否则无法完成,遂涉及引脚的寄存器操作,对应工程图如图2-8所示,同时距离会在显示屏上显示,越近数字越小,当数字为1时,发出“danger”声报警,同时rgb颜色随距离越近,由绿变红,详情见代码,代码如下: #include <Adafruit_CircuitPlayground.h> #include <Arduino_GFX_Library.h> // #define GFX_BL DF_GFX_BL // default backlight pin, you may replace DF_GFX_BL to actual backlight pin Arduino_DataBus *bus = new Arduino_SWSPI(3 /* DC */, 2 /*CS*/, 10 /* SCK*/, 9 /* MOSI*/, 6 /*MISO*/); //CS A5(2) SCK A3(10) MOSI A2(9) MISO A1(6) DC A4(3) Arduino_GFX *gfx = new Arduino_GC9A01(bus, DF_GFX_RST, 0 /* rotation */, true /* IPS */); void setup() { CircuitPlayground.begin(); // PA4做ADC输入 PORT->Group[PORTA].DIRCLR.reg = (1 << 4); // Set pin A4 as input PORT->Group[PORTA].PINCFG[4].bit.PMUXEN = 1; // Enable peripheral multiplexer on pin A4 PORT->Group[PORTA].PMUX[4 >> 1].reg |= PORT_PMUX_PMUXE_B; // Set pin A4 to peripheral function B (ADC) // 配置 ADC ADC->CTRLA.bit.ENABLE = 0; // 先禁用 ADC 以进行配置 ADC->INPUTCTRL.bit.MUXPOS = ADC_INPUTCTRL_MUXPOS_PIN4; // 选择 PA4 作为 ADC 输入通道 ADC->CTRLB.reg = ADC_CTRLB_PRESCALER_DIV64 | ADC_CTRLB_RESSEL_12BIT; // 设置预分频器和分辨率 ADC->SAMPCTRL.reg = 0x3F; // 设置采样时间 ADC->CTRLA.bit.ENABLE = 1; // 启用 ADC // PORT->Group[PORTA].DIRSET.reg = (1 << 17); // 将 PA17 配置为输出 // PORT->Group[PORTA].OUTSET.reg = (1 << 17); // 将 PA17 设置为高电平 pinMode(CPLAY_IR_EMITTER, OUTPUT); pinMode(CPLAY_BUZZER, OUTPUT); // pinMode(CPLAY_SPEAKER_SHUTDOWN, OUTPUT); // digitalWrite(CPLAY_SPEAKER_SHUTDOWN, HIGH); gfx -> begin(); gfx->fillScreen(BLACK); gfx->setTextSize(4); gfx->setTextColor(RED); // Serial.begin(9600); // while (!Serial); // Wait until serial console is opened // Serial.println("Ready to receive IR signals"); } const uint8_t spDANGER[] PROGMEM = {0x2D,0xBF,0x21,0x92,0x59,0xB4,0x9F,0xA2,0x87,0x10,0x8E,0xDC,0x72,0xAB,0x5B,0x9D,0x62,0xA6,0x42,0x9E,0x9C,0xB8,0xB3,0x95,0x0D,0xAF,0x14,0x15,0xA5,0x47,0xDE,0x1D,0x7A,0x78,0x3A,0x49,0x65,0x55,0xD0,0x5E,0xAE,0x3A,0xB5,0x53,0x93,0x88,0x65,0xE2,0x00,0xEC,0x9A,0xEA,0x80,0x65,0x82,0xC7,0xD8,0x63,0x0A,0x9A,0x65,0x5D,0x53,0xC9,0x49,0x5C,0xE1,0x7D,0x2F,0x73,0x2F,0x47,0x59,0xC2,0xDE,0x9A,0x27,0x5F,0xF1,0x8B,0xDF,0xFF,0x03}; void loop() { // CircuitPlayground.irSend.send(7, 0x5555, 16); // delay(1); for (int i = 0; i < 200; i++) { // 38kHz PWM信号 digitalWrite(CPLAY_IR_EMITTER, HIGH); delayMicroseconds(13); digitalWrite(CPLAY_IR_EMITTER, LOW); delayMicroseconds(13); } // digitalWrite(CPLAY_BUZZER, LOW); //Continue looping until you get a complete signal received // 开始转换 ADC->SWTRIG.bit.START = 1; // 启动 ADC 转换 // 等待转换完成 while (ADC->INTFLAG.bit.RESRDY == 0); // digitalWrite(CPLAY_IR_EMITTER, LOW); // 读取结果 uint16_t result = ADC->RESULT.reg; uint8_t dis = (result - 2300) / 60; // if (result > 1500) // Serial.println(result); gfx->setCursor(110, 110); gfx->fillScreen(BLACK); gfx->println(7-dis); if (dis >= 6) { CircuitPlayground.speaker.say(spDANGER); CircuitPlayground.speaker.end(); } for (int i = 0; i < 10; i++) { CircuitPlayground.setPixelColor(i, 255 * dis / 7.0, 255 * (7 - dis) / 7.0, 0); } delay(300); // delay(100); }   效果图:   图2-9 物体距离过近,红光警示 2.5进阶任务 任务介绍:制作不倒翁——展示不倒翁运动过程中的不同灯光效果。 涉及器件:Adafruit Circuit Playground Express。 涉及库:Adafruit Circuit Playground。 具体内容:首先利用LIS3DH得到X、Y、Z,其中LIS3DH设置加速度为±2g,采样为50Hz,故需对其处理(乘上4),处理完后,进而算出横滚角和俯仰角,计算如下:   再通过俯仰角和横滚角计算出对应方位及深度,利用方向角索引至对应RGB,再利用深度,决定点亮几个RGB,达到RGB随不倒翁运动而变化的效果。详情见代码,代码如下: #include <Adafruit_CircuitPlayground.h> void setup() { CircuitPlayground.begin(); CircuitPlayground.lis.setDataRate(LIS3DH_DATARATE_50_HZ); CircuitPlayground.lis.setRange(LIS3DH_RANGE_2_G); // Serial.begin(9600); // while (!Serial); // Wait until serial console is opened // Serial.println("Ready to read LIS3DH"); } float X, Y, Z; short pitch ,roll; void loop() { CircuitPlayground.lis.read(); X = (float)CircuitPlayground.lis.x*4/65536*1000; // 还可以试试看motionX Y = (float)CircuitPlayground.lis.y*4/65536*1000; Z = (float)CircuitPlayground.lis.z*4/65536*1000; pitch = (short)(atan2((float)(0-Y), Z) * 180 / 3.14159); //转换为度数 roll = (short)(atan2((float)(X), Z) * 180 / 3.14159); //转换为度数 float direction = atan2(roll, pitch); // 计算方向角 int ledIndex; // Serial.println(direction); // direction范围是[-PI, PI] if (direction >= 0) { ledIndex = round((direction / PI) * 6); // 映射到LED索引 } else { ledIndex = 11 + round((direction / PI) * 6); // 映射到LED索引 } // int ledIndex = round((direction / PI) * 6) % 12; // 映射到LED索引 // Serial.println(ledIndex); float tiltMagnitude = sqrt(pitch * pitch + roll * roll); // 计算倾斜幅度 int ledCount = round((tiltMagnitude / 90.0) * 6) * 2; // 映射点亮数量 static int time = 0; // 用于控制颜色渐变的时间变量 CircuitPlayground.clearPixels(); // float angle = (float)(time) / 10 * 2.0 * M_PI; float angle = (float)(time) / 5.0 * M_PI; // 使用 sin 函数计算 RGB 颜色值 uint8_t r = (uint8_t)((sin(angle) + 1) * 127.5); uint8_t g = (uint8_t)((sin(angle + 2.0 * M_PI / 3.0) + 1) * 127.5); uint8_t b = (uint8_t)((sin(angle + 4.0 * M_PI / 3.0) + 1) * 127.5); for (int i = -ledCount/2; i < ledCount/2; i++) { int indexToLight = ledIndex + i; // CircuitPlayground.setPixelColor(indexToLight, 0, 64, 64); CircuitPlayground.setPixelColor(indexToLight, r, g, b); } // Serial.println(ledIndex); time++; // 递增时间变量,以生成渐变效果 delay(100); }   效果图: 图2-10 不倒翁倾斜,rgb随倾斜方向亮灯 2.6 创意任务 任务介绍:章鱼哥——章鱼哥的触角根据环境声音的大小,章鱼哥的触角可舒展或者收缩。 涉及器件:Adafruit Circuit Playground Express。 涉及库:Adafruit Circuit Playground。 具体内容:章鱼哥听到环境噪音(利用板载的麦克风噪音检测实现),认为敌人来临,遂伸张触角游泳离开,即环境音变大则伸张触角,环境正常则收缩触角。代码如下: #include <Adafruit_CircuitPlayground.h> #include <Servo.h> Servo myservo; // create Servo object to control a servo void setup() { CircuitPlayground.begin(); myservo.attach(A5); // attaches the servo on pin 9 to the Servo object // Serial.begin(9600); // myservo.writeMicroseconds(1450); // 舵机顺时针旋转 } void loop() { // for (int pos = 0; pos <= 180; pos += 1) { // goes from 0 degrees to 180 degrees // // in steps of 1 degree // myservo.write(pos); // tell servo to go to position in variable 'pos' // delay(15); // waits 15ms for the servo to reach the position // } // CircuitPlayground.soundSensor(); // Serial.println(CircuitPlayground.soundSensor()); // Serial.println( CircuitPlayground.mic.soundPressureLevel(500) ); // myservo.writeMicroseconds(1300); // 舵机顺时针旋转 收缩 // delay(1000); // myservo.writeMicroseconds(1600);// 舵机逆时针旋转 伸张 // myservo.writeMicroseconds(2000);// 舵机逆时针旋转 // delay(2000); if ( CircuitPlayground.mic.soundPressureLevel(300) > 75)// 有噪声则伸张 { myservo.writeMicroseconds(1800);// 舵机逆时针旋转 伸张 } else { myservo.writeMicroseconds(1200); // 舵机顺时针旋转 收缩 } }   效果图: 图2-11 章鱼听到噪音,准备伸张触角 三、活动心得 收获满满!动手能力进一步得到加强,思路进一步得以展开!祝越办越好! 最后附上源码:Follw Me第二季第一期全部任务源码-嵌入式开发相关资料下载-EEWORLD下载中心  

  • 2024-02-26
  • 回复了主题帖: 【得捷Follow me第4期】项目总结

    秦天qintian0303 发表于 2024-2-26 09:12 Pico-LCD 1.14(用于大部分的显示任务),还是的带显示才能更高完成任务  就最终任务无法使用Pico-LCD(基础任务静态IP那无需显示),因为SPI分给W5500和SD卡,没硬件SPI支持显示了,又不想软模拟,就用UDP传给AtomS3当显示了。

  • 加入了学习《得捷电子Follow Me第4期任务汇报》,观看 得捷电子Follow Me第4期任务汇报

  • 加入了学习《Follow me 第4期任务视频》,观看 Follow me 第4期任务视频

  • 2024-02-25
  • 上传了资料: Follow me 第4期全部任务实现源码

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

    一、前言(含视频)         本次Follow Me 4共分为4个任务:入门任务,基础任务,进阶任务和终极任务,其中,基础任务分为两个小任务,所以共六个任务,都顺利完成。         并且已经将内容一的视频上传至网络大学堂,视频地址为:https://training.eeworld.com.cn/video/39296 ;视频里包含了各任务的现场烧录演示及说明。           任务完成所用开发环境为Paspberry Pi的Pico SDK v1.5.1+VSCode;其中VSCode不多赘述,而Paspberry Pi的Pico SDK v1.5.1的下载地址为 https://github.com/raspberrypi/pico-setup-windows,安装过程可参考 WIZnet W5500-EVB-Pico树莓派入门教程(一)-CSDN博客;           任务完成所用硬件如下几个:W5500-EVB-Pico(必购);Pico-LCD 1.14(用于大部分的显示任务);AtomS3(W5500-EVB-Pico在做FTP服务器时,读取SD卡需要用的SPI,导致无法使用Pico-LCD做显示,通过UDP传输显示数据给AtomS3,用AtomS3做显示);SEEED XIAO ESP32 C3(测试W5500-EVB-Pico的UDP Server功能)、DAPLink一个(自备,用于在线仿真,方便调试网络)以及自己绘制的LCD转接板一个,方便给将W5500-EVB-Pico主板与Pico-LCD组合起来,转接板如下: 图1-1         下面将各任务逐一介绍并展示(内容二)。 二、入门任务     2.1 任务介绍         搭建开发环境,点亮小灯让其闪烁,并在显示屏上显示内容。     2.2 主要代码片段         LCD的显示主要靠移植Pico-LCD的官方驱动,其下载地址为https://www.waveshare.net/w/upload/2/28/Pico_code.7z;将其C驱动部分复制至工程目录下,并改名为LCD,在工程目录下的CMake中添加如下命令: add_subdirectory(DISPLAY/Config) add_subdirectory(DISPLAY/LCD) add_subdirectory(DISPLAY/Fonts) add_subdirectory(DISPLAY/GUI)         并在项目目录下的CMake中添加如下命令: include_directories(../DISPLAY/Config) include_directories(../DISPLAY/GUI) include_directories(../DISPLAY/LCD)         这样即包含了Pico-LCD的驱动库,初始化后就可直接显示输入内容,初始化过程如下: DEV_Module_Init(); DEV_SET_PWM(30); LCD_1IN14_V2_Init(HORIZONTAL); LCD_1IN14_V2_Clear(BLACK); UDOUBLE Imagesize = LCD_1IN14_V2_HEIGHT*LCD_1IN14_V2_WIDTH*2; BlackImage = (UWORD *)malloc(Imagesize); Paint_NewImage((UBYTE *)BlackImage,LCD_1IN14_V2.WIDTH,LCD_1IN14_V2.HEIGHT, 0, BLACK); Paint_SetScale(65); Paint_SetRotate(ROTATE); Paint_Clear(BLACK); LCD_1IN14_V2_Display(BlackImage);         之后在Paint_DrawString_EN函数中输入字符串数组,显示坐标即可显示相应内容。         小灯的闪烁代码如下: const uint LED_PIN = PICO_DEFAULT_LED_PIN; gpio_init(LED_PIN); gpio_set_dir(LED_PIN, GPIO_OUT); while (true) { gpio_put(LED_PIN, 1); sleep_ms(250); gpio_put(LED_PIN, 0); sleep_ms(250); }     2.3 功能展示 图2-1 驱动显示屏(显示屏通过转接板叠加在主控板上) 图2-2 BLink     三、基础任务一     3.1 任务介绍         主板W5500-EVB-Pico获取静态IP,并且PC能够ping通,同时主板可以ping通外网;PCping通结果抓包显示。     3.2 主要代码片段         需要用到W5500的官方库,其地址为https://gitee.com/wiznet-hk/w5500-evb-pico-routine.git         随后如同上述LCD添加入库,即可调用相关函数即可实现静态IP:只要初始化W5500完成,再设置网络信息,标记为静态获取即可。 // 网络信息 默认静态 wiz_NetInfo net_info = { .mac = {0x00, 0x08, 0xdc, 0x1e, 0xed, 0x2e}, // Configured MAC address .ip = {192, 168, 1, 31}, // Configured IP address .sn = {255, 255, 255, 0}, // Configured subnet mask .gw = {192, 168, 1, 1}, // Configured gateway .dns = {8, 8, 8, 8}, // Configured domain address }; // 初始化 wizchip_initialize(); sleep_ms(50); wizchip_setnetinfo(&net_info); print_network_information(get_info);         想要ping通互联网,则是向特定的目的主机发送 ICMP(Internet Control Message Protocol 因特网报文控制协议)Echo 请求报文,核心代码如下: void ping_auto(uint8_t s, uint8_t *addr) { uint8_t i; int32_t len = 0; uint8_t cnt=0; for(i = 0; i<=3;i++) { sleep_ms(10); switch(getSn_SR(s)) { case SOCK_CLOSED: close(s); IINCHIP_WRITE(Sn_PROTO(s), IPPROTO_ICMP); if(socket(s,Sn_MR_IPRAW,3000,0)!=0) { } while(getSn_SR(s)!=SOCK_IPRAW); sleep_ms(2000); break; case SOCK_IPRAW: ping_request(s, addr); req++; sleep_ms(50); while(1) { if ( (len = getSn_RX_RSR(s) ) > 0) { ping_reply(s, addr, len); sleep_ms(50); rep++; break; } else if(cnt > 200) { printf( "Request Time out. \r\n"); cnt = 0; break; } else { cnt++; sleep_ms(50); /*wait 50ms*/ } // wait_time for 2 seconds, Break on fail } break; default: break; } #ifdef PING_DEBUG if(rep!=0) { printf("Ping Request = %d, PING_Reply = %d\r\n",req,rep); if(rep == req) printf( "PING SUCCESS\r\n " ); else printf( "REPLY_ERROR\r\n " ); } else{} #endif } }     3.3 功能展示 图3-1 PC端Ping主板成功图 图3-2 主控板Ping互联网成功串口输出图     四、基础任务二     4.1 任务介绍          主板W5500-EVB-Pico做UDP服务器,并能将PC端的UDP客户端发送内容显示在显示屏上,再抓包对比报文。同时使用SEEED XIAO ESP32 C3做UDP客户端进行测试。     4.2 核心代码片段          正常初始化网络即可,UDP主要涉及Socket,包含头文件 #include "socket.h" 即可,然后轮询状态(判断是否有数据传输等)即可,代码如下: int32_t udps_2(uint8_t sn, uint8_t* buf, uint16_t port) { int32_t ret; uint16_t size, sentsize; uint8_t destip[4]; uint16_t destport; switch(getSn_SR(sn)) { case SOCK_UDP : if((size = getSn_RX_RSR(sn)) > 0) { if(size > DATA_BUF_SIZE) size = DATA_BUF_SIZE; ret = recvfrom(sn, buf, size, destip, (uint16_t*)&destport); buf[ret]=0x00; // printf("recv from[%d.%d.%d.%d][%d]: %s\n", destip[0],destip[1],destip[2],destip[3],destport,buf); sprintf(RecvIP[RecvCnt], "> %d.%d.%d.%d:%d", destip[0],destip[1],destip[2],destip[3],destport); sprintf(RecvBuf[RecvCnt], "> %s", buf); ddebug(RecvIP[RecvCnt]); ddebug(RecvBuf[RecvCnt]); if(++RecvCnt >= 10) RecvCnt = 0; if(ret <= 0) { return ret; } size = (uint16_t) ret; sentsize = 0; while(sentsize != size) { ret = sendto(sn, buf+sentsize, size-sentsize, destip, destport); if(ret < 0) { return ret; } sentsize += ret; // Don't care SOCKERR_BUSY, because it is zero. } } break; case SOCK_CLOSED: if((ret = socket(sn, Sn_MR_UDP, port, 0x00)) != sn) return ret; printf("local port:%d\n",port); break; default : break; } return 1; }     4.3 成果展示           先是用PC端的UDP(192.168.1.22:3333)发送Follow Me 4!到到主控板(192.168.1.31:8000),并用WireShark抓包(过滤条件为<ip.addr == 192.168.1.31 and udp>),显示如下: 图4-1 PC和主控板UDP通信抓包显示            再用SEED XIAO ESP32C3做UDP的客户端(192.168.1.45:8000)去测试主控板的UDP服务器功能,每3秒发送一次Follow Me 4!;同时通过显示屏展示收到的内容,完成情况如下: 图4-2 主控板显示屏显示UDP接收内容(包含主机和XIAOESP32C3)   五、进阶任务     5.1 任务内容            从NTP服务器同步时间,获取时间送显示屏显示。     5.2 核心代码片段           本质上还是UDP,这里选择用tx的NTP服务器,测试期间其地址为106.55.184.199;NTP及格式解析核心代码如下: // NTP int8_t SNTP_run(datetime *time) { uint16_t RSR_len; uint32_t destip = 0; uint16_t destport; uint16_t startindex = 40; switch(getSn_SR(NTP_SOCKET)) { case SOCK_UDP: if ((RSR_len = getSn_RX_RSR(NTP_SOCKET)) > 0) { if (RSR_len > MAX_SNTP_BUF_SIZE) RSR_len = MAX_SNTP_BUF_SIZE; recvfrom(NTP_SOCKET, data_buf, RSR_len, (uint8_t *)&destip, &destport); get_seconds_from_ntp_server(data_buf,startindex); time->yy = Nowdatetime.yy; time->mo = Nowdatetime.mo; time->dd = Nowdatetime.dd; time->hh = Nowdatetime.hh; time->mm = Nowdatetime.mm; time->ss = Nowdatetime.ss; ntp_retry_cnt=0; close(NTP_SOCKET); return 1; } if(ntp_retry_cnt<0xFFFF) { if(ntp_retry_cnt==0)//first send request, no need to wait { sendto(NTP_SOCKET,ntpmessage,sizeof(ntpmessage),NTPformat.dstaddr,ntp_port); ntp_retry_cnt++; } else // send request again? it should wait for a while { if((ntp_retry_cnt % 0xFFF) == 0) //wait time { sendto(NTP_SOCKET,ntpmessage,sizeof(ntpmessage),NTPformat.dstaddr,ntp_port); ntp_retry_cnt++; } } } else //ntp retry fail { ntp_retry_cnt=0; close(NTP_SOCKET); } break; case SOCK_CLOSED: socket(NTP_SOCKET,Sn_MR_UDP,ntp_port,0); break; } return 0; } // 送显示 sprintf(time_str[count], "> %d-%02d-%02d %02d:%02d:%02d", time.yy, time.mo, time.dd, time.hh, time.mm, time.ss); ddebug(time_str[count]);     5.3 成果展示            NTP实验内容较好展示,直接百度上搜索北京时间,然后对比即可,显示每1s才刷新一次,会存在误差,对比如下: 图5-1 左为浏览器显示北京时间 右为主控板每秒输出时间   六、最终任务     6.1 任务内容           使用外部SD卡存储器,组建简易FTP文件服务器,并能正常上传下载文件。同时因SD卡需占用一路SPI,故舍弃LCD,采用UDP传输给AtomS3用于显示FTP服务器相关内容。     6.2 核心代码片段           主要是SD卡和FatFs的移植,有现成的库,地址为 https://github.com/elehobica/pico_fatfs.git ;           设置静态IP,并修改并记住FTP的ID和密码,再开启Fatfs功能,需要修改部分代码,主要添加两个接口函数,scan_files和get_filesize,分别是扫描和获取大小,内容如下 long get_filesize(const char *dirPath, const char *filename) { char fullPath[256]; // 假设路径长度不超过255个字符 FILINFO fno; FRESULT fr; // 构造完整路径 snprintf(fullPath, sizeof(fullPath), "%s/%s", dirPath, filename); // 使用 f_stat 获取文件信息 fr = f_stat(fullPath, &fno); if (fr == FR_OK) { return (long)fno.fsize; // 返回文件大小 } else { return -1; // 发生错误,返回 -1 } } FRESULT scan_files ( char *path, /* Start node to be scanned (***also used as work area***) */ char *files, uint16_t *num) { FRESULT res; DIR dir; UINT i; static FILINFO fno; uint16_t _num = 0; *num = 0; res = f_opendir(&dir, path); /* Open the directory */ if (res == FR_OK) { for (;;) { res = f_readdir(&dir, &fno); /* Read a directory item */ if (res != FR_OK || fno.fname[0] == 0) break; /* Break on error or end of dir */ i = strlen(path); uint8_t isdir = (fno.fattrib & AM_DIR); char size[32]; sprintf(size, "%ld", (fno.fattrib & AM_DIR) ? 0 : fno.fsize); files += sprintf(files, "%crwxr-xr-x 1 pomin pomin %s Jan 19 2024 %s\r\n", (fno.fattrib & AM_DIR) ? 'd' : '-', size, fno.fname); _num++; } f_closedir(&dir); } *num = _num; return res; }     6.3 成果展示           PC端使用Filezilla做FTP客户端,W5500烧录代码后,使用Filezilla连接,地址为192.168.1.31,ID为DIgikey,密码为Followme4,端口不用选择,默认为21,连接成功,并能上传下载文件,上传过程截图如下: 图6-1 PC向W5500主控板传输图片(速度200K/s)            虽说无法使用LCD了,但是怎么能没有显示屏呢?所以还用了AtomS3做UDP服务器,将W5500主控板通过UDP发送来的内容进行显示,当作W5500的显示屏,展示如下: 图6-2 AtomS3做主控板的显示器(演示中,上传了两张图片,下载了文本)   七、心得体会         首先是学到了不少东西,接触了RP2040、W5500、ESP32,对Cmake、Ethernet、WIFI等都有了更深的理解,然后最大的感悟还是,没想到嵌入式开发还能如此简单,很多库都是别人写好的,而rp2040引脚又少,调用起来非常简单,觉得嵌入式就该往这个方向发展,更多耗费时间的还得是逻辑与算法。再者就是群里的大佬太多了,见识到了很多,自己仍需努力,向大佬看齐,最后当然是感谢得捷,感谢EEWORLD,谢谢你们提供了这个宝贵的机会,也希望今后多多出这些活动,也祝你们越来越好! 八、附件        这里就是内容三了,已将全部源码打包并上传至:https://download.eeworld.com.cn/detail/Alohaq/631392 ;如果你也安装了Pico-sdk,那么只需要添加到pcio的vscode环境里,即可编译下载全部内容。

  • 2024-01-25
  • 加入了学习《直播回放: FollowMe 3 与得捷一起解锁开发板的超能力》,观看 FollowMe 3 与得捷一起解锁开发板的超能力

最近访客

< 1/1 >

统计信息

已有5人来访过

  • 芯积分:45
  • 好友:--
  • 主题:2
  • 回复:1

留言

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


现在还没有留言