【花雕学编程】Arduino CNC 之平滑的三轴加减速运动

在这里插入图片描述

Arduino是一个开放源码的电子原型平台,它可以让你用简单的硬件和软件来创建各种互动的项目。Arduino的核心是一个微控制器板,它可以通过一系列的引脚来连接各种传感器、执行器、显示器等外部设备。Arduino的编程是基于C/C++语言的,你可以使用Arduino IDE(集成开发环境)来编写、编译和上传代码到Arduino板上。Arduino还有一个丰富的库和社区,你可以利用它们来扩展Arduino的功能和学习Arduino的知识。

Arduino的特点是:
1、开放源码:Arduino的硬件和软件都是开放源码的,你可以自由地修改、复制和分享它们。
2、易用:Arduino的硬件和软件都是为初学者和非专业人士设计的,你可以轻松地上手和使用它们。
3、便宜:Arduino的硬件和软件都是非常经济的,你可以用很低的成本来实现你的想法。
4、多样:Arduino有多种型号和版本,你可以根据你的需要和喜好来选择合适的Arduino板。
5、创新:Arduino可以让你用电子的方式来表达你的创意和想象,你可以用Arduino来制作各种有趣和有用的项目,如机器人、智能家居、艺术装置等。

在这里插入图片描述
Arduino CNC,全称Arduino Computerized Numerical Control(Arduino计算机数字控制),是结合了Arduino开源微控制器平台与CNC(计算机数字控制)技术的系统。这种系统广泛应用于自动化加工、3D打印、机械臂控制、机器人制作以及CNC雕刻机等领域。下面是对Arduino CNC的全面详细科学解释:

一、Arduino平台概述
1、定义:Arduino是一个开源的硬件和软件平台,它使得电子制作变得简单快捷。Arduino由一个可编程的微控制器(如ATmega328P)和相关电路板(如Arduino Uno)组成,通过简单的编程语言(Arduino IDE)和大量预制的库函数,用户可以轻松实现复杂的电子项目。
2、特点:
开源性:Arduino的硬件设计、软件(IDE)和参考设计都是开源的,允许用户自由修改和分发。
易用性:Arduino IDE基于C/C++语言,但提供了简化的编程接口,降低了学习门槛。
扩展性:通过各种扩展板和传感器,可以轻松扩展Arduino的功能。

二、CNC技术概述
1、定义:CNC(Computerized Numerical Control)即计算机数字控制,是一种通过预先编程的计算机程序来控制机床或其他自动化设备的运动轨迹、速度和加工参数的技术。CNC技术实现了加工过程的自动化和精确化。
2、工作原理:CNC系统通过读取存储在计算机中的程序指令,将其转换成控制机床运动的电信号,从而实现对机床的精确控制。这些程序指令通常包含了对机床各轴(如X、Y、Z轴)的位置、速度、加速度等的精确描述。

三、Arduino CNC系统
1、系统组成:
Arduino开发板:作为系统的主控制器,负责接收和处理CNC程序指令。
CNC扩展板:通常包括步进电机驱动器(如A4988)和相关的接口电路,用于将Arduino发出的控制信号转换为步进电机的驱动信号。
步进电机:作为执行机构,根据CNC程序指令实现精确的位置移动。
CNC软件:用于编写和编辑CNC程序,并将其传输到Arduino开发板中。
2、工作流程:
用户使用CNC软件编写加工程序,并将其保存到计算机中。
将加工程序通过串口或其他方式传输到Arduino开发板中。
Arduino开发板读取程序指令,并通过CNC扩展板将控制信号发送到步进电机驱动器。
步进电机驱动器将控制信号转换为步进电机的驱动电流,驱动步进电机按照程序指令进行精确的位置移动。
3、应用领域:
3D打印:控制3D打印机的打印头和平台运动。
机械臂控制:实现机械臂的精确抓取和移动。
CNC雕刻机:用于木材、塑料、金属等材料的精确雕刻和切割。
机器人制作:作为机器人的控制系统,实现机器人的自主移动和作业。

四、总结
Arduino CNC系统通过结合Arduino开源微控制器平台和CNC计算机数字控制技术,实现了加工过程的自动化和精确化。该系统具有开源性、易用性和扩展性等优点,广泛应用于3D打印、机械臂控制、CNC雕刻机等领域。随着技术的不断发展,Arduino CNC系统将在更多领域发挥重要作用。

