237浏览
查看: 237|回复: 1

[项目] 一双跟随你转动的大眼睛

[复制链接]
本帖最后由 小虾米小 于 2025-11-19 22:24 编辑

先看效果:一双跟随你转动的大眼睛图1
在你的桌面上,有一双眼睛一直灵活的在跟着你动,是不是很有感觉?如果你说话的时候,他也在看着你,并且还时不时的眨眨眼,就更加的活灵活现了。
我用矩阵激光传感器捣腾了这样一个应用。
开干!

硬件准备
Firebeetle ESP32-C5,货号:DFR1236,产品链接:https://www.dfrobot.com.cn/goods-4196.html
一双跟随你转动的大眼睛图26
3.5英寸IPS触摸显示屏,货号:DFR1092,产品链接:https://www.dfrobot.com.cn/goods-4264.html
一双跟随你转动的大眼睛图2
矩阵激光测距传感器,货号:SEN0628,产品链接:https://www.dfrobot.com.cn/goods-4243.html
一双跟随你转动的大眼睛图3
硬件连接
ESP32-C5与3.5屏幕之间使用显示屏配送的FPC线进行连接。
矩阵激光传感器使用PH2.0-4P线连接到ESP32-C5扩展板的I2C接口。
如下图所示:
一双跟随你转动的大眼睛图4

将矩阵激光传感器的拨码开关拨到如图所示的位置,设置模式为I2C模式,地址为0x33。
一双跟随你转动的大眼睛图5
将矩阵激光传感器用双面胶粘贴在显示屏上方,注意,由于显示屏上方有排针孔,不要短路了。也可以粘贴到其它合适的地方。
一双跟随你转动的大眼睛图6
下载及安装库
使用Arduino进行开发,相关配置如下:
打开Arduino平台,首先安装库矩阵激光Arduino库:DFRobot_matrixLidarDistanceSensor
链接:https://github.com/DFRobot/DFRobot_matrixLidarDistanceSensor.git

一双跟随你转动的大眼睛图7

在Arduino平台上打开工具-导入库-添加.zip库,选择刚刚重命名的zip库,确定进行添加。
在Arduino平台上打开文件-示例-DFRobot_matrixLidarDistanceSensor,你能看到它就代表你已成功导入。

一双跟随你转动的大眼睛图8

接下来,下载并安装DFRobot_GDL库,方法同矩阵激光传感器库相似。库链接:https://gitee.com/dfrobot/DFRobot_GDL

安装ESP32 SDK
安装教程请见链接:https://wiki.dfrobot.com.cn/Add_ESP32_board_to_Arduino_IDE

选择板卡
SDK安装完成后,按如图所示选择板卡为“ESP32C5 Dev Module” 。

一双跟随你转动的大眼睛图9

修改显示屏SPI引脚映射
在ESP32-C5上使用FPC线连接显示屏时,需修改显示屏的引脚映射,修改方式如下:
在电脑的如下目录,打开“pins_arduino.h”文件:C:\Users\Administrator\AppData\Local\Arduino15\packages\esp32\hardware\esp32\3.3.4-cn\variants\esp32c5

一双跟随你转动的大眼睛图10
修改引脚映射表:

引脚名称
对应引脚
备注
SCLK
23

MOSI
24

MISO
25

SDA
9

SCL
10


具体修改位置如图:

一双跟随你转动的大眼睛图11

下载代码及素材文件
下载地址:下载附件眼睛跟随人动源码及素材.rar

程序下载
程序功能
  • 当检测距离小于30 mm时,人物处于闭眼状态。
  • 当检测距离在30-1500 mm时,人物眼睛处于跟踪状态。
  • 当检测距离大于1500mm时,人物处于眨眼状态。
程序编译及下载
打开附件中的ino代码,并编译下载。
一双跟随你转动的大眼睛图13
最终完成效果见帖子最上方。


