基于Arduino ESP32 的 CAD Controller Design for Siemens NX 11 (上篇)

基于Arduino ESP32 的 CAD Controller Design for Siemens NX 11 (上篇)

背景介绍

对于长期从事CAD建模的同学来说,为了从不同角度观察3D模型,“旋转”,“缩放” 是使用率最高的操作。而对于常用的滚轮鼠标而言因其“滚轮中键”向下按压时操作面太小,长时间点击容易患上“鼠标手”,笔者在之前从事产品设计过程中深受其扰。

近期在自学Arduino后,萌生了自己做一个用于CAD 建模的控制器。Prototype 的构思源于摇杆及旋转编码器的示例程序。感兴趣的同学可以将此拓展到CATIA 上应用。

项目期间参考了,Li-Yongjun 的《ESP32 EC11 制作电脑音量调节旋钮》,

[https://blog.csdn.net/lyndon_li/article/details/124564530?utm_medium=distribute.pc_relevant.none-task-blog-2defaultbaidujs_baidulandingword~default-5-124564530-blog-137572167.235v43

稚晖君的 “【瀚文】HelloWord-Keyboard”

[https://oshwhub.com/pengzhihui/b11afae464c54a3e8d0f77e1f92dc7b7]:

感谢大佬们的开源贡献!
项目分为上、下两篇,本部分为上篇。

1. 硬件选型及设计

1.1 PS2 摇杆模块

PS2 摇杆模块,共有3路输出:VRx, VRy,SW。

其中VRx, VRy为模拟量,其实质为电位器输出端的电压值,需接AD口;

其中SW为数字量,接数字口。VRx, VRy经ESP32 AD 转换后输出数值,数据类型为int。
[摇杆模块]
在这里插入图片描述
[摇杆模块原理图及Proteus仿真,该模块的全值电阻为4.5K]
在这里插入图片描述

1.2 EC11 旋转编码器模块

旋转编码器的是一种位置传感器,用于确定旋转轴的角位置。它根据旋转运动生成模拟或数字信号,旋转编码器有许多不同类型,它们根据输出信号或传感技术进行分类。本方案采用的是一种低成本的触点电刷增量式旋转编码器,它是测量旋转最简单的传感器。
本项目中,旋转编码器是用于替代鼠标的滚轮,用于3D建模“缩小”,“放大”操作。

1.2.1 工作原理

详见B站,【旋转编码器如何工作以及如何与Arduino一起使用[How To Mechatronics]】https://www.bilibili.com/video/BV1JJ411s7p3?p=2&vd_source=37fd58933b54ae0d29f796611848ad70
其工作原理,如下所示:

EC11 Encoder-原理

1.2.2 引脚定义

在这里插入图片描述
CLK: CLK(Clock):这是编码器的主要输出脉冲信号,用于确定旋转的数量。每当旋钮向任一方向转动一个触点,CLK输出会经历一次从高电平到低电平的周期变化。
DT: DT(Data or Direction):这是类似于CLK输出的信号,但它比CLK信号滞后90°的相位。这个输出用于确定旋转的方向。当编码器逆时针旋转时,DT输出逻辑低电平;当编码器顺时针旋转时,DT输出逻辑高电平。
SW: 按键输出端口
+: 电源+
GND: 电源-
CLK和DT信号通常通过相位差来确定旋转的方向。例如,如果CLK信号在下降沿时(电平由高变低),而DT信号是高电平,则表示顺时针旋转;如果DT信号是低电平,则表示逆时针旋转。

1.2.3 电路原理图

在这里插入图片描述

1.3 按键

按键的工作原理简单,不再赘述。本项目中按键用于替代“鼠标中键的向下按键”,实现在3D建模的过程中旋转模型的部分操作。
为了规避按键的抖动,采用上拉电阻接入,按键不触发时,保持高电平,电路原理图如下:
在这里插入图片描述

2.程序设计

源代码如下:

// CAD Controller Design for  Siemens NX 11 
// Auth:Hope.Zhu  Sep/10/2024
// REV :00

// 预编译第三方库文件
#include <BleCombo.h>  
#include "EC11.hpp"
#include "OneButton.h"
EC11 encoder;

// Polling allows to use the encoder with any digital input pin.
const int encoderPinA = 17;  //EC11 引脚A
const int encoderPinB = 16;  //EC11 引脚B
//const int EC11_SW_Pin = 4;   //EC11 引脚SW 停用,不好操作

// 摇杆
const int X_Pin = A4;  // X向的输入,其实质是电位器经AD转换后的电压信号
const int Y_Pin = A5;  // Y向的输入, 同上

// 独立按键
const int SW_Pin = 14;  //

// LED 状态指示灯,用于调试过程中观察状态的变化
const int LEDPin1 = 13;   // CW 旋转指示
const int LEDPin2 = 27;   // C.C.W 旋转指示
const int LEDPin3 = 2;    // 蓝牙连接状态指示灯
const int LEDPin4 = 26;	  // 摇杆指示灯,X+
const int LEDPin5 = 15;   // 摇杆指示灯,X-
const int LEDPin6 = 25;   // 摇杆指示灯,Y+
const int LEDPin7 = 12;   // 摇杆指示灯,Y-

OneButton button(SW_Pin, true);  // 独立按键,

void setup() {
  Serial.begin(115200);
  Serial.println("Starting CAD Controller work!");
  Keyboard.begin();
  Mouse.begin();

  // 编码器,C PIN 为公共端
  pinMode(encoderPinA, INPUT_PULLUP);  
  pinMode(encoderPinB, INPUT_PULLUP);

  analogSetWidth(10);  // 设置采样分辨率

  pinMode(X_Pin, INPUT);
  pinMode(Y_Pin, INPUT);
  pinMode(SW_Pin, INPUT_PULLUP);  
  digitalWrite(SW_Pin, HIGH);    

  pinMode(LEDPin1, OUTPUT);
  digitalWrite(LEDPin1, HIGH); // LEDPin1共阳极,初始化置高电平熄灭
  pinMode(LEDPin2, OUTPUT);
  digitalWrite(LEDPin2, HIGH); // LEDPin2共阳极,初始化置高电平熄灭
  pinMode(LEDPin3, OUTPUT);
  pinMode(LEDPin4, OUTPUT);
  pinMode(LEDPin5, OUTPUT);
  pinMode(LEDPin6, OUTPUT);
  pinMode(LEDPin7, OUTPUT);
 
  // link functions to be called on events.
  button.attachLongPressStart(LongPressStart, &button);
  button.attachDuringLongPress(DuringLongPress, &button);
  button.attachLongPressStop(LongPressStop, &button);
  button.setLongPressIntervalMs(500);
}

void loop() {
  if (Keyboard.isConnected()) {
    button.tick();
    Rocker_Switch();
    // 旋转编码器代码不够优雅,可以后续封装成函数
    EC11Event e;
    if (encoder.read(&e)) {
      blinkLED(LEDPin3);
      // OK, got an event waiting to be handled.
      if (e.type == EC11Event::StepCW) {  // 顺时针
        Serial.println("Scroll Down");
        Mouse.move(0, 0, -5);          //(X向,Y向,滚轮),此处只控制滚轮
        Serial.println("- - -");
        blinkLED2(LEDPin1);       

      } else {  // 逆时针
        Serial.println("Scroll Up");
        Mouse.move(0, 0, 5);
        Serial.println("+ + +");
        blinkLED2(LEDPin2);
      }
    } else {
      //Serial.println("not connected");
    }
  }

  // With polling-style pin checking we can still read infrequently, but we need to poll the pins often enough.
  for (int i = 0; i < 10; i++) {
    encoder.checkPins(digitalRead(encoderPinA), digitalRead(encoderPinB));
    delay(1);
  }
}

// 共阴极LED模块闪烁
void blinkLED(int ledPin) {
  digitalWrite(ledPin, HIGH);
  delay(10);
  digitalWrite(ledPin, LOW);  
}

// 共阳极LED模块闪烁
void blinkLED2(int ledPin) {
  digitalWrite(ledPin, LOW);
  delay(10);
  digitalWrite(ledPin, HIGH);  
}

// 摇杆模块
void Rocker_Switch() {
  int X_Val = analogRead(X_Pin)/4;  // AD 转换后的X_Val 模拟值, /4 防溢出
  //Serial.print("X_Val:");			// 调试时用于观察输出量
  //Serial.println(X_Val);
  int Y_Val = analogRead(Y_Pin)/4;  // AD 转换后的Y_Val 模拟值,/4 防溢出
  //Serial.print("Y_Val:");       	// 调试时用于观察输出量
  //Serial.println(Y_Val);
  // int C_Val= 2900;             	// 摇杆的中值 (需根据实际输出量调整)
  // int P_Val=200;               	// 摇杆的偏移量 (需根据实际输出量调整)
  int H_Val = 850;               	//C_Val + P_Val ;     // 摇杆的 上阈值
  int L_Val = 650;               	//C_Val + P_Val ;     // 摇杆的 下阈值

  if (X_Val > H_Val) {  // 水平移动
    //Keyboard.write(KEY_RIGHT_ARROW);  //用于后续开发模式2,控制键盘按键
    Mouse.move(25, 0, 0);         		// 移动量根据个人使用习惯调整
    delay(20);
    blinkLED(LEDPin4);
    Serial.println("--->");
  } else if (X_Val < L_Val) {
    //Keyboard.write(KEY_LEFT_ARROW);  //用于后续开发模式2,控制键盘按键
    Mouse.move(-25, 0, 0);
    delay(20);
    blinkLED(LEDPin5);
    Serial.println("<---");
  }

  if (Y_Val > H_Val) {
    //Keyboard.write(KEY_UP_ARROW);   //用于后续开发模式2,控制键盘按键
    Mouse.move(0, 25, 0);
    //Mouse.release(MOUSE_MIDDLE);
    delay(20);
    blinkLED(LEDPin6);
    Serial.println("^^^");
  } else if (Y_Val < L_Val) {
    //Keyboard.write(KEY_DOWN_ARROW); //用于后续开发模式2,控制键盘按键
    Mouse.move(0, -25, 0);
    delay(20);
    blinkLED(LEDPin7);
    Serial.println("$$$");
  }
}


// this function will be called when the button started long pressed.
void LongPressStart(void *oneButton)
{
  Serial.print(((OneButton *)oneButton)->getPressedMs());
  Serial.println("\t - LongPressStart()");
}

// this function will be called when the button is released.
void LongPressStop(void *oneButton)
{
  Serial.print(((OneButton *)oneButton)->getPressedMs());
  Serial.println("\t - LongPressStop()\n"); 
  Mouse.release(MOUSE_MIDDLE);
}

// this function will be called when the button is held down.
void DuringLongPress(void *oneButton)
{
  Serial.print(((OneButton *)oneButton)->getPressedMs());
  Serial.println("\t - DuringLongPress()");
  Mouse.press(MOUSE_MIDDLE);
}

// End

3.演示动画

3.1 EC11 控制PDF 文档/网页,翻页

在这里插入图片描述

3.2 摇杆及按键控制 Siemens NX 11 3D 模型旋转 (需先设置好旋转点)

在这里插入图片描述

3.3 EC11 控制 Siemens NX 11 3D 模型缩放

在这里插入图片描述

4 结构设计(待下篇更新)

待人体工学DEMO验证完后更新…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值