在这里插入图片描述
主要特点

  1. 运动平稳性
    在 Arduino CNC(计算机数字控制)系统中,平滑的三轴加减速运动能够避免电机在启动和停止时产生剧烈的冲击。传统的直接启动和停止方式可能会导致电机扭矩瞬间变化过大,引起机械结构的震动和磨损。而平滑的加减速运动通过逐渐增加或减小电机的速度,使运动过程更加平稳,减少了对机械部件的损害,延长了设备的使用寿命。
    例如,在使用 CNC 雕刻机进行精细雕刻时,平稳的运动可以保证刀具在切入和切出材料时不会因为震动而产生毛刺,提高了加工表面的质量。
  2. 速度控制精确
    可以精确地控制三轴(通常为 X、Y、Z 轴)在加减速过程中的速度变化。通过合理设置加减速曲线,能够根据不同的加工需求调整速度的变化率。比如,在进行高速加工时,可以设置较快的加速度以提高加工效率;而在接近工件表面或进行精细加工时,则设置较慢的加速度,以确保加工精度。
    利用 Arduino 的编程能力,可以实现复杂的速度控制算法,如 S 曲线加减速,使速度变化更加平滑和精确。
  3. 减少误差累积
    平滑的加减速运动有助于减少运动过程中的误差累积。在 CNC 加工中,每一次的位置误差都可能会影响最终的加工精度。通过平稳的加减速,能够更好地控制电机的步数和位置,降低因速度突变而导致的定位误差。
    特别是在进行多轴联动的复杂加工时,各轴之间的运动协调非常重要。平滑的加减速可以保证各轴之间的同步性,减少因速度不一致而产生的误差。
  4. 提高运动效率
    合理的加减速控制可以在保证运动平稳和精度的前提下,提高整体的运动效率。相比于直接启动和停止,平滑的加减速可以使电机更快地达到目标速度,减少了无效的运动时间。
    例如,在 CNC 铣床中,快速而平滑的加减速可以使刀具更快地到达加工位置,提高了单位时间内的加工量。

应用场景

  1. 精密机械加工
    在制造高精度的机械零件时,如航空航天领域的零部件、光学仪器的精密部件等,对加工精度和表面质量要求极高。平滑的三轴加减速运动能够确保刀具在加工过程中的稳定运行,减少因震动和误差累积而导致的尺寸偏差和表面粗糙度问题。
    例如,在加工发动机的精密齿轮时,平滑的运动可以保证齿轮的齿形精度和表面光洁度,提高齿轮的传动性能。
  2. 3D 打印
    3D 打印过程中,喷头的运动需要精确控制。平滑的加减速运动可以使喷头在移动过程中更加稳定,避免因速度突变而导致的材料挤出不均匀、层间结合不良等问题。
    特别是在打印复杂的三维模型时,各轴的协调运动和平滑的加减速能够保证模型的精度和质量。
  3. 激光切割与雕刻
    激光切割和雕刻设备需要精确控制激光头的运动轨迹和速度。平滑的三轴加减速运动可以使激光头在启动和停止时更加平稳,避免因速度变化过快而导致的切割边缘不整齐、雕刻深度不一致等问题。
    例如,在对木材、亚克力等材料进行激光雕刻时,平稳的运动可以使雕刻图案更加清晰、细腻。

需要注意的事项

  1. 参数设置与优化
    加减速的参数设置(如加速度、减速度、最大速度等)需要根据具体的硬件设备(如电机、驱动器、机械结构等)和加工任务进行优化。不合适的参数设置可能会导致运动不平稳、电机失步等问题。
    例如,如果加速度设置过大,电机可能无法及时响应,导致失步现象;而加速度设置过小,则会降低运动效率。
  2. 电机扭矩与负载匹配
    在进行加减速运动时,要确保电机的扭矩能够满足负载的需求。特别是在加速度较大的情况下,电机需要提供足够的扭矩来克服惯性力。如果电机扭矩不足,可能会导致电机堵转或失步,影响加工精度和设备的正常运行。
    因此,在选择电机和驱动器时,需要根据负载的大小和运动要求进行合理匹配,并在实际应用中进行测试和调整。
  3. 实时监测与反馈
    为了确保加减速运动的平滑性和准确性,需要对电机的运行状态进行实时监测。可以通过编码器等传感器获取电机的位置和速度信息,并将其反馈给 Arduino 控制系统。
    如果发现运动过程中出现异常情况(如失步、速度偏差等),控制系统可以及时进行调整,保证运动的稳定性。
  4. 软件与硬件兼容性
    确保 Arduino 所使用的控制软件与硬件设备(如电机驱动器、传感器等)之间具有良好的兼容性。不同的硬件设备可能需要不同的控制信号和通信协议,需要进行相应的编程和配置。
    同时,要注意软件的稳定性和可靠性,避免因软件故障而导致的运动异常。

在这里插入图片描述
1、三轴基本运动

#include <AccelStepper.h>

// 定义步进电机引脚
#define stepPinX 2
#define dirPinX 5
#define stepPinY 3
#define dirPinY 6
#define stepPinZ 4
#define dirPinZ 7

// 创建步进电机对象
AccelStepper stepperX(1, stepPinX, dirPinX);
AccelStepper stepperY(1, stepPinY, dirPinY);
AccelStepper stepperZ(1, stepPinZ, dirPinZ);

void setup() {
    Serial.begin(115200);
    
    // 设置速度和加速度
    stepperX.setMaxSpeed(500);
    stepperX.setAcceleration(100);
    
    stepperY.setMaxSpeed(500);
    stepperY.setAcceleration(100);
    
    stepperZ.setMaxSpeed(500);
    stepperZ.setAcceleration(100);
}

void loop() {
    // 让 X 轴移动
    stepperX.moveTo(1000); // 向前移动1000步
    stepperY.moveTo(0); // Y 轴保持在0
    stepperZ.moveTo(0); // Z 轴保持在0

    while (stepperX.distanceToGo() != 0 || stepperY.distanceToGo() != 0 || stepperZ.distanceToGo() != 0) {
        stepperX.run();
        stepperY.run();
        stepperZ.run();
    }

    delay(1000); // 暂停1秒

    // 让 Y 轴移动
    stepperX.moveTo(0); // X 轴回到0
    stepperY.moveTo(1000); // 向前移动1000步
    stepperZ.moveTo(0); // Z 轴保持在0

    while (stepperX.distanceToGo() != 0 || stepperY.distanceToGo() != 0 || stepperZ.distanceToGo() != 0) {
        stepperX.run();
        stepperY.run();
        stepperZ.run();
    }

    delay(1000); // 暂停1秒

    // 让 Z 轴移动
    stepperX.moveTo(0); // X 轴保持在0
    stepperY.moveTo(0); // Y 轴保持在0
    stepperZ.moveTo(1000); // 向前移动1000步

    while (stepperX.distanceToGo() != 0 || stepperY.distanceToGo() != 0 || stepperZ.distanceToGo() != 0) {
        stepperX.run();
        stepperY.run();
        stepperZ.run();
    }

    delay(1000); // 暂停1秒
}

2、三轴顺序运动

#include <AccelStepper.h>

// 定义步进电机引脚
#define stepPinX 2
#define dirPinX 5
#define stepPinY 3
#define dirPinY 6
#define stepPinZ 4
#define dirPinZ 7

// 创建步进电机对象
AccelStepper stepperX(1, stepPinX, dirPinX);
AccelStepper stepperY(1, stepPinY, dirPinY);
AccelStepper stepperZ(1, stepPinZ, dirPinZ);

void setup() {
    Serial.begin(115200);

    // 设置速度和加速度
    stepperX.setMaxSpeed(300);
    stepperX.setAcceleration(150);
    
    stepperY.setMaxSpeed(300);
    stepperY.setAcceleration(150);
    
    stepperZ.setMaxSpeed(300);
    stepperZ.setAcceleration(150);
}

void loop() {
    // 顺序移动三轴
    moveAxes(1000, 1000, 1000); // 向(1000, 1000, 1000)移动
    delay(1000); // 暂停1秒
    moveAxes(0, 0, 0); // 返回原点
    delay(1000); // 暂停1秒
}

