分类 无线电 下的文章

        其实开机黑屏,没有任何视频信号这个问题在这台机子装机时就出现过了。为了跑本地AI绘画脚本,买了一块M40 24G显卡的计算卡,装机时装上这块卡开机就会黑屏。经过反复折腾,需要进行如下处理:

  • 撬出主板电池,短接主板上BIOS放电插针25秒以上
  • 装回主板电池,开机,注意此时计算卡不能安装在插槽上
  • 进入BIOS设置,打开高级设置中的允许显卡4G以上的选项,保存退出
  • 断电,装上计算卡重新开机即可

        没有电台室,业余无线电台也就这么放在写字台上,紧邻我的台式电脑显示器和键盘。开通使用后,遇到了意想不到的射频干扰,只要电台发射,就会出现以下情况:

  • 显示器黑屏,电台结束发射时恢复,有时电台结束发射后也不能恢复,视频信号丢失
  • 键盘死机,不再有任何反应,或者电台发射时会在无操作的情况自行乱动作,包括且不限于打开计算器、给音频输出静音、打开Edge页面、打开搜索页面并自行填入一大串乱七八糟的字符等等
  • 鼠标死机,不再有任何反应
  • 有线网络中断,电台结束发射时恢复
  • 系统报警USB接口工作设备不正常

        经过搜索,采取了以下办法,仍未完全避免以上现象,会随机无规律出现以上情况:

  • 给所有的网线、USB设备线、HDMI线、电台直流电源线等两端加上磁环
  • 重新布线,电台天线电缆尽量远离USB线等
  • 电台和天调外壳与台机外壳连接(接地)

        经过各种对比测试,最终这样解决射频干扰问题:

  • 更换多重屏蔽双磁环HDMI线后,显示屏黑屏问题解决。
  • 更换一个老鼠标后,有线鼠标死机问题解决。
  • 无意中发现发射时显示器后的交换机电源灯暗淡闪烁、网口指示灯在发射时全部熄灭,在交换机的直流电源线上加上磁环后,发射时有线网络中断问题解决。
  • 机械键盘无论怎样在线上增加磁环都必死无疑,最后换了无线键盘鼠标解决。还有一个现象:当用显示器的USB接口连线给无线键盘充电时,电台发射时同样出现严重干扰现象,在供电的USB线两端增加磁环后解决。

        体会:

  • 业余电台发射时射频干扰太大,有条件时还是要有专门的电台室,做好机壳接地等工作。
  • 与业余电台连接的电脑用线缆要精挑细选,选用多重屏蔽抗干扰能力好的产品,你在普通场合能够正常用的线缆在这种场合不一定能胜任。
  • 以鼠标为例,电脑老产品用料比较足,新产品偷工减料的情况比较普遍,所以有时候不一定越新越好。
  • 现在大部分USB线缆等的屏蔽抗干扰能力都是很差的。上磁环可以补救一部分,但不要指望仅仅靠磁环就能解决所有问题。

微信图片_20240921134620.jpg

        八重洲FT-891是2018年买的,同年申请的短波电台执照,而真正把短波天线架设起来,开通短波电台是......上个星期。其间第一份短波电台执照过期,想续执照时被告知管理规定发生变化,100W短波业余无线电台设台许可权限由所在地无线电管理部门上收到工信部,去工信部申请时发现系统暂不可用,系统终于开放是接近2023年底,第一时间提交申请,新的工信部执照终于在2024年5月寄到手中。对于居住在多层居民小区的条件而言,八木正V什么的就不要想了,想尽办法动用无人机牵引等手段好不容易在两栋楼之间拉了一条端馈天线,然后第一时间就受到了小区物管和属地派出所的上门亲切关怀......证照齐全,没有问题放行,这才理解为什么有些HAM止步于UV段,明明有上短波的实力就是没有上短波的行动,这短波真不是想玩就能玩的......
        请教、摸索,终于把FT8用起来了。第一个QSL是夏威夷的HAM,15W跨越七千公里啊。终于,在经历了80年代末买到第一本讲业余无线电书籍的向往、1992年重新开放业余无线电台申请的激动、2017年取得A照和呼号、2018年取得B和短波电台执照......后,我的短波业余无线电台——BH8UMP终于设立起来了。