实现原理
矩阵激光传感器WIKI链接:https://wiki.dfrobot.com.cn/SKU_SEN0628_%E7%9F%A9%E9%98%B5%E6%BF%80%E5%85%89%E6%B5%8B%E8%B7%9D%E4%BC%A0%E6%84%9F%E5%99%A8

通过WIKI我们发现,矩阵激光会打出8*8共64个测距点,这就意味着不仅可以检测障碍物的距离,还能检测障碍物的位置。这是实现移动检测的主要原理。如图:
一双跟随你转动的大眼睛图14

在显示部分,原理如下:
先用AI生成一张人脸图。
正脸就像是一张最底部照片的画布,当程序处于眨眼状态时,眉毛和眼睛都会持续的跟新局部像素进行刷新,持续在最底部的画布上进行绘制眉毛和眼睛的绘制,以实现眨眼动画的刷新
眼睛的绘制主要我是通过在眼白画布上持续的刷和写,这样其他地方的图片像素不需要改变,只需要让眼睛眼白中进行刷写就能够实现眼睛的眼睛眼白中运动,在眼白中建立坐标系,这样我们就只需要知道每一帧眼睛的坐标即可。

一双跟随你转动的大眼睛图15

眼睛在眼白中圆滑运动实现原理,当坐标出现变化时,当前眼睛坐标(x1,y1),离目标眼睛(x2,y2)的差值|(x2-x1,y2-y1)|越大时,眼珠变化的速度就越快,反之越小,这样实现了平滑运动,如下图所示:

一双跟随你转动的大眼睛图16
实现步骤
图片帧素材准备
在这个项目时,首先要准备除了需要用到的试验耗材外,还需准备图片素材。这个图片素材需要使用视频素材转化而来。
如果你没有直接使用适合的素材,可使用AI生成一张合适的人物正脸图片,有了这张图片过后,使用这个链接AI生****物闭上眼睛的动态视频: https://app.klingai.com/global/video-extend/new.
拥有视频过后,你就可以通过(剪映、pr工具)提取出该人物的动态连续帧,如下:

一双跟随你转动的大眼睛图17

图片处理
选出几个图片关键帧,并对关键部位(如眼球、眉毛、眼框)进行裁剪和提取,我这里选了四张关键帧进行处理,如下:

一双跟随你转动的大眼睛图18一双跟随你转动的大眼睛图19一双跟随你转动的大眼睛图20

注意:1.在进行图片裁剪时,我们需要注意记录(眼球、眼眶、眉毛)的照片的像素大小要一致。因为这些地方在程序进行动态改变时,需要保证像素不变,否则会造成像素撕裂。
在进行裁剪时,需要记住每张裁剪的坐标,这个坐标都是裁剪坐标左上角,可使用光标进行标注进行X-Y轴坐标的查看,这些坐标需要保留到程序中使用。

一双跟随你转动的大眼睛图21
需要保留大小和坐标清单如下(除眼球中点坐标除外):

一双跟随你转动的大眼睛图22

图片转化
接下来就是将png图片转化为RGB565,这一步需要使用到转换工具。
可以使用bilbil 博主(爆辣小电匞)的工具教程,链接如下:https://www.bilibili.com/video/BV1oe411176s/?vd_source=e791586b6b2a1e5dc8602bdf57db8b18
将上面处理的这些图片一并进行转换,结果在素材的像素文件里,如下:
一双跟随你转动的大眼睛图23

在代码中我合并成了一个figure.h文件,这里的figure.h文件是figure.png转化而来
注意:1.在前面的实现原理中,我们提到了眼白画布,既然它是画布,它其中的数据就是可变的,在进figure.h进行合并时,需要将左右眼白的画布定义为二维数组,并且不能使用PROGMEM和const进行声明。其它的都可以使用const和PROGMEM进行声明,这样可以将大量的数据存放在flash中,减少RAM的负担,我使用的ESP32 C5,如果全部放在RAM中,编译时会报错(内存不足)。