void moveAxes(int x, int y, int z) {
    stepperX.moveTo(x);
    stepperY.moveTo(y);
    stepperZ.moveTo(z);

    while (stepperX.distanceToGo() != 0 || stepperY.distanceToGo() != 0 || stepperZ.distanceToGo() != 0) {
        stepperX.run();
        stepperY.run();
        stepperZ.run();
    }
}

3、三轴同步运动

#include <AccelStepper.h>

// 定义步进电机引脚
#define stepPinX 2
#define dirPinX 5
#define stepPinY 3
#define dirPinY 6
#define stepPinZ 4
#define dirPinZ 7

// 创建步进电机对象
AccelStepper stepperX(1, stepPinX, dirPinX);
AccelStepper stepperY(1, stepPinY, dirPinY);
AccelStepper stepperZ(1, stepPinZ, dirPinZ);

void setup() {
    Serial.begin(115200);

    // 设置速度和加速度
    stepperX.setMaxSpeed(400);
    stepperX.setAcceleration(200);
    
    stepperY.setMaxSpeed(400);
    stepperY.setAcceleration(200);
    
    stepperZ.setMaxSpeed(400);
    stepperZ.setAcceleration(200);
}

void loop() {
    // 同步移动三轴
    stepperX.moveTo(1000); // 向前移动1000步
    stepperY.moveTo(1000); // 同时向前移动1000步
    stepperZ.moveTo(1000); // 同时向前移动1000步

    while (stepperX.distanceToGo() != 0 || stepperY.distanceToGo() != 0 || stepperZ.distanceToGo() != 0) {
        stepperX.run();
        stepperY.run();
        stepperZ.run();
    }

    delay(1000); // 暂停1秒

    // 返回原点
    stepperX.moveTo(0);
    stepperY.moveTo(0);
    stepperZ.moveTo(0);

    while (stepperX.distanceToGo() != 0 || stepperY.distanceToGo() != 0 || stepperZ.distanceToGo() != 0) {
        stepperX.run();
        stepperY.run();
        stepperZ.run();
    }

    delay(1000); // 暂停1秒
}

要点解读
三轴运动控制:
所有示例展示了如何控制三轴步进电机的运动,包括 X、Y 和 Z 轴。通过设置每个电机的最大速度和加速度,实现平滑的运动。
加减速特性:
使用 setMaxSpeed() 和 setAcceleration() 方法设置每个电机的速度和加速度。这使得电机在启动和停止时能够平滑过渡,避免了突然的冲击,减少了机械磨损。
同步与顺序控制:
示例 2 和 3 展示了顺序和同步运动的实现。在顺序运动中,电机一个接一个地移动,而在同步运动中,所有电机同时移动到目标位置。根据需求选择合适的运动模式。
运动到目标位置:
使用 moveTo() 方法设置目标位置,并在循环中通过 run() 方法使电机逐步到达目标。distanceToGo() 方法用于检查电机是否到达目标位置。
延时与反馈:
每次运动完成后,代码通过 delay() 暂停一段时间,便于观察。可以通过串口输出当前状态,提供实时反馈,方便调试与监控。

在这里插入图片描述
4、基础三轴加减速控制

#include <AccelStepper.h>

// 定义步进电机引脚
const int stepPinX = 3;
const int dirPinX = 4;
const int stepPinY = 5;
const int dirPinY = 6;
const int stepPinZ = 7;
const int dirPinZ = 8;

// 创建步进电机对象
AccelStepper stepperX(AccelStepper::DRIVER, stepPinX, dirPinX);
AccelStepper stepperY(AccelStepper::DRIVER, stepPinY, dirPinY);
AccelStepper stepperZ(AccelStepper::DRIVER, stepPinZ, dirPinZ);

void setup() {
    stepperX.setMaxSpeed(1000); // 设置最大速度
    stepperY.setMaxSpeed(1000);
    stepperZ.setMaxSpeed(1000);

    stepperX.setAcceleration(500); // 设置加速度
    stepperY.setAcceleration(500);
    stepperZ.setAcceleration(500);
}

