Mohammed Alaarag
New member
# مرحبا أصدقائي
###
**مشكلتي:**
**لا يتحرك محرك AK60-6 باستخدام Teensy 4.1 وCAN Bus**
أواجه مشكلة في تشغيل **محرك AK60-6** باستخدام **Teensy 4.1** و**جهاز الإرسال والاستقبال CAN SN65HVD230**.
لقد قمت سابقًا بتحميل الكود وتشغيل المحرك بنجاح باستخدام تطبيق الشركة المصنعة (**cubeMarstool_v1.32**)، لذا فإن المحرك يعمل بشكل جيد.
---
##
تفاصيل الاتصالات والرمز والإعدادات:
### **المكونات المستخدمة:**
- **لوحة التحكم:** Teensy 4.1
- **وحدة إرسال واستقبال CAN:** SN65HVD230
- **المحرك:** AK60-6
- **مصدر طاقة المحرك:** 24 فولت تيار مستمر (4 أمبير)
---
### **اتصالات Teensy 4.1 إلى SN65HVD230:**
- `3.3V` (من Teensy) → `VCC` (على SN65HVD230)
- `GND` (من Teensy) → `GND` (على SN65HVD230)
- `الدبوس 31` (Teensy TX) → `TXD` (على SN65HVD230)
- `الدبوس 30` (Teensy RX) → `RXD` (على SN65HVD230)
- `CANL` (من SN65HVD230) → `CANL` (على محرك AK60-6)
- **لا يتم عكس اتصالات CANH/CANL**
---
### **المقاومات النهائية:**
- يوجد **مقاومة 120 أوم** على نهاية CAN (على لوحة SN65HVD230 من الشركة المصنعة).
---
### **إعدادات المحرك والرمز:**
- **معرف المحرك:** تم ضبطه على `66` (عشري) باستخدام تطبيق cubeMarstool_v1.32.
في الكود، تم تعيينه على `0x42` (سداسي عشري).
- **معدل البود:** تم ضبطه على `500000 بت في الثانية (500 كيلوبت في الثانية)` في تطبيق المحرك،
وقد تم تعديل الكود ليتناسب باستخدام:
`can3.setBaudRate(500000);`
- **المكتبة المستخدمة:** `FlexCAN_T4` (مثبتة)
- **وضع التحكم:** يرسل الكود الأمر للدخول إلى وضع التحكم:
`0xFF FF FF FF FF FF FC`
---
##
العدد الحالي:
- **المحرك لا يزال لا يتحرك**.
- لا تظهر أخطاء واضحة في **الشاشة التسلسلية**، لكن المحرك لا يستجيب لأوامر الحركة.
---
##
طلب:
يرجى المساعدة في تحديد سبب عدم استجابة المحرك.
سأرفق **الكود المستخدم** و **صور الاتصال**.
[الرمز=cpp]```cpp
#تضمين <FlexCAN_T4.h>
FlexCAN_T4<CAN3، RX_SIZE_256، TX_SIZE_16> can3؛
// تعريف الحدود للمحرك AK60-6 (حسب الصفحة 4)
const float P_MIN = -12.5f; // راد (-95.5 درجة)
const float P_MAX = 12.5f; // راد (95.5 درجة)
ثابت عائم V_MIN = -41.87f؛ // راد/ثانية
ثابت عائم V_MAX = 41.87f؛ // rad/s
ثابت عائم T_MIN = -9.0f؛ // Nm
ثابت عائم T_MAX = 9.0f؛ // Nm
ثابت عائم KP_MIN = 0.0f؛
ثابت عائم KP_MAX = 500.0f؛
ثابت عائم KD_MIN = 0.0f؛
ثابت عائم KD_MAX = 5.0f؛
// دالة تتحول من float إلى uint (حسب الصفحة 6)
uint16_t float_to_uint(float x، float x_min، float x_max، uint8_t بت) {
مدى التعويم = x_max - x_min؛
إزاحة عائمة = x_min؛
العودة (uint16_t)((x - الإزاحة) * ((float)((1 << bits) - 1) / span));
}
// دالة تجهيز أمر CAN فطره للمحرك (حسب الصفحة 5)
void pack_cmd(CAN_message_t &msg، float p_des، float v_des، float kp، float kd، float t_ff) {
// تطبيق الحدود على القيم
p_des = constrain(p_des, P_MIN, P_MAX);
v_des = constrain(v_des, V_MIN, V_MAX);
kp = مقيد(kp، KP_MIN، KP_MAX)؛
kd = مقيد(kd، KD_MIN، KD_MAX)؛
t_ff = مقيد(t_ff، T_MIN، T_MAX)؛
// تحويل القيم إلى سجل سليمة بشكل مؤكد
uint16_t p_int = float_to_uint(p_des، P_MIN، P_MAX، 16)؛
uint16_t v_int = float_to_uint(v_des, V_MIN, V_MAX, 12);
uint16_t kp_int = float_to_uint(kp، KP_MIN، KP_MAX، 12)؛
uint16_t kd_int = float_to_uint(kd، KD_MIN، KD_MAX، 12)؛
uint16_t t_int = float_to_uint(t_ff، T_MIN، T_MAX، 12)؛
// تعبئة أقراص الرسالة CAN
msg.buf[0] = p_int >> 8؛
msg.buf[1] = p_int & 0xFF؛
msg.buf[2] = v_int >> 4؛
msg.buf[3] = ((v_int & 0xF) << 4) | (kp_int >> 8)؛
msg.buf[4] = kp_int & 0xFF؛
msg.buf[5] = kd_int >> 4؛
msg.buf[6] = ((kd_int & 0xF) << 4) | (t_int >> 8)؛
msg.buf[7] = t_int & 0xFF؛
}
إعداد باطل () {
التسلسل.البداية(115200);
تأخير(1000)؛
// تهيئة CAN بسرعة 1 ميجابت في الثانية (غيّرها إذا كنت تستخدم 500 كيلوبت في الثانية)
يمكن3.البدء();
can3.setBaudRate(1000000); // غيّر إلى 500000 إذا لزم الأمر
can3.enableFIFO();
can3.enableFIFOInterrupt();
// إرسال أمر الدخول في وضع التحكم
CAN_message_t أدخل عنصر التحكم؛
بالنسبة إلى (uint8_t i = 0؛ i < 7؛ i++) أدخل control.buf = 0xFF؛
أدخل control.buf[7] = 0xFC؛
enter_control.id = 0x42; // محرك الهوية
can3.write(أدخل التحكم)؛
Serial.println("تم محرك تهيئة AK60-6");
}
حلقة فارغة () {
موضع الهدف الثابت = 0.0f؛
أمر CAN_message_t؛
cmd.id = 0x42; // محرك الهوية
// إرسال أمر موضعي (90 درجة = 1.57 راديان)
pack_cmd(cmd، هدف الموضع، 0.0f، 40.0f، 0.5f، 0.0f)؛
can3.write(cmd);
// تغيير الموضع بين 0 و 90 درجة
هدف الموضع = (هدف الموضع == 0.0f) ؟ 1.57f : 0.0f؛
تأخير (2000)؛ // انتظر 2 ثانية
}
```[/CODE]
**شكرًا لك!**
###

