04-04-2026-20-12
This commit is contained in:
parent
cb0ddffb95
commit
cce4c3d5b7
156
scr/MKS42C.cpp
156
scr/MKS42C.cpp
|
|
@ -0,0 +1,156 @@
|
||||||
|
#include "MKS42C.h"
|
||||||
|
|
||||||
|
MKS42C::MKS42C(HardwareSerial& serial, uint8_t address) {
|
||||||
|
_serial = &serial;
|
||||||
|
_addr = address;
|
||||||
|
_isMoving = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t MKS42C::calculateCRC(uint8_t* data, uint8_t len) {
|
||||||
|
// вычисление контрольной суммы
|
||||||
|
uint16_t checksum = 0;
|
||||||
|
for (uint8_t i = 0; i < len; i++) {
|
||||||
|
checksum += data[i];
|
||||||
|
}
|
||||||
|
return (uint8_t)(checksum & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MKS42C::sendRaw(uint8_t* data, uint8_t len) {
|
||||||
|
// отправить в порт
|
||||||
|
_serial->write(data, len);
|
||||||
|
_serial->write(calculateCRC(data, len));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MKS42C::clearBuffer() {
|
||||||
|
// очистить входящий буфер
|
||||||
|
while (_serial->available()) {
|
||||||
|
_serial->read();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MKS42C::setEnable(bool state) {
|
||||||
|
// вкл / выкл движка
|
||||||
|
uint8_t cmd[] = {_addr, 0xF3, (uint8_t)(state ? 0x01 : 0x00)};
|
||||||
|
sendRaw(cmd, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MKS42C::stop() {
|
||||||
|
// стоп
|
||||||
|
uint8_t cmd[] = {_addr, 0xF7};
|
||||||
|
sendRaw(cmd, 2);
|
||||||
|
_isMoving = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MKS42C::setHome() {
|
||||||
|
// задать текущую позицию, как 0 (сброс энкодера)
|
||||||
|
uint8_t cmd[] = {_addr, 0x34};
|
||||||
|
sendRaw(cmd, 2);
|
||||||
|
delay(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MKS42C::setTorque(uint16_t ma) {
|
||||||
|
// задать момент вращения
|
||||||
|
uint8_t cmd[] = {_addr, 0xAF, (uint8_t)((ma >> 8) & 0xFF), (uint8_t)(ma & 0xFF)};
|
||||||
|
sendRaw(cmd, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MKS42C::run(uint8_t dir, uint8_t speed) {
|
||||||
|
// просто включить
|
||||||
|
uint8_t val = ((dir & 0x01) << 7) | (speed & 0x7F);
|
||||||
|
uint8_t cmd[] = {_addr, 0xF6, val};
|
||||||
|
|
||||||
|
sendRaw(cmd, 3);
|
||||||
|
_isMoving = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MKS42C::rotateDegrees(float degrees, uint8_t speed) {
|
||||||
|
// включить на определённое количество гражут=сов
|
||||||
|
long pulses = (long)((degrees / 360.0) * 16384.0);
|
||||||
|
uint8_t dir = (pulses >= 0) ? 0x00 : 0x01;
|
||||||
|
uint32_t absP = abs(pulses);
|
||||||
|
|
||||||
|
uint8_t cmd[] = {
|
||||||
|
_addr,
|
||||||
|
0xFD,
|
||||||
|
(uint8_t)((dir << 7) | (speed & 0x7F)),
|
||||||
|
(uint8_t)((absP >> 24) & 0xFF),
|
||||||
|
(uint8_t)((absP >> 16) & 0xFF),
|
||||||
|
(uint8_t)((absP >> 8) & 0xFF),
|
||||||
|
(uint8_t)(absP & 0xFF)
|
||||||
|
};
|
||||||
|
sendRaw(cmd, 7);
|
||||||
|
_isMoving = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
float MKS42C::readPosition() {
|
||||||
|
// считать значение энкодера
|
||||||
|
clearBuffer();
|
||||||
|
uint8_t cmd[] = {_addr, 0x30};
|
||||||
|
sendRaw(cmd, 2);
|
||||||
|
|
||||||
|
unsigned long start = millis();
|
||||||
|
while (_serial->available() < 5 && millis() - start < 50);
|
||||||
|
|
||||||
|
if (_serial->available() >= 5) {
|
||||||
|
uint8_t buf[5];
|
||||||
|
_serial->readBytes(buf, 5);
|
||||||
|
|
||||||
|
uint16_t rawPos = (uint16_t)((buf[2] << 8) | buf[3]);
|
||||||
|
|
||||||
|
// Переводим в понятные градусы
|
||||||
|
return (rawPos * 360.0) / 16384.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
long MKS42C::readAbsolutePosition() {
|
||||||
|
// считать абсолютное значение энкодера
|
||||||
|
clearBuffer();
|
||||||
|
uint8_t cmd[] = {_addr, 0x31};
|
||||||
|
sendRaw(cmd, 2);
|
||||||
|
|
||||||
|
unsigned long start = millis();
|
||||||
|
while (_serial->available() < 6 && millis() - start < 100);
|
||||||
|
|
||||||
|
if (_serial->available() >= 6) {
|
||||||
|
uint8_t buf[6];
|
||||||
|
_serial->readBytes(buf, 6);
|
||||||
|
uint32_t rawPos = ((uint32_t)buf[2] << 24) | ((uint32_t)buf[3] << 16) |
|
||||||
|
((uint32_t)buf[4] << 8) | (uint32_t)buf[5];
|
||||||
|
return (buf[1] == 0) ? (long)rawPos : -(long)rawPos;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MKS42C::isBusy() {
|
||||||
|
// проверить движется ли мотор
|
||||||
|
if (_serial->available() >= 3) {
|
||||||
|
uint8_t buf[3];
|
||||||
|
if (_serial->peek() == _addr) {
|
||||||
|
_serial->readBytes(buf, 3);
|
||||||
|
if (buf[1] == 0x02) {
|
||||||
|
_isMoving = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _isMoving;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MKS42C::isBlocked() {
|
||||||
|
// проверить блокировку вала
|
||||||
|
clearBuffer();
|
||||||
|
uint8_t cmd[] = {_addr, 0x3A};
|
||||||
|
sendRaw(cmd, 2);
|
||||||
|
|
||||||
|
unsigned long start = millis();
|
||||||
|
while (_serial->available() < 3 && millis() - start < 50);
|
||||||
|
|
||||||
|
if (_serial->available() >= 3) {
|
||||||
|
uint8_t buf[3];
|
||||||
|
_serial->readBytes(buf, 3);
|
||||||
|
return (buf[1] == 0x02);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
87
scr/MKS42C.h
87
scr/MKS42C.h
|
|
@ -0,0 +1,87 @@
|
||||||
|
#ifndef MKS42C_H
|
||||||
|
#define MKS42C_H
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <HardwareSerial.h>
|
||||||
|
|
||||||
|
class MKS42C {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Конструктор класса
|
||||||
|
* @param serial Ссылка на объект HardwareSerial (например, Serial2)
|
||||||
|
* @param address UART адрес мотора (по умолчанию 0xE0)
|
||||||
|
*/
|
||||||
|
MKS42C(HardwareSerial& serial, uint8_t address = 0xE0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Включить или выключить удержание вала
|
||||||
|
* @param state true - включить (Enable), false - отключить (Disable)
|
||||||
|
*/
|
||||||
|
void setEnable(bool state);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Остановка двигателя
|
||||||
|
*/
|
||||||
|
void stop();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Установить текущую позицию как нулевую (Home)
|
||||||
|
* Данные записываются в EEPROM драйвера.
|
||||||
|
*/
|
||||||
|
void setHome();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Установка крутящего момента через ограничение тока
|
||||||
|
* @param ma Ток в миллиамперах (рекомендуется 0 - 2000)
|
||||||
|
*/
|
||||||
|
void setTorque(uint16_t ma);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Запустить непрерывное вращение
|
||||||
|
* @param dir Направление: 0 - CW (по часовой), 1 - CCW (против часовой)
|
||||||
|
* @param speed Скорость вращения (0 - 255)
|
||||||
|
*/
|
||||||
|
void run(uint8_t dir, uint8_t speed);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Поворот на определенное количество градусов
|
||||||
|
* @param degrees Угол (положительный или отрицательный)
|
||||||
|
* @param speed Скорость вращения (0 - 255)
|
||||||
|
*/
|
||||||
|
void rotateDegrees(float degrees, uint8_t speed);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Чтение текущей позиции вала (0-360 градусов)
|
||||||
|
* @return Позиция в градусах (float)
|
||||||
|
*/
|
||||||
|
float readPosition();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Чтение абсолютной позиции энкодера (с учетом полных оборотов)
|
||||||
|
* @return Количество импульсов (14-бит энкодер: 16384 на оборот при MStep 16)
|
||||||
|
*/
|
||||||
|
long readAbsolutePosition();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Проверка, завершил ли мотор движение (по команде rotateDegrees)
|
||||||
|
* @return true - мотор еще в пути, false - мотор остановился
|
||||||
|
*/
|
||||||
|
bool isBusy();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Проверка состояния защиты (блокировка вала)
|
||||||
|
* @return true - сработала защита (Protect), false - нормальная работа
|
||||||
|
*/
|
||||||
|
bool isBlocked();
|
||||||
|
|
||||||
|
private:
|
||||||
|
HardwareSerial* _serial;
|
||||||
|
uint8_t _addr;
|
||||||
|
bool _moving;
|
||||||
|
|
||||||
|
uint8_t calculateCRC(uint8_t* data, uint8_t len);
|
||||||
|
void sendRaw(uint8_t* data, uint8_t len);
|
||||||
|
void clearBuffer();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
Loading…
Reference in New Issue