void loop() {
    // 向指定位置移动
    stepperX.moveTo(1000); // X轴移动1000步
    stepperY.moveTo(500);  // Y轴移动500步
    stepperZ.moveTo(250);  // Z轴移动250步

    // 逐步运行,直到到达目标位置
    while (stepperX.distanceToGo() != 0 || stepperY.distanceToGo() != 0 || stepperZ.distanceToGo() != 0) {
        stepperX.run();
        stepperY.run();
        stepperZ.run();
    }

    delay(1000); // 等待1秒

    // 反向移动
    stepperX.moveTo(-1000);
    stepperY.moveTo(-500);
    stepperZ.moveTo(-250);

    while (stepperX.distanceToGo() != 0 || stepperY.distanceToGo() != 0 || stepperZ.distanceToGo() != 0) {
        stepperX.run();
        stepperY.run();
        stepperZ.run();
    }
    
    delay(1000); // 等待1秒
}

要点解读:
三轴控制:通过创建三个AccelStepper对象控制三个步进电机,分别对应X、Y、Z轴。
加减速管理:使用setMaxSpeed()和setAcceleration()方法设置每个电机的最大速度和加速度,确保运动平滑。
目标位置移动:使用moveTo()方法设定目标位置,并通过run()方法逐步运行电机,保证运动的连续性。
反向运动:在到达目标后,设置反向运动,展示如何实现双向运动。
延时控制:在运动完成后使用delay()函数等待,便于观察运动效果。

5、动态调整速度与加速度

#include <AccelStepper.h>

const int stepPinX = 3;
const int dirPinX = 4;
const int stepPinY = 5;
const int dirPinY = 6;
const int stepPinZ = 7;
const int dirPinZ = 8;

AccelStepper stepperX(AccelStepper::DRIVER, stepPinX, dirPinX);
AccelStepper stepperY(AccelStepper::DRIVER, stepPinY, dirPinY);
AccelStepper stepperZ(AccelStepper::DRIVER, stepPinZ, dirPinZ);

void setup() {
    stepperX.setMaxSpeed(800);
    stepperY.setMaxSpeed(800);
    stepperZ.setMaxSpeed(800);

    stepperX.setAcceleration(400);
    stepperY.setAcceleration(400);
    stepperZ.setAcceleration(400);
}

void loop() {
    for (int i = 0; i < 5; i++) {
        // 循环移动到不同位置
        stepperX.moveTo(1000 + i * 200); // 每次移动增加200步
        stepperY.moveTo(500 + i * 100);
        stepperZ.moveTo(250 + i * 50);

        while (stepperX.distanceToGo() != 0 || stepperY.distanceToGo() != 0 || stepperZ.distanceToGo() != 0) {
            stepperX.run();
            stepperY.run();
            stepperZ.run();
        }

        // 动态调整速度
        stepperX.setMaxSpeed(800 - i * 100); // 每次降低最大速度
        stepperY.setMaxSpeed(800 - i * 100);
        stepperZ.setMaxSpeed(800 - i * 100);

        delay(1000); // 等待1秒
    }
}

要点解读:
动态调整:在每次运动后动态调整电机的最大速度,展示如何适应不同的运动需求。
循环运动:通过for循环多次移动到不同位置,增加代码的灵活性和可扩展性。
逐步平滑运动:在每个目标位置之间保持平滑运动,确保操作的精确性。
减速控制:通过逐步降低最大速度,展示如何在运动过程中控制电机的加减速特性。
简单逻辑:代码结构清晰,适合初学者理解动态调整速度和加速度的实现。

6、用户输入控制的三轴运动

#include <AccelStepper.h>

const int stepPinX = 3;
const int dirPinX = 4;
const int stepPinY = 5;
const int dirPinY = 6;
const int stepPinZ = 7;
const int dirPinZ = 8;

AccelStepper stepperX(AccelStepper::DRIVER, stepPinX, dirPinX);
AccelStepper stepperY(AccelStepper::DRIVER, stepPinY, dirPinY);
AccelStepper stepperZ(AccelStepper::DRIVER, stepPinZ, dirPinZ);

void setup() {
    Serial.begin(115200);
    stepperX.setMaxSpeed(1000);
    stepperY.setMaxSpeed(1000);
    stepperZ.setMaxSpeed(1000);

    stepperX.setAcceleration(500);
    stepperY.setAcceleration(500);
    stepperZ.setAcceleration(500);
}

void loop() {
    if (Serial.available() > 0) {
        String command = Serial.readStringUntil('\n'); // 读取用户输入的命令
        if (command.startsWith("X")) {
            int position = command.substring(1).toInt(); // 获取目标位置
            stepperX.moveTo(position); // 设置目标位置
        } else if (command.startsWith("Y")) {
            int position = command.substring(1).toInt();
            stepperY.moveTo(position);
        } else if (command.startsWith("Z")) {
            int position = command.substring(1).toInt();
            stepperZ.moveTo(position);
        }

        // 运行电机到达目标位置
        while (stepperX.distanceToGo() != 0 || stepperY.distanceToGo() != 0 || stepperZ.distanceToGo() != 0) {
            stepperX.run();
            stepperY.run();
            stepperZ.run();
        }
    }
}

要点解读:
用户输入控制:通过串口输入控制三轴运动,提供灵活的用户交互接口。
命令解析:使用String处理用户输入的命令,支持不同轴的独立控制。
动态目标设置:用户可以根据需要动态设置目标位置,增加操作的灵活性。
平滑运动:确保在设置目标后,电机平滑地运行到目标位置。
易于扩展:代码结构清晰,适合添加更多功能或控制更多轴的扩展。

总结
以上示例展示了如何使用Arduino实现平滑的三轴加减速运动。关键要点包括:
步进电机控制:使用AccelStepper库简化步进电机的控制,支持加减速功能。
动态调整:通过设置最大速度和加速度,使运动过程更加平滑和精确。
用户交互:通过串口输入实现用户对运动的控制,增加灵活性。
清晰的逻辑结构:代码结构简单明了,适合初学者理解三轴运动控制的基本实现。

注意,以上案例只是为了拓展思路,仅供参考。它们可能有错误、不适用或者无法编译。您的硬件平台、使用场景和Arduino版本可能影响使用方法的选择。实际编程时,您要根据自己的硬件配置、使用场景和具体需求进行调整,并多次实际测试。您还要正确连接硬件,了解所用传感器和设备的规范和特性。涉及硬件操作的代码,您要在使用前确认引脚和电平等参数的正确性和安全性。

在这里插入图片描述

### 关于在Arduino上使用LVGL库的示例教程 #### 示例代码解析 为了帮助理解如何在Arduino平台上利用LVGL库构建图形用户界面,下面提供了一个简单的`HelloWorld`实例。此例子展示了基本的初始化过程以及创建一个按钮的方法。 ```cpp #include "lvgl/lvgl.h" #include "lv_arduino.h" void setup() { Serial.begin(9600); // 初始化TFT屏幕和触摸屏 tft.init(); ts.begin(); // 初始化LVGL库 lv_init(); lv_disp_drv_t disp_drv; lv_disp_drv_init(&disp_drv); /*Basic display driver initialization*/ disp_drv.flush_cb = my_disp_flush; // 设置刷新回调函数 lv_disp_drv_register(&disp_drv); // 创建一个按钮并设置其属性 lv_obj_t * btn1 = lv_btn_create(lv_scr_act()); lv_obj_set_pos(btn1, 10, 10); /*Set its position*/ lv_obj_set_size(btn1, 120, 50); /*Set its size*/ // 给按钮添标签 lv_obj_t * label = lv_label_create(btn1); lv_label_set_text(label, "Button"); } void loop() { lv_task_handler(); /*Let the GUI do its work*/ delay(5); /*Sleep a bit not to waste resources*/ } ``` 这段代码首先包含了必要的头文件,并定义了`setup()`函数来完成硬件初始化工作[^2]。接着,在屏幕上创建了一个按钮对象,并通过调用`lv_btn_create()`方法将其放置到当前活动窗口中;之后调整位置大小并通过`lv_label_create()`给该按钮附加文字说明。最后,在主循环里不断更新GUI状态以响应事件处理程序。 #### 主要组件解释 - **lvgl/** 文件夹下存放着核心图形引擎及相关模块; - **examples/** 中有多个子目录分别对应不同类型的案例研究,比如最基础的`HelloWorld`入门级应用; - **libraries/** 收录了第方依赖项和其他支持包; - **tools/** 提供了一些实用工具,例如图像转换器等辅助开发的小应用程序[^5]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

驴友花雕

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值