**لا يتحرك محرك AK60-6 باستخدام Teensy 4.1 وCAN Bus**
أواجه مشكلة في تشغيل **محرك AK60-6** باستخدام **Teensy 4.1** و**جهاز الإرسال والاستقبال CAN SN65HVD230**.
لقد قمت سابقًا بتحميل الكود وتشغيل المحرك بنجاح باستخدام تطبيق الشركة المصنعة (**cubeMarstool_v1.32**)، لذا فإن المحرك يعمل بشكل جيد.
---
##

### **المكونات المستخدمة:**
- **لوحة التحكم:** Teensy 4.1
- **وحدة إرسال واستقبال CAN:** SN65HVD230
- **المحرك:** AK60-6
- **مصدر طاقة المحرك:** 24 فولت تيار مستمر (4 أمبير)
---
### **اتصالات Teensy 4.1 إلى SN65HVD230:**
- `3.3V` (من Teensy) → `VCC` (على SN65HVD230)
- `GND` (من Teensy) → `GND` (على SN65HVD230)
- `الدبوس 31` (Teensy TX) → `TXD` (على SN65HVD230)
- `الدبوس 30` (Teensy RX) → `RXD` (على SN65HVD230)
- `CANL` (من SN65HVD230) → `CANL` (على محرك AK60-6)
- **لا يتم عكس اتصالات CANH/CANL**
---
### **المقاومات النهائية:**
- يوجد **مقاومة 120 أوم** على نهاية CAN (على لوحة SN65HVD230 من الشركة المصنعة).
---
### **إعدادات المحرك والرمز:**
- **معرف المحرك:** تم ضبطه على `66` (عشري) باستخدام تطبيق cubeMarstool_v1.32.
في الكود، تم تعيينه على `0x42` (سداسي عشري).
- **معدل البود:** تم ضبطه على `500000 بت في الثانية (500 كيلوبت في الثانية)` في تطبيق المحرك،
وقد تم تعديل الكود ليتناسب باستخدام:
`can3.setBaudRate(500000);`
- **المكتبة المستخدمة:** `FlexCAN_T4` (مثبتة)
- **وضع التحكم:** يرسل الكود الأمر للدخول إلى وضع التحكم:
`0xFF FF FF FF FF FF FC`
---
##