一双跟随你转动的大眼睛图24

程序说明
这一部分是眼睛裁剪大小和坐标的关键参数(如果你要改动素材,就需要改动这里)
一双跟随你转动的大眼睛图25

函数说明
这个程序实现了一个基于3.5英寸屏幕和激光矩阵距离传感器的交互式眼睛显示系统。主要功能是通过激光传感器检测用户位置,控制屏幕上的一对虚拟眼睛进行实时跟踪和表情变化:当检测到用户靠近时,眼睛会注视用户;用户远离时眨眼;用户离的太近时闭眼;还能实现平滑的眼球移动和自然的眨眼动画效果;创造出生动的人机交互体验。
  1. #include "Arduino.h"
  2. #include "DFRobot_GDL.h"
  3. #include "DFRobot_MatrixLidar.h"
  4. #include "figure.h"
  5. #define TFT_DC    8   
  6. #define TFT_CS    27      
  7. #define TFT_RST   26     
  8. #define TFT_BL    15   
  9. #define MIN(a, b) ((a) < (b) ? (a) : (b))
  10. #define MAX(a, b) ((a) > (b) ? (a) : (b))
  11. DFRobot_ST7365P_320x480_HW_SPI display(/*dc=*/TFT_DC,/*cs=*/TFT_CS,/*rst=*/TFT_RST,/*bl=*/TFT_BL);
  12. DFRobot_MatrixLidar_I2C tof(0x33);
  13. #define EYE_SOCKET_WIDE 49               
  14. #define EYE_SOCKET_LONG 43
  15. #define EYE_MID_POS_X   24               //眼睛中点在画布上的坐标
  16. #define EYE_MID_POS_Y   21
  17. #define LEFT_EYE_COORDINATE_X 81
  18. #define LEFT_EYE_COORDINATE_Y 188
  19. #define RIGHT_EYE_COORDINATE_X 194
  20. #define RIGHT_EYE_COORDINATE_Y 188
  21. const uint8_t eyebrowWide = 185,eyebrowLong = 21;
  22. const uint8_t eyebrowX = 72,eyebrowY = 152;
  23. const uint8_t eyeWide1 = 54,eyeLong1 = 54;
  24. const uint8_t eyeLeftX = 77,eyeLeftY = 180;
  25. const uint8_t eyeRight_x = 192,eyeRight_y = 180;
  26. //眼睛状态
  27. uint8_t eyeStates = 4;//0---睁眼状态 1---闭眼状态 2---眨眼过程中
  28. int eyeWide = 27;//眼睛照片的大小
  29. int eyeLong = 35;
  30. int baseEye_x  = EYE_MID_POS_X;
  31. int baseEye_y = EYE_MID_POS_Y;
  32. uint8_t oldEye_l[35][27] = {0};
  33. uint8_t oldEye_r[35][27] = {0};
  34. uint8_t first_erasure = 0;
  35. int baseMoveEyeLeft_x  = 28;//左眼睛中点在画布上的坐标
  36. int baseMoveEyeLeft_y = 22;
  37. int baseMoveEyeRight_x  = 19;//右眼睛中点在画布上的坐标
  38. int baseMoveEyeRight_y = 22;
  39. uint64_t newTime;
  40. uint64_t oldTime;
  41. // 坐标范围
  42. const uint8_t X_MIN = 5;
  43. const uint8_t X_MAX = 43;
  44. const uint8_t Y_MIN = 10;
  45. const uint8_t Y_MAX = 37;
  46. uint8_t targetX = 0,targetY = 0;
  47. int32_t focusX = -255;
  48. int32_t  focusY = -255;
  49. int32_t randomFocusX = 255,randomFocusY = 255;
  50. int32_t minThld = 1500;
  51. uint8_t interactFlag  = 0;
  52. uint8_t oldInteractFlag = 0;
  53. uint8_t blinkFlag = 0;
  54. uint64_t end_time;
  55. uint64_t start_time;
  56. void setup()
  57. {
  58.   Serial.begin(115200);
  59.   display.begin();
  60.   display.setRotation(0);
  61.   display.drawPIC(0,0,320 ,480,(uint8_t *)figure);
  62.   sensorModuleInit();
  63.   
  64.   oldTime = millis();
  65. }
  66. void loop()
  67. {
  68.   interactFlag = coordinatop(0);
  69.   if(interactFlag == 0 && oldInteractFlag != 0){
  70.     eyeStates = 1;
  71.   }else if(interactFlag == 1){
  72.     eyeStates = 4;
  73.   }else if(interactFlag == 2 && oldInteractFlag != 2){
  74.     eyeStates = 2;
  75.     blinkFlag = 1;
  76.   }
  77.   oldInteractFlag = interactFlag;
  78.   newTime = millis();
  79.   if(newTime -oldTime >= 3000){
  80.     if(blinkFlag == 0 && eyeStates == 2){
  81.       blinkFlag = 1;
  82.     }
  83.     oldTime = newTime;
  84.   }
  85.   eyeInteraction();
  86. }
  87. void sensorModuleInit(){
  88.   while(tof.begin() != 0){
  89.     Serial.println("begin error !!!!!");
  90.   }
  91.   Serial.println("begin success");
  92.   while(tof.setRangingMode(eMatrix_8X8) != 0){
  93.     Serial.println("init error !!!!!");
  94.     delay(1000);
  95.   }
  96.   Serial.println("init success");
  97.   // for(int i = 0;i<2;i++){
  98.   //   minThld = 5000;
  99.   //   interactFlag = coordinatop(1);
  100.   //   delay(10);
  101.   // }
  102.   onBaseDraweye(1);
  103.   eyeWhiteRefresh();
  104. }
  105. uint8_t coordinatop(uint8_t initMode)
  106. {
  107.   uint16_t buf[64];
  108.   int32_t minDate = minThld;
  109.   int32_t temp;
  110.   focusX = 255;
  111.   focusY = 255;
  112.   uint8_t flag[4] = {0};
  113.   tof.getAllData(buf);
  114.   for(int i = 0;i < 8;i++){
  115.     for(int j = 0;j<8;j++){
  116.       if(initMode){
  117.         
  118.         if(minThld > buf[(i*8)+j]){
  119.           minThld = buf[(i*8)+j];
  120.         }
  121.       }else{
  122.           // Serial.print(buf[(i*8)+j]);
  123.           // Serial.print("\t");
  124.           if(buf[(i*8)+j]<30){
  125.               flag[0] = 1;
  126.           }
  127.           if(buf[(i*8)+j] > minThld){
  128.             flag[2] = 1;
  129.           }
  130.           if(minDate >= buf[(i*8)+j]){
  131.             minDate = buf[(i*8)+j];
  132.             focusX = j + 1;
  133.             focusY = i + 1;
  134.             flag[1] = 1;
  135.           }
  136.         
  137.       }
  138.     }
  139.   //  Serial.println();
  140.   }
  141. //  Serial.println("______________________________");
  142.   for(int i = 2;i >= 0;i--){
  143.     if(flag[i] == 1){
  144.       flag[3] = i;
  145.     }
  146.   }
  147.   
  148.   if(initMode){
  149.     minThld = minThld - 30;
  150.     if(minThld > 1330){
  151.       minThld  = 1300;
  152.     }
  153.   }
  154.   return flag[3];
  155. }
  156. //限幅
  157. void positionLimitation(uint8_t *x,uint8_t *y)
  158. {
  159.   MIN(*x,X_MIN);
  160.   MAX(*x,X_MAX);
  161.   MIN(*y,Y_MIN);
  162.   MAX(*y,Y_MAX);
  163. }
  164. uint8_t V[5] = {7, 5, 3, 2, 1}; // 速度数组(步长值)
  165. // 眼睛平滑移动函数
  166. void eyeSmoothMotion(uint8_t targetX, uint8_t targetY) {
  167.     static uint8_t oldTargetX = 255, oldTargetY = 255; // 存储上一次的目标位置
  168.     static bool isMovingX = false, isMovingY = false;
  169.     if (oldTargetX != targetX) {
  170.         oldTargetX = targetX;
  171.         isMovingX = true; // 标记X轴开始移动
  172.     }
  173.     if (oldTargetY != targetY) {
  174.         oldTargetY = targetY;
  175.         isMovingY = true; // 标记Y轴开始移动
  176.     }
  177.     int diffX = targetX - baseEye_x;
  178.     int diffY = targetY - baseEye_y;
  179.    
  180.     uint8_t absDiffX = abs(diffX);
  181.     uint8_t absDiffY = abs(diffY);
  182.     if (isMovingX) {
  183.         uint8_t vIndexX;
  184.         if (absDiffX > 20) {
  185.             vIndexX = 0;
  186.         } else if (absDiffX > 15) {
  187.             vIndexX = 1;
  188.         } else if (absDiffX > 5) {
  189.             vIndexX = 2;
  190.         } else if (absDiffX > 2) {
  191.             vIndexX = 3;
  192.         } else {
  193.             vIndexX = 4;
  194.         }
  195.         uint8_t speedStepX = V[vIndexX];
  196.         if (absDiffX <= speedStepX) {
  197.             baseEye_x = targetX;
  198.             isMovingX = false;
  199.         } else {
  200.             if (diffX > 0) {
  201.                 baseEye_x += speedStepX;
  202.             }else {
  203.                 baseEye_x -= speedStepX;
  204.             }
  205.         }
  206.     }
  207.     if (isMovingY) {
  208.         uint8_t vIndexY;
  209.         if (absDiffY > 20) {
  210.             vIndexY = 0;
  211.         } else if (absDiffY > 15) {
  212.             vIndexY = 1;
  213.         } else if (absDiffY > 5) {
  214.             vIndexY = 2;
  215.         } else if (absDiffY > 2) {
  216.             vIndexY = 3;
  217.         } else {
  218.             vIndexY = 4;
  219.         }
  220.         
  221.         uint8_t speedStepY = V[vIndexY];
  222.         if (absDiffY <= speedStepY) {
  223.             baseEye_y = targetY;
  224.             isMovingY = false;
  225.         } else {
  226.             if (diffY > 0) {
  227.                 baseEye_y += speedStepY;
  228.             } else {
  229.                 baseEye_y -= speedStepY;
  230.             }
  231.         }
  232.     }
  233. }
  234. void eyeWhiteRefresh(void)
  235. {
  236.   display.drawPIC(LEFT_EYE_COORDINATE_X,LEFT_EYE_COORDINATE_Y,EYE_SOCKET_WIDE ,EYE_SOCKET_LONG,(uint8_t*)base_l);
  237.   display.drawPIC(RIGHT_EYE_COORDINATE_X,RIGHT_EYE_COORDINATE_Y,EYE_SOCKET_WIDE ,EYE_SOCKET_LONG,(uint8_t*)base_r);
  238. }
  239. void onBaseDraweye(uint8_t initPlace)
  240. {
  241.   int drawEyeLeft_x,drawEyeRight_x;
  242.   int drawEyeLeft_y,drawEyeRight_y;
  243.   int drawEye_x,drawEye_y;
  244.   if(initPlace == 0){
  245.     drawEye_x = baseEye_x - eyeWide / 2;//眼睛照片在画布左上角的坐标
  246.     drawEye_y = baseEye_y - eyeLong / 2;
  247.     drawEyeLeft_x = drawEye_x;
  248.     drawEyeLeft_y = drawEye_y;
  249.     drawEyeRight_x = drawEye_x;
  250.     drawEyeRight_y = drawEye_y;
  251.   }else{
  252.     drawEye_x = baseMoveEyeLeft_x - eyeWide / 2;//眼睛照片在画布左上角的坐标
  253.     drawEye_y = baseMoveEyeLeft_y - eyeLong / 2;
  254.     drawEyeLeft_x = drawEye_x;
  255.     drawEyeLeft_y = drawEye_y;
  256.     drawEye_x = baseMoveEyeRight_x - eyeWide / 2;//眼睛照片在画布左上角的坐标
  257.     drawEye_y = baseMoveEyeRight_y - eyeLong / 2;
  258.     drawEyeRight_x = drawEye_x;
  259.     drawEyeRight_y = drawEye_y;
  260.   }
  261.   static int oldDrawEye_L_x = drawEye_x;
  262.   static int oldDrawEye_L_y = drawEye_y;//保存老的坐标点
  263.   
  264.   static int oldDrawEye_R_x;
  265.   static int oldDrawEye_R_y;
  266.   if(first_erasure == 0){
  267.     first_erasure = 1;
  268.   }else{
  269.     erasePaint(oldDrawEye_L_x,oldDrawEye_L_y,0,base_l,oldEye_l);
  270.     erasePaint(oldDrawEye_R_x,oldDrawEye_R_y,0,base_r,oldEye_r);
  271.   }
  272.     erasePaint(drawEyeLeft_x,drawEyeLeft_y,1,base_l,oldEye_l);
  273.     erasePaint(drawEyeRight_x,drawEyeRight_y,1,base_r,oldEye_r);
  274.     oldDrawEye_L_x = drawEyeLeft_x;
  275.     oldDrawEye_L_y = drawEyeLeft_y;
  276.     oldDrawEye_R_x = drawEyeRight_x;
  277.     oldDrawEye_R_y = drawEyeRight_y;
  278. }
  279. void erasePaint(int draweye_x,int draweye_y,uint8_t erasureFlag,uint16_t base[43][49],uint8_t oldEye[35][27])
  280. {
  281. int itemp,jtemp;
  282.   for(int i = 0;i < eyeLong;i++){
  283.     itemp = draweye_y + i;
  284.     if(itemp < 0 || itemp >= EYE_SOCKET_LONG){
  285.       continue;
  286.     }
  287.     for(int j  = 0;j < eyeWide;j++){
  288.       jtemp = draweye_x + j;
  289.       if(jtemp < 0 || jtemp >= EYE_SOCKET_WIDE)
  290.         continue;
  291.       if(erasureFlag){
  292.         if(base[itemp][jtemp] == 0xEF1B){
  293.           oldEye[i][j] = 1;
  294.           base[itemp][jtemp] = eye[i][j];
  295.         }
  296.       }else{
  297.         if(oldEye[i][j] == 1){
  298.           base[itemp][jtemp] = 0xEF1B;
  299.           oldEye[i][j] = 0;
  300.         }
  301.       }
  302.     }
  303.   }
  304. }
  305. void eyeInteraction()
  306. {
  307.   static uint8_t blinkingCount = 0;
  308.   static uint8_t eyeTrackFlag = 0;
  309.   static uint8_t eyeStates_ = eyeStates;
  310.   switch(eyeStates_)//0---睁眼状态 1---闭眼状态 2---闭眼过程中  3.睁眼过程中
  311.   {
  312.     case 0:
  313.       blinkingCount = 0;
  314.       if(eyeStates_ != eyeStates){
  315.           eyeStates_ = 5;
  316.       }
  317.       break;
  318.     case 1://闭上眼睛
  319.       if(blinkingCount < 2){
  320.         blinkingCount+=1;
  321.       }
  322.       if(eyeStates_ != eyeStates){
  323.         eyeStates_ = 3;
  324.       }
  325.       break;
  326.     case 2://闭眼过程中,衔接睁眼
  327.       if(blinkFlag){
  328.         if(++blinkingCount >= 2){
  329.           eyeStates_ = 3;
  330.         }
  331.       }else{
  332.         blinkingCount = 0;
  333.       }
  334.       if(eyeStates_ != eyeStates && blinkFlag == 0){
  335.           eyeStates_ = 5;
  336.         }
  337.       break;
  338.     case 3://睁眼过程中,衔接正脸
  339.       if(--blinkingCount <= 0){
  340.         eyeStates_ = 0;
  341.         blinkFlag = 0;
  342.       }
  343.       break;
  344.     case 4://眼睛跟踪扫描
  345.       if(eyeTrackFlag){//启动之前确保眼睛处于睁开状态
  346.         eyeballRefresh();
  347.       }else{
  348.         eyeRefresh(0);
  349.         eyeTrackFlag = 1;
  350.       }
  351.       if(eyeStates_ != eyeStates){
  352.         eyeStates_ = 5;
  353.         eyeTrackFlag = 0;
  354.       }
  355.       break;
  356.     case 5://转换器
  357.       if(eyeStates_ != eyeStates){
  358.         eyeStates_ = eyeStates;
  359.         blinkingCount = 0;
  360.       }
  361.       break;
  362.   }
  363.   if(eyeStates_ <= 3 && eyeStates_ >= 0 || eyeStates_ == 5){
  364.     eyeRefresh(blinkingCount);
  365.   }
  366. }
  367. void eyeballRefresh(void)
  368. {
  369.   if(interactFlag == 4){
  370.       targetX = EYE_MID_POS_X;
  371.       targetY = EYE_MID_POS_Y;
  372.   }else{
  373.     targetX = map(focusX,0,7,X_MAX, X_MIN);
  374.     targetY = map(focusY,0,7,Y_MIN, Y_MAX);
  375.     positionLimitation(&targetX,&targetY);
  376.   }
  377.   eyeSmoothMotion(targetX,targetY);
  378.   onBaseDraweye(0);
  379.   eyeWhiteRefresh();
  380. }
  381. void eyeRefresh(uint8_t blink)
  382. {
  383.   switch(blink)
  384.     {
  385.       case 0:
  386.         display.drawPIC(eyeLeftX,eyeLeftY,eyeWide1 ,eyeLong1,(uint8_t*)eye_l_0);
  387.         display.drawPIC(eyeRight_x,eyeRight_y,eyeWide1 ,eyeLong1,(uint8_t*)eye_r_0);
  388.         display.drawPIC(eyebrowX,eyebrowY,eyebrowWide ,eyebrowLong,(uint8_t*)eyebrow_0);
  389.         break;
  390.       case 1:
  391.         display.drawPIC(eyeRight_x,eyeRight_y,eyeWide1 ,eyeLong1,(uint8_t*)eye_r_2);
  392.         display.drawPIC(eyeLeftX,eyeLeftY,eyeWide1 ,eyeLong1,(uint8_t*)eye_l_2);
  393.         display.drawPIC(eyebrowX,eyebrowY,eyebrowWide ,eyebrowLong,(uint8_t*)eyebrow_3);
  394.         break;
  395.       case 2:
  396.         //display.drawPIC(eyebrowX,eyebrowY,eyebrowWide ,eyebrowLong,(uint8_t*)eyebrow_3);
  397.         display.drawPIC(eyeLeftX,eyeLeftY,eyeWide1 ,eyeLong1,(uint8_t*)eye_l_3);
  398.         display.drawPIC(eyeRight_x,eyeRight_y,eyeWide1 ,eyeLong1,(uint8_t*)eye_r_3);
  399.         break;
  400.     }  
  401. }
复制代码






























































































程序文件截图.png

hnyzcj  版主

发表于 前天 09:00

优秀
回复

使用道具 举报

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

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
关于楼主

楼主的其它帖子

上海智位机器人股份有限公司 沪ICP备09038501号-4 备案 沪公网安备31011502402448

© 2013-2025 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail