2025-11-19 10:24:49 [显示全部楼层]
7浏览
查看: 7|回复: 0

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

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

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






























































































程序文件截图.png
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

硬件清单

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

楼主的其它帖子

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

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

mail