26浏览
查看: 26|回复: 2

[项目] 【Arduino 动手做】我使用 Arduino UNO 创建了一个绘图时钟

[复制链接]
当我思考要做什么的时候,我想起很久以前在YouTube上看到过一个情节时钟的视频,其中的时间画在白板上。

情节时钟看起来就像这样:你写下时间,擦掉,然后再写一次。它有一种模拟的感觉,很有趣。

我犹豫是否要使用像视频中那样的水性白板笔,因为擦拭时会出现污渍,而且笔也会变干。

不过, YouTube上有一个视频解决了这个问题。

通过将UV LED光照射到发光贴纸上来显示时间。由于照射后会残留余辉,因此如果连续绘制时间会弄脏,但如果按下按钮开关即可显示时间,则没有问题。

这次我们将尝试创建这种类型。

所用零件

电路图、草图、案例

有关如何创建和设置的说明,请参阅上面的参考视频(第 1 部分:制作)和下面的参考视频(第 2 部分:设置)。

创建和校准

临时组装在面包板上
为了进行调整和检查操作,我将其连接到面包板上,打印了前面板,并连接了伺服器等。

校准
我们将参考视频第二部分进行校准。将四个角粗略对齐后,您可以在显示时间的同时进行进一步的调整,但这种调整需要相当长的时间。

另外,如果连接臂的螺丝拧得太紧,显示的字符就会变形,因此如果字符显示不正确,则需要进行调整。

我尝试显示它,我喜欢它手写的样子。

我临时拼装了一下,确认没问题。请勿抄袭笔顺。(^_^)

【Arduino 动手做】我使用 Arduino UNO 创建了一个绘图时钟图2

【Arduino 动手做】我使用 Arduino UNO 创建了一个绘图时钟图1

【Arduino 动手做】我使用 Arduino UNO 创建了一个绘图时钟图3

【Arduino 动手做】我使用 Arduino UNO 创建了一个绘图时钟图4

【Arduino 动手做】我使用 Arduino UNO 创建了一个绘图时钟图6

【Arduino 动手做】我使用 Arduino UNO 创建了一个绘图时钟图5

【Arduino 动手做】我使用 Arduino UNO 创建了一个绘图时钟图7


驴友花雕  中级技神
 楼主|

发表于 3 小时前

【Arduino 动手做】我使用 Arduino UNO 创建了一个绘图时钟