微信图片_20240910123134.jpg

        结合domoticz系统的构建,2018年在楼顶安装了家用气象站,气象站采用一套HAM友提供的套件,弃用其温度百叶箱(内含主控)及无线液晶屏等显示部件,保留套件中风向风速传感器及雨量传感器,增加一个百叶箱,用BM280测量温湿度与气压,用一块NODEMCU作为主控芯片,测量计算风向风速雨量等信息,通过2.4G无线局域网向Domoticz和OneNET发送数据。这一版气象站问题还是不少的,最大的问题是架设在屋顶,与家里路由器隔了一个带有屏蔽作用的钢筋混凝土的屋顶,WIFI连接十分不稳定,经常出现掉线的情况,想了很多办法,包括在阳台增设无线中继放大器等,始终无法彻底解决连接不稳定问题,曾经考虑过改用有线联网,但气象站的百叶箱太小,放不下ethernet模块和POE模块,加之感觉这套系统中风向风速等传感器的技术比较玩具,例如风向是八个干簧管,通过串接不同阻值电阻指示八个方向,无法准确测量风向,风速是风杯旋转时干簧管通断产生脉冲信号等,雨量传感器虽然采用的是翻斗式的设计,但其受雨口并未按照国标设计等,也就凑合用了下来。
微信图片_20240311084953.jpg

        最近这套系统彻底没数据了,断电重启也无效,这才下定决心进行换版重制。这次选用RS485接口的气象站组件,内置了温湿度气压,以及超声波风向风速传感器,还有一个光学雨量传感器。超声波测量风向风速似乎已经相对成熟,但采用光学方法测量雨量倒是没有想到,搜索了一番发现,似乎这也是一种得到承认的方法,那就试试吧。采用RS485组件的优点是一是数据读取方便,因其采用modbus协议,一个RS485设备可以集成多种传感器,只要发送指令读取每个传感器对应的寄存器数据即可,二是RS485传输距离长,一根RS485电缆从屋顶连下来,主控模块也可放在室内,防护更好,也方便后期调整升级固件。这次采用ethernet连接,不会再出现连接不稳定现象。
微信图片_20240311084931.jpg

        调试过程中的技术问题及解决要点如下:

  • Arduino的MODBUS RS485库有很多,作为主站控制的话,SensorModbusMaster是最好用的。虽然作者说这个库用于带自动收发的芯片,例如MAX13487的时候效果更好,但试验下来,如果只用9600这样波特率的话,MAX485芯片工作也完全正常。
  • RS485接口电路中AB之间的终端电阻是用于阻抗匹配的,用来减少反射,但是如果RS485接线本身不长的话,加上终端电阻反而是有害无益,调试时发现读取数据很不稳定,设置了8N1的串口协议有时候只能读出7bit数据,百思不得其解,去掉终端电阻就一切正常了。而且加上终端电阻后将大幅度拉低AB间电平,所以加不加,最好试验着看。
  • 有人串口ethernet模块如果出现发送的数据语法格式无误,但就是返回代码400的话,大概率是串口工作模式没有处在正确模式上,即发送数据时还处于命令模式,或发送命令模式时还处于数据透传模式,但是ethernet工作过程中可能会出现各种情况,编写程序时难以穷尽所有情况,所以一个讨巧的办法是在进入命令模式时先发送一遍进入数据透传模式,反之亦然,这样如果工作模式正确最多返回一条-1错误,不影响程序正常运行,但如果工作模式不正确,则正好可以纠正到程序设计模式上来,后续工作就一切正常了。

        domoticz总的来说是算稳定的开源系统,但自己增加功能势必遇到各种稀奇古怪的问题,domoticz中文区半死不活,domoticz.com访问又被拒绝,解决问题还是颇费时间。当然有些问题属于自己对raspbian还没有烂熟于心的缘故,raspberry pi遇到问题搜索大法不一定管用,国内搜索质量良莠不齐,很多解答随着软件版本的更新已失效,最高效的方式还是把问题转换为英文,在google上搜索往往第一页还没有翻完就找到答案。以下是一些记录备忘,此文将不定时更新。

  • raspberry pi的定时任务设置问题。经常遇到定时任务设置了但是没有起作用的情况,而且好像crontab在不同位置有不同文件,有的配置文件还与用户账号有关。试验下来,用这个命令没问题: crontab -e ,要想更保险一点,执行的脚本用绝对路径。修改完了后不要忘记sudo service cron restart重启服务。
  • domoticz的开关等可以设置开或关时触发动作,但语句开头必须是http://或https://或script://,执行脚本时语句格式是:

    scripts:///home/xx/xxx.../xxx.py
    scripts:///home/xx/xxx.../xxx.sh
    scripts:///home/xx/xxx.../xxx.lua

    等等,如果设置了执行脚本但是没有起作用,大概率是被执行脚本没有打开执行权限,脚本执行后日志中返回错误码32256或512都是这个问题,进入脚本目录执行sudo chmod +x XXX.pysudo chmod 755 XXX.py即可,如果还不行就写个sh脚本,把执行命令等写进去,设为执行这个sh脚本就可以,貌似用这个方法被执行脚本打开不打开执行权限都没有关系。

  • domoticz.com屏蔽国内IP后,官网论坛可以访问https://en.domoticz.cn/forum/,官网WIKI可以访问https://en.domoticz.cn/wiki/Main_Page。貌似国内的镜像站?

        往微信推送信息,Server酱是最方便的办法。注册,获得一个KEY,再在微信上弄个企业微信的链接,就可以通过post https://sctapi.ftqq.com/.send?title=short_title&desp=long_content来推送信息,SENDKEY是你的发送密码,title后面是推送标题,desp后面是推送内容,内容用markdown语法,可以是文字、图片、链接或者几者的混排,但它用的好像是commonmark.org的语法,有些通用写法它不一定认。你用什么语言POST都可以,当然用python是最方便。

        于是我:

