esp32 spi 驱动 oled 屏显示来自 PC 的画面

esp32 spi 驱动 oled 屏显示来自 PC 的画面

实验代码

gayhub 实验源码

设备及运行环境

  1. 装有python的电脑
Python 3.8.2 (tags/v3.8.2:7b3ab59, Feb 25 2020, 23:03:10) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
  1. esp32开发板(ttgo-t-display)
  2. 0.96 OLED(80 * 160 ST7735S)

流程

  • PC端
    1. py截屏
    2. py缩小图片
    3. py将缩小的图由rgb转成 rgb565
    4. 将图片转码完成后以字节流的方式存入临时bin文件
    5. 读取bin文件,通过socket发送
    6. 因为需要转码、转存文件,测试之后大概是一秒四帧。(这个时候socket缓冲默认,后来缓存调整得很大,发送帧率上去了,但是数据还是堵在服务端没发送出去。。。)
  • esp32
    1. 连接 wifi 的同时设置好端口(跟PC端设置的socket端口一样,我只是使用了 arduino中的WIFI库, 可以使用socket方式接收数据也是偶然发现的,~~后续有新的发现会做记录(谁知道我还会不会想起来嘿嘿)~)
    2. 设置 oled 屏 io 口,使用SPI驱动oled屏(这里有一些不理解。。。 查看 ttgo 的 io 说明,发现上面标注我所使用到的 io 口都是gpio,并不是被标注为 SPI。所以有可能是gpio模拟的 spi???~~后续有新的发现会做记录 嘿嘿~)

使用的库

  • TFT_eSPI
  • arduino 的 wifi 库(不确定是arduino的通用库,还是esp32的专属库。。。。。)

OLED 配置方式

  • 软件配置
    1. 修改配置文件。修改 TFT_eSPI 根目录里面的 User_Setup_Select.h, 将#include // Setup file configured for my ST7735S 80x160的注释删掉,然后将其它不需要用到的配置头文件注释掉

    2. 修改 io 口。 修改 TFT_eSPI/User_Setups/Setup43_ST7735.h 的文件, 修改 io 口(这里直接就是对应开发板上面标注的 io, 这里直接没有设置背光 )

    #define TFT_MOSI            26 // 对应 oled板的 sda
    #define TFT_SCLK            27 // 对应 oled板的 scl
    #define TFT_CS              32 // 对应 oled板的 cs
    #define TFT_DC              33 // 对应 oled板的 dc
    #define TFT_RST             25 // 对应 oled板的 res
    #define TFT_BL          0  // Display backlight control pin
    
    1. 设置 wifi 得 client
    const IPAddress serverIP(192,168,0,104); //欲访问的地址
    uint16_t serverPort = 8080;         //服务器端口号
    

运行时发现的问题

  • 问题: 帧率低(一秒一帧。。。)。
    • 实际测试来看,屏可以实现更高帧率,问题有可能是出现在了数据接收这一块,因为没有找到arduino 的 wifi库里面 client类设置缓冲大小的方法,所以缓冲是没有设置的。
  • 问题: 内存告急
    • 为了解决无法设置缓冲大小的问题,尝试使用多个数组来实现队列,用队列缓存数据,实现先进先出,但是创建两个数组后,内存就告急了。。。(一个数组长度 12800。。。我可能是个憨憨。。。),目前是不了了之。。。
  • 问题: 设置发送端的 socket缓冲区大小为 0 可以有效提高帧率
    • 当调大发送端的 socket缓冲区,发送速率翻倍增长, 但是接收端的显示帧率反倒是因此变得更加低了。发送端缓冲设置为0 确实可以让帧率提升,而后果就是丢帧严重。。。。。。。。

部分代码

  • 发送端的 rgb888 转 rgb565 (起初没有发现驱动需要的色彩数据是rgb565,费了很多功夫重新阅读了驱动部分的代码,总算懵懵懂懂搞完了)
# png 转 rgb565
def png2rgb565(im):

    binoutfile = open("binData.bin", "wb")
    swapLast = ''
    pix = im.load()  #load pixel array
    for h in range(imgH):
        for w in range(imgW):
            if w < im.size[0]:
                R=pix[w,h][0]>>3
                G=pix[w,h][1]>>2
                B=pix[w,h][2]>>3
                rgb = (R<<11) | (G<<5) | B
                if (isSWAP == True):
                    swap_string_low = rgb >> 8
                    swap_string_high = (rgb & 0x00FF) << 8
                    swap_string = swap_string_low | swap_string_high
                    binoutfile.write(struct.pack('H', swap_string))
                else:
                    print(".")
            else:
                rgb = 0
    binoutfile.close()
  • esp32 接收部分的代码
while (client.connected() || client.available()) //如果已连接或有收到的未读取的数据
{
    if (client.available()) //如果有数据可读取
    {
        // binData1 = client.read();
        if(flag % 2 == 0)
        {
            /*
            读取一个像素的色彩数据的第二字节, 这里只能一次读取一个字节, 
            而从服务端发送的数据是用一个16位数字表示1像素点的 rgb色彩的,
            所以就需要读两次才可以获取一个完成像素色彩
            */
            binData1 = client.read(); 
            binData1 = binData1 << 8; // 左移八位
            result = binData0 | binData1; // 数据还原
            ttgo[index] = (uint16_t)result; // 数据存入缓存数组
            
            index++;
            if(index == 12800) // 读取完一帧就显示
            {
                index = 0;
                tft.pushImage(0, 0,  sh, sw, ttgo);
            }
        }else
        {
            binData0 = client.read(); // 读取一个像素的色彩数据的第一字节
        }
        flag++;
    }else // else 啥我也想不到,反正是拿来测试的
    {
//                Serial.print("\n");
    }
    
}
这次的小实验完成后感慨太多了, 因为完成的东西也是个半成品,跟预期的样子还差了很远(毕竟现在一秒一帧。。。)。不过本着一帧不卡,两帧流畅,三帧电竞的乐观精神来说,这次也不算是完败,起码我还走到了写实验总结这一步。hhhhh。接下来是回归基础学习了,毕竟在学校学的那点c语言都忘得差不多了。
学习计划 1. 重新学习c/c++ 2. 开始学习 stm32
目标 从硬件到软件,做一个穿戴设备

你可能感兴趣的:(esp32)