项目代码

  1. //#define CALIBRATE
  2. //#define GRID // After Calibration this mode should plot a pretty good dot grid on the screen
  3. // See additional calibration comments in the code down by the "#ifdef CALIBRATE"
  4. // Adjust these values for servo arms in position for state 1 _|
  5. const double SERVO_LEFT_ZERO =  1600;
  6. const double SERVO_RIGHT_SCALE = 690; // + makes rotate further left
  7. // Adjust these values for servo arms in position for state 2 |_
  8. const double SERVO_RIGHT_ZERO = 650;
  9. const double SERVO_LEFT_SCALE = 650;
  10. #define OPTION_12_HOUR // 12 or comment out this line for 24 hour time
  11. //#define OPTION_MONTH_DAY // commented out = month/day or uncomment the line for day/month
  12. const double DRAW_DELAY = 5; // 3
  13. ///////////////////////////////////////////////////////////////////////////////
  14. // Plotclock
  15. // cc - by Johannes Heberlein 2014
  16. // modified for glow clock - Tucker Shannon 2018
  17. // improved - 12Me21 2018
  18. // v 1.07ddd
  19. // thingiverse.com/joo   wiki.fablab-nuernberg.de
  20. // thingiverse.com/TuckerPi
  21. // units: mm; microseconds; radians
  22. // origin: bottom left of drawing surface
  23. // time library see http://playground.arduino.cc/Code/time
  24. // RTC  library see http://playground.arduino.cc/Code/time
  25. //               or http://www.pjrc.com/teensy/td_libs_DS1307RTC.html
  26. // Change log:
  27. // 1.01  Release by joo at https://github.com/9a/plotclock
  28. // 1.02  Additional features implemented by Dave (https://github.com/Dave1001/):
  29. //       - added ability to calibrate servofaktor seperately for left and right servos
  30. //       - added code to support DS1307, DS1337 and DS3231 real time clock chips
  31. //       - see http://www.pjrc.com/teensy/td_libs_DS1307RTC.html for how to hook up the real time clock
  32. // 1.03  Fixed the length bug at the servoplotclockogp2 angle calculation, other fixups
  33. // 1.04  Modified for Tuck's glow clock
  34. // 1.05  Modified calibration mode to draw a 4 point square instead
  35. // 1.06  Rewrote most of the code, improved calibration, added date drawing, fixed bug in angle calculations, etc.
  36. // 1.07ddd  Reverted code to return it to using the DS1307 Library and removed the long press date code.
  37. //          Did this because I liked this codes calibration code better than the v1.05 calibration code that drew a square.
  38. //          Plus the bug fixes in 1.06 are good
  39. //          Added comments on how to calibrate
  40. //          Split Number drawing and letter drawing into two different functions
  41. //          Improved the letter "I"
  42. ///////////////////////////////////////////////////////////////////////////////
  43. #include <Time.h> // see http://playground.arduino.cc/Code/time
  44. #include <TimeLib.h>
  45. #include <Servo.h> //servo controller
  46. #include <Wire.h>
  47. #include <DS1307RTC.h> // see http://playground.arduino.cc/Code/time
  48. //pins
  49. const int SERVO_LEFT_PIN = 6;
  50. const int SERVO_RIGHT_PIN = 5;
  51. const int LED_PIN = 12;
  52. const int BUTTON_PIN = 13;
  53. //Sizes
  54. const double LOWER_ARM = 35; //servo to lower arm joint
  55. const double UPPER_ARM_LEFT = 56; //lower arm joint to led
  56. const double LED_ARM = 13.5; //upper arm joint to led
  57. const double UPPER_ARM = 45; //lower arm joint to upper arm joint
  58. double cosineRule(double a, double b, double c);
  59. const double LED_ANGLE = cosineRule(UPPER_ARM_LEFT,UPPER_ARM,LED_ARM);
  60. //Location of servos relative to origin
  61. const double SERVO_LEFT_X = 22;
  62. const double SERVO_LEFT_Y = -32;
  63. const double SERVO_RIGHT_X = SERVO_LEFT_X + 25.5;
  64. const double SERVO_RIGHT_Y = SERVO_LEFT_Y;
  65. // lovely macros
  66. #define radian(angle) (M_PI*2* angle)
  67. #define dist(x,y) sqrt(sq(x)+sq(y))
  68. #define angle(x,y) atan2(y,x)
  69. //digit location/size constants
  70. const double TIME_BOTTOM = 12;
  71. const double TIME_WIDTH = 11;
  72. const double TIME_HEIGHT = 18; //16;
  73. const double DAY_WIDTH = 7;
  74. const double DAY_HEIGHT = 12;
  75. const double DAY_BOTTOM = 5;
  76. const double DATE_BOTTOM = 24;
  77. const double HOME_X = 55, HOME_Y = -5;
  78. Servo servoLeft, servoRight;
  79. // Sunday is the first triple
  80. const char weekDays[] = {8,10,12, 5,6,12, 9,10,2, 11,2,13, 9,4,10, 3,7,14, 8,1,9}; //character set: AEFHMORSTUWNDI
  81. double lastX = HOME_X, lastY = HOME_Y;
  82. bool lightOn = false;
  83. void setup() {
  84.     pinMode(LED_PIN, OUTPUT);
  85.     digitalWrite(LED_PIN, LOW);
  86.     pinMode(BUTTON_PIN, INPUT_PULLUP);
  87. }
  88. void light(bool state){
  89.     lightOn = state == HIGH; //I'm *pretty* sure HIGH/LOW are just true/false, but...
  90.     delay(100);
  91.     digitalWrite(LED_PIN, state);
  92. }
  93. const int LONG_PRESS_DURATION = 750;
  94. void loop(){
  95.     if(digitalRead(BUTTON_PIN) != LOW)
  96.         return;
  97.     if (!servoLeft.attached()) servoLeft.attach(SERVO_LEFT_PIN);
  98.     if (!servoRight.attached()) servoRight.attach(SERVO_RIGHT_PIN);
  99.     #ifdef CALIBRATE
  100.         // Pressing the button alternates the servo arms between 2 states.
  101.         // State one if left arm pointing to 9 o'clock and right arm pointing to 12 o'clock _|
  102.         // State two if left arm pointing to 12 o'clock and right arm pointing to 3 o'clock |_
  103.         // At the very top of the code you adjust the 4 constants to get the arms into these exact positions.
  104.         // Adjust SERVO_LEFT_ZERO so that the left servo points to 9 o'clock when in state one
  105.         // Adjust SERVO_RIGHT_SCALE so that the right servo points to 12 o'clock when in state one
  106.         
  107.         // Adjust SERVO_RIGHT_ZERO so that the right servo points to 3 o'clock when in state two
  108.         // Adjust SERVO_LEFT_SCALE so that the left servo points to 12 o'clock when in state two
  109.         
  110.         static bool half;
  111.         servoLeft.writeMicroseconds(floor(SERVO_LEFT_ZERO + (half ? - M_PI/2  : 0) * SERVO_LEFT_SCALE ));
  112.         servoRight.writeMicroseconds(floor(SERVO_RIGHT_ZERO + (half ? 0 : M_PI/2 ) * SERVO_RIGHT_SCALE ));
  113.         light(half ? LOW : HIGH);
  114.         half = !half;
  115.         delay(2000);
  116.     #else //CALIBRATE
  117.         #ifdef GRID
  118.             for(int i = 0; i <= 70; i += 10)
  119.                 for(int j = 0; j <= 40; j += 10){
  120.                     drawTo(i, j);
  121.                     light(HIGH);
  122.                     light(LOW);
  123.                 }
  124.         #else //GRID
  125.             delay(10); // debounce
  126.             uint32_t longpress = millis() + LONG_PRESS_DURATION;
  127.             while ((!digitalRead(BUTTON_PIN)) && (millis() < longpress))
  128.             { }; // wait
  129.             bool date = false;
  130.             if (millis() >= longpress)
  131.                 date = true;
  132.                
  133.             drawTo(HOME_X, 0);
  134.             tmElements_t tm;
  135.             //time_t tt;
  136.             uint8_t dayOfWeek; // 0 = Sunday, 6 = Saturday
  137.             if (RTC.read(tm))
  138.             {
  139.               setTime(tm.Hour,tm.Minute,tm.Second,tm.Day,tm.Month,tm.Year);
  140.               //tt = makeTime(tm); // need a normal time so it can be converted to day of week. Sunday = 1
  141.               dayOfWeek = dayOfWeek(makeTime(tm)) - 1; // the minus 1 normalized so Sunday = 0
  142.             }
  143.             if (date) {
  144.               #ifdef OPTION_MONTH_DAY
  145.                   int temp = tm.Day;
  146.                   tm.Day = tm.Month;
  147.                   tm.Month = temp;
  148.               #endif
  149.               //draw month
  150.               if(tm.Month / 10)
  151.                   drawDigit(70-(DAY_WIDTH+3)*5, DATE_BOTTOM, DAY_WIDTH, DAY_HEIGHT, tm.Month / 10);
  152.               drawDigit(70-(DAY_WIDTH+3)*4, DATE_BOTTOM, DAY_WIDTH, DAY_HEIGHT, tm.Month % 10);
  153.               // Draw Slash
  154.               drawDigit(70-(DAY_WIDTH+3)*3, DATE_BOTTOM, DAY_WIDTH, DAY_HEIGHT, 12);
  155.               //day
  156.               if(tm.Day / 10){
  157.                   drawDigit(70-(DAY_WIDTH+3)*2, DATE_BOTTOM, DAY_WIDTH, DAY_HEIGHT, tm.Day / 10);
  158.                   drawDigit(70-(DAY_WIDTH+3), DATE_BOTTOM, DAY_WIDTH, DAY_HEIGHT, tm.Day % 10);
  159.               }else
  160.                   drawDigit(70-(DAY_WIDTH+3)*2, DATE_BOTTOM, DAY_WIDTH, DAY_HEIGHT, tm.Day % 10);
  161.               //weekday
  162.               drawChar(5,DAY_BOTTOM,DAY_WIDTH,DAY_HEIGHT,weekDays[dayOfWeek*3]);
  163.               drawChar(5+DAY_WIDTH+5,DAY_BOTTOM,DAY_WIDTH,DAY_HEIGHT, weekDays[dayOfWeek*3+1]);
  164.               drawChar(5+(DAY_WIDTH+5)*2,DAY_BOTTOM,DAY_WIDTH,DAY_HEIGHT,weekDays[dayOfWeek*3+2]);
  165.               
  166.             } else {
  167.               #ifdef OPTION_12_HOUR
  168.                 if(tm.Hour >= 12){
  169.                     tm.Hour = tm.Hour - 12;
  170.                     // drawDigit(5,35,1,1,10); // Draws a DOT - Not sure why
  171.                 }
  172.                 if(tm.Hour == 0)
  173.                     tm.Hour = 12;
  174.               #endif
  175.               //draw hour
  176.               if(tm.Hour / 10)
  177.                   drawDigit(3, TIME_BOTTOM, TIME_WIDTH, TIME_HEIGHT, tm.Hour / 10);
  178.               drawDigit(3+TIME_WIDTH+3, TIME_BOTTOM, TIME_WIDTH, TIME_HEIGHT, tm.Hour % 10);
  179.               // Draw colon
  180.               drawDigit((69-TIME_WIDTH)/2, TIME_BOTTOM, TIME_WIDTH, TIME_HEIGHT, 11);
  181.               //minute
  182.               drawDigit(69-(TIME_WIDTH+3)*2, TIME_BOTTOM, TIME_WIDTH, TIME_HEIGHT, tm.Minute / 10);
  183.               drawDigit(72-(TIME_WIDTH+3), TIME_BOTTOM, TIME_WIDTH, TIME_HEIGHT, tm.Minute % 10);
  184.               
  185.             }
  186.         #endif // NOT CALIBRATE OR GRID
  187.         drawTo(HOME_X, HOME_Y);
  188.     #endif // GRID or Normal Plot Time
  189.     servoLeft.detach();
  190.     servoRight.detach();
  191. }
  192. #define digitMove(dx, dy) drawTo(x + width*dx, y + height*dy)
  193. #define digitStart(dx, dy) digitMove(dx, dy); light(HIGH)
  194. #define digitArc(dx, dy, rx, ry, start, last) drawArc(x + width*dx, y + height*dy, width*rx, height*ry, radian(start), radian(last))
  195. // Symbol is drawn with the lower left corner at (x,y) and a size of (width,height).
  196. void drawDigit(double x, double y, double width, double height, char digit) {
  197.     //see macros for reference
  198.     switch (digit) {
  199.         case 0: //
  200.             digitStart(1/2,1);
  201.             digitArc(1/2,1/2, 1/2,1/2, 1/4, -3/4);
  202.             //digitStart(1,1/2);
  203.             //digitArc(1/2,1/2, 1/2,1/2, 0, 1.02);
  204.             break;
  205.         case 1: //
  206.             digitStart(1/4,7/8);
  207.             digitMove(1/2,1);
  208.             digitMove(1/2,0);
  209.             break;
  210.         case 2: //
  211.             digitStart(0,3/4);
  212.             digitArc(1/2,3/4, 1/2,1/4, 1/2, -1/8);
  213.             digitArc(1,0, 1,1/2, 3/8, 1/2);
  214.             digitMove(1,0);
  215.             break;
  216.         case 3:
  217.             digitStart(0,3/4);
  218.             digitArc(1/2,3/4, 1/2,1/4, 3/8, -1/4);
  219.             digitArc(1/2,1/4, 1/2,1/4, 1/4, -3/8);
  220.             break;
  221.         case 4:
  222.             digitStart(1,3/8);
  223.             digitMove(0,3/8);
  224.             digitMove(3/4,1);
  225.             digitMove(3/4,0);
  226.             break;
  227.         case 5: //wayy too many damn lines
  228.             digitStart(1,1);
  229.             digitMove(0,1);
  230.             digitMove(0,1/2);
  231.             digitMove(1/2,1/2);
  232.             digitArc(1/2,1/4, 1/2,1/4, 1/4, -1/4);
  233.             digitMove(0,0);
  234.             break;
  235.         case 6:
  236.             digitStart(0,1/4);
  237.             digitArc(1/2,1/4, 1/2,1/4, 1/2, -1/2);
  238.             digitArc(1,1/2, 1,1/2, 1/2, 1/4);
  239.             break;
  240.         case 7:
  241.             digitStart(0,1);
  242.             digitMove(1,1);
  243.             digitMove(1/4,0);   
  244.             break;
  245.         case 8:
  246.             digitStart(1/2,1/2);
  247.             digitArc(1/2,3/4, 1/2,1/4, -1/4, 3/4);
  248.             digitArc(1/2,1/4, 1/2,1/4, 1/4, -3/4);
  249.             break;
  250.         case 9:
  251.             digitStart(1,3/4);
  252.             digitArc(1/2,3/4, 1/2,1/4, 0, 1);
  253.             digitMove(3/4,0);
  254.             break;
  255.         case 10: //dot
  256.             digitStart(0,0);
  257.             //digitMove(0,1);
  258.             //digitMove(1,1);
  259.             //digitMove(1,0);
  260.             break;
  261.         case 11: //colon
  262.             digitStart(1/2,3/4);
  263.             light(LOW);
  264.             digitStart(1/2,1/4);
  265.             break;
  266.         case 12: //slash
  267.             digitStart(3/4,5/4);
  268.             digitMove(1/4,-1/4);
  269.             break;
  270.     }
  271.     light(LOW);
  272. }
  273. void drawChar(double x, double y, double width, double height, char digit) {
  274.     //see macros for reference
  275.     switch (digit) {
  276.         //letters for the day of the week
  277.         case 1: //A
  278.             digitStart(0,0);
  279.             digitMove(1/2,1);
  280.             digitMove(1,0);
  281.             light(LOW);
  282.             digitStart(1/4,1/2);
  283.             digitMove(3/4,1/2);
  284.           break;
  285.         case 2: //E
  286.             digitStart(1,0);
  287.             digitMove(0,0);
  288.             digitMove(0,1);
  289.             digitMove(1,1);
  290.             light(LOW);
  291.             digitStart(0,1/2);
  292.             digitMove(1,1/2);
  293.             break;
  294.         case 3: //F
  295.             digitStart(0,0);
  296.             digitMove(0,1);
  297.             digitMove(1,1);
  298.             light(LOW);
  299.             digitStart(0,1/2);
  300.             digitMove(1,1/2);
  301.             break;
  302.         case 4: //H
  303.             digitStart(0,1);
  304.             digitMove(0,0);
  305.             light(LOW);
  306.             digitStart(0,1/2);
  307.             digitMove(1,1/2);
  308.             light(LOW);
  309.             digitStart(1,1);
  310.             digitMove(1,0);
  311.             break;
  312.         case 5: //M
  313.             digitStart(0,0);
  314.             digitMove(0,1);
  315.             digitMove(1/2,1/2);
  316.             digitMove(1,1);
  317.             digitMove(1,0);
  318.             break;
  319.         case 6: //O (0)
  320.             digitStart(1,1/2);
  321.             digitArc(1/2,1/2, 1/2,1/2, 0, 1.02);
  322.             break;
  323.         case 7: //R
  324.             digitStart(0,0);
  325.             digitMove(0,1);
  326.             digitMove(1/2,1);
  327.             digitArc(1/2,3/4, 1/2,1/4, 1/4, -1/4);
  328.             digitMove(0,1/2);
  329.             digitMove(1,0);
  330.             break;
  331.         case 8: //S
  332.             digitStart(0,0);
  333.             digitMove(1/2,0);
  334.             digitArc(1/2,1/4, 1/2,1/4, -1/4, 1/4);
  335.             digitArc(1/2,3/4, 1/2,1/4, 3/4, 1/4);
  336.             digitMove(1,1);
  337.             break;
  338.         case 9: //T
  339.             digitStart(1,1);
  340.             digitMove(-1/2,1); //bad
  341.             light(LOW);
  342.             digitStart(1/2,1);
  343.             digitMove(1/2,0);
  344.             break;
  345.         case 10: //U
  346.             digitStart(0,1);
  347.             digitMove(0,1/4);
  348.             digitArc(1/2,1/4, 1/2,1/4, -1/2, 0);
  349.             digitMove(1,1);
  350.             break;
  351.         case 11: //W
  352.             digitStart(0,1);
  353.             digitMove(0,0);
  354.             digitMove(1/2,1/2);
  355.             digitMove(1,0);
  356.             digitMove(1,1);
  357.             break;
  358.         case 12: //N
  359.             digitStart(0,0);
  360.             digitMove(0,1);
  361.             digitMove(1,0);
  362.             digitMove(1,1);
  363.             break;
  364.         case 13: //D
  365.             digitStart(0,0);
  366.             digitMove(0,1);
  367.             digitMove(1/2,1);
  368.             digitArc(1/2,1/2, 1/2,1/2, 1/4,-1/4);
  369.             digitMove(0,0);
  370.             break;
  371.         case 14: //I
  372.             digitStart(1/2,1);
  373.             digitMove(1/2,0);
  374.             light(LOW);
  375.             digitStart(0,0);
  376.             digitMove(1,0);
  377.             light(LOW);
  378.             digitStart(1,1);
  379.             digitMove(0,1);
  380.             break;
  381.     }
  382.     light(LOW);
  383. }
  384. #define ARCSTEP 0.05 //0.05 //should change depending on radius...
  385. void drawArc(double x, double y, double rx, double ry, double pos, double last) {
  386.     if(pos < last)
  387.         for(; pos <= last; pos += ARCSTEP)
  388.             drawTo(x + cos(pos)*rx, y + sin(pos)*ry);
  389.     else
  390.         for(; pos >= last; pos -= ARCSTEP)
  391.             drawTo(x + cos(pos)*rx, y + sin(pos)*ry);
  392. }
  393. //didn't really change this
  394. void drawTo(double pX, double pY) {
  395.     double dx, dy, c;
  396.     int i;
  397.    
  398.     // dx dy of new point
  399.     dx = pX - lastX;
  400.     dy = pY - lastY;
  401.     //path length in mm, times 4 equals 4 steps per mm
  402.     c = floor(4 * dist(dx,dy));
  403.    
  404.     if (c < 1)
  405.         c = 1;
  406.    
  407.     // draw line point by point
  408.     for (i = 1; i <= c; i++){
  409.         set_XY(lastX + (i * dx / c), lastY + (i * dy / c));
  410.         if (lightOn)
  411.             delay(DRAW_DELAY);
  412.     }
  413.    
  414.     lastX = pX;
  415.     lastY = pY;
  416. }
  417. // cosine rule for angle between c and a
  418. double cosineRule(double a, double b, double c) {
  419.     return acos((sq(a)+sq(c)-sq(b))/(2*a*c));
  420. }
  421. void set_XY(double x, double y) {
  422.     //Calculate triangle between left servo, left arm joint, and light
  423.     //Position of pen relative to left servo
  424.     //rectangular
  425.     double penX = x - SERVO_LEFT_X;
  426.     double penY = y - SERVO_LEFT_Y;
  427.     //polar
  428.     double penAngle = angle(penX,penY);
  429.     double penDist = dist(penX,penY);
  430.     //get angle between lower arm and a line connecting the left servo and the pen
  431.     double bottomAngle = cosineRule(LOWER_ARM, UPPER_ARM_LEFT, penDist);
  432.    
  433.     servoLeft.writeMicroseconds(floor(SERVO_LEFT_ZERO + (bottomAngle + penAngle - M_PI) * SERVO_LEFT_SCALE));
  434.    
  435.     //calculate middle arm joint location
  436.     double topAngle = cosineRule(UPPER_ARM_LEFT, LOWER_ARM, penDist);
  437.     double lightAngle = penAngle - topAngle + LED_ANGLE + M_PI;
  438.     double jointX = x - SERVO_RIGHT_X + cos(lightAngle) * LED_ARM;
  439.     double jointY = y - SERVO_RIGHT_Y + sin(lightAngle) * LED_ARM;
  440.    
  441.     bottomAngle = cosineRule(LOWER_ARM, UPPER_ARM, dist(jointX, jointY));
  442.     double jointAngle = angle(jointX, jointY);
  443.    
  444.     servoRight.writeMicroseconds(floor(SERVO_RIGHT_ZERO + (jointAngle - bottomAngle) * SERVO_RIGHT_SCALE));
  445. }
复制代码


回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 3 小时前

【Arduino 动手做】我使用 Arduino UNO 创建了一个绘图时钟

回复

使用道具 举报

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

本版积分规则

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

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4 备案 沪公网安备31011502402448

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

mail