用它来推中央气象台的各种气象图微信图片_20240304114327.jpg

用它来推定制的天气预报微信图片_20240304114336.jpg

用它来推domoticz的实时数据微信图片_20240304114318.jpg

用它来推前一晚流星监测站的监测结果微信图片_20240304114355.jpg

        总之想推什么推什么,用python写个简单的脚本抓取想要推送的信息,然后通过Server酱推送就好。把脚本丢到树莓派上,设个定时任务,就可以定时推送啦。

        Domoticz控制开关用ESP-01S是最方便的办法。ESP-01S烧录ESPEasy固件后,可以不用编程,仅仅经过简单设置就可以在Domoticz中使用。之前在淘宝买过ESP01继电器板,用来控制灯光等需要外接电源模块,颇为不便,最近看到https://www.instructables.com/Home-Automation-Using-ESP01/上的印刷电路板,设计科学,将电源模块也集成在电路板上,外接电器十分方便,下载印刷电路板图制作后,试验成功。有几年没有烧录ESPEasy了,一些步骤不太记得,费了一些功夫,把流程记录如下,以后再用也方便些。

  • 先下载ESPEasy固件和烧录器,最新版在https://github.com/letscontrolit/ESPEasy/releases,其中也有历史固件。不一定要下载最新版,要选择下载ESP8266系列的固件。
  • 将ESP-01S插在编程器上,烧录ESPEasy固件,注意要选择1M那个版本的固件,不能用4M1M版本的。
  • 烧录完毕后按编程器上的复位按钮,稍后在wifi列表中连接新出现的ESP_0的SSID,连接密码是configesp。
  • 浏览器会自动弹出配网窗口,如果没有弹出,在浏览器中输入192.168.4.1,进入配网界面,选择ESP-01S需要连接的网络SSID,输入密码保存。模块配网后会重启,显示模块的IP地址。如果没有显示,切换网络到局域网上,在局域网内寻找新联网设备,记录IP地址。
  • 在浏览器中进入模块IP地址,进行配置。模块配置可以看https://blog.csdn.net/lionwerson/article/details/104417481,其实最好是对比之前已经做好的配置进行配置。

        几点Tips:

  • 不同的继电器板有不同的控制逻辑,比如原来在淘宝上买的继电器板是低电平导通,网上这个继电器板电路则是高电平导通,如要上电即导通,则设置中“Hardware”中GPIO-0模式要设置为Output Low。
  • Domoticz增加新的开关要到设置-硬件中找到之前设置的Dummy,点“创建虚拟传感器”,选择传感器类型为开关,输入一个名字,在开关页面就可以看到新建的开关。
  • ESP-01S与ESP-01的区别是前者的IO口已经内置上拉电阻,不需要在电路板上再行设置,所以尽量选择ESP-01S。这个网站也讲了两者区别和ESPEasy的配置过程https://sancla.com/domoticz/esp8266-with-esp-easy/
  • 不同版本的easyesp烧录器各有不同,较新版本固件的烧录器除了要选择固件版本,还要选择烧录起始地址,地址选0x00000000即可。