- **المحرك لا يزال لا يتحرك**.
- لا تظهر أخطاء واضحة في **الشاشة التسلسلية**، لكن المحرك لا يستجيب لأوامر الحركة.
---
##

يرجى المساعدة في تحديد سبب عدم استجابة المحرك.
سأرفق **الكود المستخدم** و **صور الاتصال**.
[الرمز=cpp]```cpp
#تضمين <FlexCAN_T4.h>
FlexCAN_T4<CAN3، RX_SIZE_256، TX_SIZE_16> can3؛
// تعريف الحدود للمحرك AK60-6 (حسب الصفحة 4)
const float P_MIN = -12.5f; // راد (-95.5 درجة)
const float P_MAX = 12.5f; // راد (95.5 درجة)
ثابت عائم V_MIN = -41.87f؛ // راد/ثانية
ثابت عائم V_MAX = 41.87f؛ // rad/s
ثابت عائم T_MIN = -9.0f؛ // Nm
ثابت عائم T_MAX = 9.0f؛ // Nm
ثابت عائم KP_MIN = 0.0f؛
ثابت عائم KP_MAX = 500.0f؛
ثابت عائم KD_MIN = 0.0f؛
ثابت عائم KD_MAX = 5.0f؛
// دالة تتحول من float إلى uint (حسب الصفحة 6)
uint16_t float_to_uint(float x، float x_min، float x_max، uint8_t بت) {
مدى التعويم = x_max - x_min؛
إزاحة عائمة = x_min؛
العودة (uint16_t)((x - الإزاحة) * ((float)((1 << bits) - 1) / span));
}
// دالة تجهيز أمر CAN فطره للمحرك (حسب الصفحة 5)
void pack_cmd(CAN_message_t &msg، float p_des، float v_des، float kp، float kd، float t_ff) {
// تطبيق الحدود على القيم
p_des = constrain(p_des, P_MIN, P_MAX);
v_des = constrain(v_des, V_MIN, V_MAX);
kp = مقيد(kp، KP_MIN، KP_MAX)؛
kd = مقيد(kd، KD_MIN، KD_MAX)؛
t_ff = مقيد(t_ff، T_MIN، T_MAX)؛
// تحويل القيم إلى سجل سليمة بشكل مؤكد
uint16_t p_int = float_to_uint(p_des، P_MIN، P_MAX، 16)؛
uint16_t v_int = float_to_uint(v_des, V_MIN, V_MAX, 12);
uint16_t kp_int = float_to_uint(kp، KP_MIN، KP_MAX، 12)؛
uint16_t kd_int = float_to_uint(kd، KD_MIN، KD_MAX، 12)؛
uint16_t t_int = float_to_uint(t_ff، T_MIN، T_MAX، 12)؛
// تعبئة أقراص الرسالة CAN
msg.buf[0] = p_int >> 8؛
msg.buf[1] = p_int & 0xFF؛
msg.buf[2] = v_int >> 4؛
msg.buf[3] = ((v_int & 0xF) << 4) | (kp_int >> 8)؛
msg.buf[4] = kp_int & 0xFF؛
msg.buf[5] = kd_int >> 4؛
msg.buf[6] = ((kd_int & 0xF) << 4) | (t_int >> 8)؛
msg.buf[7] = t_int & 0xFF؛
}
إعداد باطل () {
التسلسل.البداية(115200);
تأخير(1000)؛
// تهيئة CAN بسرعة 1 ميجابت في الثانية (غيّرها إذا كنت تستخدم 500 كيلوبت في الثانية)
يمكن3.البدء();
can3.setBaudRate(1000000); // غيّر إلى 500000 إذا لزم الأمر
can3.enableFIFO();
can3.enableFIFOInterrupt();
// إرسال أمر الدخول في وضع التحكم
CAN_message_t أدخل عنصر التحكم؛
بالنسبة إلى (uint8_t i = 0؛ i < 7؛ i++) أدخل control.buf = 0xFF؛
أدخل control.buf[7] = 0xFC؛
enter_control.id = 0x42; // محرك الهوية
can3.write(أدخل التحكم)؛
Serial.println("تم محرك تهيئة AK60-6");
}
حلقة فارغة () {
موضع الهدف الثابت = 0.0f؛
أمر CAN_message_t؛
cmd.id = 0x42; // محرك الهوية
// إرسال أمر موضعي (90 درجة = 1.57 راديان)
pack_cmd(cmd، هدف الموضع، 0.0f، 40.0f، 0.5f، 0.0f)؛
can3.write(cmd);
// تغيير الموضع بين 0 و 90 درجة
هدف الموضع = (هدف الموضع == 0.0f) ؟ 1.57f : 0.0f؛
تأخير (2000)؛ // انتظر 2 ثانية
}
```[/CODE]
**شكرًا لك!**