微信图片_20240303230103.jpg

        esp32系列是高性价比物联网节点设备的代表,速度够快,自带WIFI又可以使用Arduino IDE编程,最近试用了一种带有OV2640摄像头的ESP32-CAM只要很简单地设置就可以做很多种工作,以下是试验记录。

        Arduino IDE要在首选项中在其他开发板管理器地址中填入https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json,再去开发板管理器界面中找到ESP32,点击安装后才能使用ESP32系列单片机。注意要联网才能安装。

  • 用作延时相机

    #include "esp_camera.h"
    #include "FS.h"                // SD Card ESP32
    #include "SD_MMC.h"            // SD Card ESP32
    #include "soc/soc.h"           // Disable brownout problems
    #include "soc/rtc_cntl_reg.h"  // Disable brownout problems
    #include "driver/rtc_io.h"
    #include <WiFi.h>
    #include "time.h"
    
    
    // REPLACE WITH YOUR NETWORK CREDENTIALS
    const char* ssid = "XXXXXX";
    const char* password = "XXXXXX";
    
    
    // REPLACE WITH YOUR TIMEZONE STRING: https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv
    String myTimezone ="CST-8";
    
    
    // Pin definition for CAMERA_MODEL_AI_THINKER
    // Change pin definition if you're using another ESP32 camera module
    #define PWDN_GPIO_NUM     32
    #define RESET_GPIO_NUM    -1
    #define XCLK_GPIO_NUM      0
    #define SIOD_GPIO_NUM     26
    #define SIOC_GPIO_NUM     27
    #define Y9_GPIO_NUM       35
    #define Y8_GPIO_NUM       34
    #define Y7_GPIO_NUM       39
    #define Y6_GPIO_NUM       36
    #define Y5_GPIO_NUM       21
    #define Y4_GPIO_NUM       19
    #define Y3_GPIO_NUM       18
    #define Y2_GPIO_NUM        5
    #define VSYNC_GPIO_NUM    25
    #define HREF_GPIO_NUM     23
    #define PCLK_GPIO_NUM     22
    
    
    // Stores the camera configuration parameters
    camera_config_t config;
    
    
    // Initializes the camera
    void configInitCamera(){
    config.ledc_channel = LEDC_CHANNEL_0;
    config.ledc_timer = LEDC_TIMER_0;
    config.pin_d0 = Y2_GPIO_NUM;
    config.pin_d1 = Y3_GPIO_NUM;
    config.pin_d2 = Y4_GPIO_NUM;
    config.pin_d3 = Y5_GPIO_NUM;
    config.pin_d4 = Y6_GPIO_NUM;
    config.pin_d5 = Y7_GPIO_NUM;
    config.pin_d6 = Y8_GPIO_NUM;
    config.pin_d7 = Y9_GPIO_NUM;
    config.pin_xclk = XCLK_GPIO_NUM;
    config.pin_pclk = PCLK_GPIO_NUM;
    config.pin_vsync = VSYNC_GPIO_NUM;
    config.pin_href = HREF_GPIO_NUM;
    config.pin_sscb_sda = SIOD_GPIO_NUM;
    config.pin_sscb_scl = SIOC_GPIO_NUM;
    config.pin_pwdn = PWDN_GPIO_NUM;
    config.pin_reset = RESET_GPIO_NUM;
    config.xclk_freq_hz = 20000000;
    config.pixel_format = PIXFORMAT_JPEG; //YUV422,GRAYSCALE,RGB565,JPEG
    config.grab_mode = CAMERA_GRAB_LATEST;
    
    
    // Select lower framesize if the camera doesn't support PSRAM
    if(psramFound()){
      config.frame_size = FRAMESIZE_UXGA; // FRAMESIZE_ + QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA
      config.jpeg_quality = 5; //0-63 lower number means higher quality
      config.fb_count = 1;
    } else {
      config.frame_size = FRAMESIZE_UXGA;
      config.jpeg_quality = 5;
      config.fb_count = 1;
    }
    
    // Initialize the Camera
    esp_err_t err = esp_camera_init(&config);
    if (err != ESP_OK) {
      Serial.printf("Camera init failed with error 0x%x", err);
      return;
    }
    }
    
    
    // Connect to wifi
    void  initWiFi(){
    WiFi.begin(ssid, password);
    Serial.println("Connecting Wifi");
    while (WiFi.status() != WL_CONNECTED) {
      Serial.print(".");
      delay(500);
    }
    }
    
    
    // Function to set timezone
    void setTimezone(String timezone){
    Serial.printf("  Setting Timezone to %s\n",timezone.c_str());
    setenv("TZ",timezone.c_str(),1);  //  Now adjust the TZ.  Clock settings are adjusted to show the new local time
    tzset();
    }
    
    
    // Connect to NTP server and adjust timezone
    void initTime(String timezone){
    struct tm timeinfo;
    Serial.println("Setting up time");
    configTime(0, 0, "pool.ntp.org");    // First connect to NTP server, with 0 TZ offset
    if(!getLocalTime(&timeinfo)){
      Serial.println(" Failed to obtain time");
      return;
    }
    Serial.println("Got the time from NTP");
    // Now we can set the real timezone
    setTimezone(timezone);
    }
    
    
    // Get the picture filename based on the current ime
    String getPictureFilename(){
    struct tm timeinfo;
    if(!getLocalTime(&timeinfo)){
      Serial.println("Failed to obtain time");
      return "";
    }
    char timeString[20];
    strftime(timeString, sizeof(timeString), "%Y-%m-%d_%H-%M-%S", &timeinfo);
    Serial.println(timeString);
    String filename = "/picture_" + String(timeString) +".jpg";
    return filename; 
    }
    
    
    // Initialize the micro SD card
    void initMicroSDCard(){
    // Start Micro SD card
    Serial.println("Starting SD Card");
    if(!SD_MMC.begin()){
      Serial.println("SD Card Mount Failed");
      return;
    }
    uint8_t cardType = SD_MMC.cardType();
    if(cardType == CARD_NONE){
      Serial.println("No SD Card attached");
      return;
    }
    }
    
    
    // Take photo and save to microSD card
    void takeSavePhoto(){
    // Take Picture with Camera
    camera_fb_t * fb = esp_camera_fb_get();
    
    //Uncomment the following lines if you're getting old pictures
    //esp_camera_fb_return(fb); // dispose the buffered image
    //fb = NULL; // reset to capture errors
    //fb = esp_camera_fb_get();
    
    if(!fb) {
      Serial.println("Camera capture failed");
      delay(1000);
      ESP.restart();
    }
    
    
    // Path where new picture will be saved in SD Card
    String path = getPictureFilename();
    Serial.printf("Picture file name: %s\n", path.c_str());
    
    // Save picture to microSD card
    fs::FS &fs = SD_MMC; 
    File file = fs.open(path.c_str(),FILE_WRITE);
    if(!file){
      Serial.printf("Failed to open file in writing mode");
    } 
    else {
      file.write(fb->buf, fb->len); // payload (image), payload length
      Serial.printf("Saved: %s\n", path.c_str());
    }
    file.close();
    esp_camera_fb_return(fb); 
    }
    
    
    void setup() {
    WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); // disable brownout detector
    
    
    Serial.begin(115200);
    delay(2000);
    
    
    // Initialize Wi-Fi
    initWiFi();
    // Initialize time with timezone
    initTime(myTimezone);    
    // Initialize the camera  
    Serial.print("Initializing the camera module...");
    configInitCamera();
    Serial.println("Ok!");
    // Initialize MicroSD
    Serial.print("Initializing the MicroSD card module... ");
    initMicroSDCard();
    }
    
    
    void loop() {    
    // Take and Save Photo
    takeSavePhoto();
    delay(60000);
    }

            在程序中修改SSID、PASSWORD,myTimezone设置时区字符串,在https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv中查找到属于当地的时区字符串;config.frame_size设置拍摄分辨率,config.jpeg_quality设置图像质量,0~63,数字越小图像质量越高,但有可能造成图像拍摄出现问题。loop()中delay()函数内是延时时间。
            图像质量实在差劲,最高分辨率UXGA下图像质量设置为0时所拍照片偶有撕裂现象,我一般设置为5。模块上电后按一下reset键,可以确保系统正常工作。

  • 用作网络摄影机

    #include "esp_camera.h"
    #include <WiFi.h>
    
    //
    // WARNING!!! PSRAM IC required for UXGA resolution and high JPEG quality
    //            Ensure ESP32 Wrover Module or other board with PSRAM is selected
    //            Partial images will be transmitted if image exceeds buffer size
    //
    //            You must select partition scheme from the board menu that has at least 3MB APP space.
    //            Face Recognition is DISABLED for ESP32 and ESP32-S2, because it takes up from 15 
    //            seconds to process single frame. Face Detection is ENABLED if PSRAM is enabled as well
    
    // ===================
    // Select camera model
    // ===================
    //#define CAMERA_MODEL_WROVER_KIT // Has PSRAM
    //#define CAMERA_MODEL_ESP_EYE // Has PSRAM
    //#define CAMERA_MODEL_ESP32S3_EYE // Has PSRAM
    //#define CAMERA_MODEL_M5STACK_PSRAM // Has PSRAM
    //#define CAMERA_MODEL_M5STACK_V2_PSRAM // M5Camera version B Has PSRAM
    //#define CAMERA_MODEL_M5STACK_WIDE // Has PSRAM
    //#define CAMERA_MODEL_M5STACK_ESP32CAM // No PSRAM
    //#define CAMERA_MODEL_M5STACK_UNITCAM // No PSRAM
    #define CAMERA_MODEL_AI_THINKER // Has PSRAM
    //#define CAMERA_MODEL_TTGO_T_JOURNAL // No PSRAM
    //#define CAMERA_MODEL_XIAO_ESP32S3 // Has PSRAM
    // ** Espressif Internal Boards **
    //#define CAMERA_MODEL_ESP32_CAM_BOARD
    //#define CAMERA_MODEL_ESP32S2_CAM_BOARD
    //#define CAMERA_MODEL_ESP32S3_CAM_LCD
    //#define CAMERA_MODEL_DFRobot_FireBeetle2_ESP32S3 // Has PSRAM
    //#define CAMERA_MODEL_DFRobot_Romeo_ESP32S3 // Has PSRAM
    #include "camera_pins.h"
    
    // ===========================
    // Enter your WiFi credentials
    // ===========================
    const char* ssid = "XXXXXX";
    const char* password = "XXXXXX";
    
    void startCameraServer();
    void setupLedFlash(int pin);
    
    void setup() {
    Serial.begin(115200);
    Serial.setDebugOutput(true);
    Serial.println();
    
    camera_config_t config;
    config.ledc_channel = LEDC_CHANNEL_0;
    config.ledc_timer = LEDC_TIMER_0;
    config.pin_d0 = Y2_GPIO_NUM;
    config.pin_d1 = Y3_GPIO_NUM;
    config.pin_d2 = Y4_GPIO_NUM;
    config.pin_d3 = Y5_GPIO_NUM;
    config.pin_d4 = Y6_GPIO_NUM;
    config.pin_d5 = Y7_GPIO_NUM;
    config.pin_d6 = Y8_GPIO_NUM;
    config.pin_d7 = Y9_GPIO_NUM;
    config.pin_xclk = XCLK_GPIO_NUM;
    config.pin_pclk = PCLK_GPIO_NUM;
    config.pin_vsync = VSYNC_GPIO_NUM;
    config.pin_href = HREF_GPIO_NUM;
    config.pin_sccb_sda = SIOD_GPIO_NUM;
    config.pin_sccb_scl = SIOC_GPIO_NUM;
    config.pin_pwdn = PWDN_GPIO_NUM;
    config.pin_reset = RESET_GPIO_NUM;
    config.xclk_freq_hz = 20000000;
    config.frame_size = FRAMESIZE_UXGA;
    config.pixel_format = PIXFORMAT_JPEG; // for streaming
    //config.pixel_format = PIXFORMAT_RGB565; // for face detection/recognition
    config.grab_mode = CAMERA_GRAB_WHEN_EMPTY;
    config.fb_location = CAMERA_FB_IN_PSRAM;
    config.jpeg_quality = 5;
    config.fb_count = 1;
    
    // if PSRAM IC present, init with UXGA resolution and higher JPEG quality
    //                      for larger pre-allocated frame buffer.
    if(config.pixel_format == PIXFORMAT_JPEG){
      if(psramFound()){
        config.jpeg_quality = 5;
        config.fb_count = 2;
        config.grab_mode = CAMERA_GRAB_LATEST;
      } else {
        // Limit the frame size when PSRAM is not available
        config.frame_size = FRAMESIZE_SVGA;
        config.fb_location = CAMERA_FB_IN_DRAM;
      }
    } else {
      // Best option for face detection/recognition
      config.frame_size = FRAMESIZE_240X240;
    #if CONFIG_IDF_TARGET_ESP32S3
      config.fb_count = 2;
    #endif
    }
    
    #if defined(CAMERA_MODEL_ESP_EYE)
    pinMode(13, INPUT_PULLUP);
    pinMode(14, INPUT_PULLUP);
    #endif
    
    // camera init
    esp_err_t err = esp_camera_init(&config);
    if (err != ESP_OK) {
      Serial.printf("Camera init failed with error 0x%x", err);
      return;
    }
    
    sensor_t * s = esp_camera_sensor_get();
    // initial sensors are flipped vertically and colors are a bit saturated
    if (s->id.PID == OV3660_PID) {
      s->set_vflip(s, 1); // flip it back
      s->set_brightness(s, 1); // up the brightness just a bit
      s->set_saturation(s, -2); // lower the saturation
    }
    // drop down frame size for higher initial frame rate
    if(config.pixel_format == PIXFORMAT_JPEG){
      s->set_framesize(s, FRAMESIZE_QVGA);
    }
    
    #if defined(CAMERA_MODEL_M5STACK_WIDE) || defined(CAMERA_MODEL_M5STACK_ESP32CAM)
    s->set_vflip(s, 1);
    s->set_hmirror(s, 1);
    #endif
    
    #if defined(CAMERA_MODEL_ESP32S3_EYE)
    s->set_vflip(s, 1);
    #endif
    
    // Setup LED FLash if LED pin is defined in camera_pins.h
    #if defined(LED_GPIO_NUM)
    setupLedFlash(LED_GPIO_NUM);
    #endif
    
    WiFi.begin(ssid, password);
    WiFi.setSleep(false);
    
    while (WiFi.status() != WL_CONNECTED) {
      delay(500);
      Serial.print(".");
    }
    Serial.println("");
    Serial.println("WiFi connected");
    
    startCameraServer();
    
    Serial.print("Camera Ready! Use 'http://");
    Serial.print(WiFi.localIP());
    Serial.println("' to connect");
    }
    
    void loop() {
    // Do nothing. Everything is done in another task by the web server
    delay(10000);
    }

            在程序中修改SSID、PASSWORD,上传后打开串口监视器,按rst键,看模块IP地址,在浏览器中输入IP地址就进入网络摄像头界面,点Start Stream开始摄像头网络直播。各种参数可以在浏览器界面进行设置。
    esp32-cam.png

  • 人脸检测和人脸识别

            上面网络摄像头界面左边栏有人脸检测和人脸识别功能,把分辨率调整到320*240时可以开启,此时可以自动识别画面中出现的人脸,还可点击enroll face键预存需要识别的人脸。

        本记录将持续更新。