Ардуинщики всех стран - объединяйтесь! В этом форуме, конечно.
Ответить

Arduino RS485 управление двигателем и обратная связь.

Чт окт 21, 2021 12:30:40

Доброго времени суток!
Не так давно занимаюсь электроникой и низкоуровневым программированием а с промышленными протоколами дела совсем не имел.
Есть двигатель он работает по протоколу rs-485, у меня связка ардуино уно + модуль rs-485 + мотор.

Я ним могу управлять и на него команды приходят, а вот обратной связи я добиться не могу. В тему добавлю код своего скетча.
Я не очень силен в работе с битами и регистрами, если есть хорошая литература которая даст понять как мне это все использовать - я буд только признательным. Потому что в данном протоколе есть старшие и младшие биты и я кое как понять как мне сделать скетч.

Добавлю фото с инструкцией к протоколу.
СпойлерИзображение
Изображение

Код:
const int PIN_DIR = 2;
byte servoID_1 = 0x01;
//byte servoALL = 0x
uint16_t a=0;
void setup() {

pinMode(PIN_DIR,OUTPUT);
Serial.begin(115200);

digitalWrite(PIN_DIR,LOW);
Serial.flush();


}

void loop() {

a = analogRead(A0);
a= map(a,0,1023,0,360);
delay(100);

//moveServo4(a);
torque(a);
 // moveServo_temp(a);
  //delay(1000);
 // torque_pol(0);
delay(1000); 
printBuffer();
//delay(2000); 


}



void printBuffer(){
  unsigned char buf[5];
  uint8_t tem[1];
  uint16_t volt[1];
  uint16_t sp[1];
  uint16_t enc[1];

 
 
  byte notchecksum = (0xDC);
  digitalWrite(PIN_DIR,HIGH);
  buf[0]=0x3E;
  buf[1]=0x9C;
  buf[2]=0x01;
  buf[3]=0x00;
  buf[4]=0xDB;
  Serial.write(buf,5);
  Serial.flush();
  digitalWrite(PIN_DIR,LOW);
  while(Serial.available()>0){
    tem[1]=Serial.read();
    delay(300);
    volt[1]=Serial.read();
    delay(300);
    sp[1]=Serial.read();
    delay(300);
    enc[1]=Serial.read();
    delay(300);
  }
   Serial.print(tem[1],HEX);
   Serial.print("  ");
  Serial.print(volt[1],HEX);
  Serial.print("  ");
  Serial.print(sp[1],HEX);
  Serial.print("  ");
  Serial.print(enc[1],HEX);
  Serial.print("  ");
  Serial.println("");
 
}

void torque(int Position){
  unsigned char buf[8];
  char Position_H = Position >> 8;
  char Position_L = Position % 256;
  byte notchecksum = (Position_L+Position_H);
  digitalWrite(PIN_DIR,HIGH);
  buf[0]=0x3E;
  buf[1]=0xA1;
  buf[2]=0x01;
  buf[3]=0x02;
  buf[4]=0xE2;
  buf[5]=Position_L;
  buf[6]=Position_H;
  buf[7]=notchecksum;
  Serial.write(buf,8);
  Serial.flush();
 
  delay(100);
  digitalWrite(PIN_DIR,LOW);
 
 
}
void moveServo(){
 
  digitalWrite(2,HIGH);
  delay(100);
  Serial.write(0x3E);
  Serial.write(0xA4);
  Serial.write(0x01);
  Serial.write(0x0C);
  Serial.write(0xEF);
  Serial.write(0x10);
  Serial.write(0x27);
  Serial.write(0x00);
  Serial.write(0x00);
  Serial.write(0x00);
  Serial.write(0x00);
  Serial.write(0x00);
  Serial.write(0x00);
  Serial.write(0xA0);
  Serial.write(0x8C);
  Serial.write(0x00);
  Serial.write(0x00);
  Serial.write(0x63);
  Serial.flush();
  digitalWrite(2,LOW);

  delay(100);
 
   
}

void moveServo4(int Position){
  char Position_H = Position >> 8;
  char Position_L = Position % 256;
  byte notchecksum = (Position_L+Position_H+0x00+0x00+0x00+0x00+0x00+0x00+0xA0+0x8C+0x00+0x00);
  //byte notchecksum = (0xA0+0x8C+0x00+0x00+0x00+0x00+0x00+0x00+0xA0+0x8C+0x00+0x00);

  digitalWrite(PIN_DIR,HIGH);
  delay(100);
  Serial.write(0x3E);
  Serial.write(0xA4);
  Serial.write(0x01);
  Serial.write(0x0C);
  Serial.write(0xEF);
  Serial.write(Position_H);                    // Serial.write(Position_L);
  Serial.write(Position_L);
  Serial.write(0x00);
  Serial.write(0x00);
  Serial.write(0x00);
  Serial.write(0x00);
  Serial.write(0x00);
  Serial.write(0x00);
  Serial.write(0xA0);
  Serial.write(0x8C);
  Serial.write(0x00);
  Serial.write(0x00);
  Serial.write(notchecksum);
  Serial.flush();
 

  delay(100);
  digitalWrite(2,LOW);
  //Serial.println(Position_H);
 // Serial.println(Position_L);
 
   
}

void moveServo2(){
  byte notchecksum = (0x00+0x00+0x00+0x00+0x00+0x00+0x00+0x00+0xA0+0x8C+0x00+0x00);
  digitalWrite(2,HIGH);
  delay(100);
  Serial.write(0x3E);
  Serial.write(0xA4);
  Serial.write(0x01);
  Serial.write(0x0C);
  Serial.write(0xEF);
  Serial.write(0x00);
  Serial.write(0x00);
  Serial.write(0x00);
  Serial.write(0x00);
  Serial.write(0x00);
  Serial.write(0x00);
  Serial.write(0x00);
  Serial.write(0x00);
  Serial.write(0xA0);
  Serial.write(0x8C);
  Serial.write(0x00);
  Serial.write(0x00);
  Serial.write(notchecksum);
  Serial.flush();
  digitalWrite(2,LOW);

  delay(100);
 
   
}

void moveServo3(){
 
  digitalWrite(2,HIGH);
  delay(100);
  Serial.write(0x3E);
  Serial.write(0xA4);
  Serial.write(0x01);
  Serial.write(0x0C);
  Serial.write(0xEF);
  Serial.write(0xA0);
  Serial.write(0x8C);
  Serial.write(0x00);
  Serial.write(0x00);
  Serial.write(0x00);
  Serial.write(0x00);
  Serial.write(0x00);
  Serial.write(0x00);
  Serial.write(0xA0);
  Serial.write(0x8C);
  Serial.write(0x00);
  Serial.write(0x00);
  Serial.write(0x58);
  Serial.flush();
  digitalWrite(2,LOW);

  delay(100);
 
   
}


void moveServo_temp(int Position){
  unsigned char ab;
  char Position_H = Position >> 8;
  char Position_L = Position % 256;
  byte notchecksum = (0x00+0x00+0x00+0x00+0x00+0x00+0x00+0x00+0x00+0x00+0x00+0x00+0x00);
  //byte notchecksum = (0xA0+0x8C+0x00+0x00+0x00+0x00+0x00+0x00+0xA0+0x8C+0x00+0x00);

  digitalWrite(2,HIGH);
  delay(100);
  Serial.write(0x3E);
  Serial.write(0xA4);
  Serial.write(0x01);
  Serial.write(0x07);
  Serial.write(0xEA);
  Serial.write(0x00);
  Serial.write(0x00);
  Serial.write(0x00);
  Serial.write(0x00);
  Serial.write(0x00);
  Serial.write(0x00);
  Serial.write(0x00);
  Serial.write(0x00);
  Serial.write(notchecksum);
  Serial.flush();
  digitalWrite(2,LOW);

  delay(100);
  //ab=Serial.read();
  //Serial.print("ab - ");
  //Serial.println(ab);
 
   
}

Re: Arduino RS485 управление двигателем и обратная связь.

Чт окт 21, 2021 13:22:29

Для чтения state вы передаете команду из 5 байт. DATA[4] - контрольная сумма, как она вычислялась (0xDB)? Наверное без правильной контрольной суммы ответа не будет.
Зачем массивы из одного элемента 16 бит?
Код:
 uint8_t tem[1];
 uint16_t volt[1];
 uint16_t sp[1];
 uint16_t enc[1];

Serial.read() принимает 1 байт (8 бит).
После команды чтения state должно быть получено 13 байт.
Сделать массив из 13 байт типа unsigned char rxbuf[13];
И принять можно типа так:
Код:
i = 0;
while(Serial.available()>0){
    rxbuf[i]=Serial.read();
    i++;
   if(i >=13) break;
  }

Потом разбирать байты на составляющие.
з.ы. мог и ошибиться - надо проверять

Re: Arduino RS485 управление двигателем и обратная связь.

Чт окт 21, 2021 13:30:54

RS-485 - это интерфейс, а не протокол.
Зачем столько сериалврайтов? Неужели нельзя передать по указателю на массив?
Тайминги между отправкой и приёмом надо выдерживать?

Re: Arduino RS485 управление двигателем и обратная связь.

Чт окт 21, 2021 13:45:15

Без корректной контрольной суммы ответа не будет.
Блок обработки на моторе со своей "головой" - про ту cheksum должно быть где-то описано - иначе и с управлением не справится.
Раз можете управлять - значит где-то уже расчет контрольного байта был (иначе и управление не пропустит).
:roll:
Напоминает вариации на тему интел хексов...
При соответствующей скорости можно на ходу анализировать как в парсере бутлоадера котуинки...
8)

Re: Arduino RS485 управление двигателем и обратная связь.

Чт окт 21, 2021 14:24:30

при управлении видно, какие то потуги с контрольной суммой проглядываются типа:
Код:
byte notchecksum = (0x00+0x00+0x00+0x00+0x00+0x00+0x00+0x00+0xA0+0x8C+0x00+0x00);
...
  Serial.write(0x8C);
  Serial.write(0x00);
  Serial.write(0x00);
  Serial.write(notchecksum);

это просто сумма и похоже может быть > 255, может такое и прокатит

Re: Arduino RS485 управление двигателем и обратная связь.

Чт окт 21, 2021 14:47:21

Может самый простой вариант - считается сумма всех байт, далее ее инверсия и +1 (дополнение до 2) как у интел хекса?
Для каждой строки КС своя должна быть.
8)

Re: Arduino RS485 управление двигателем и обратная связь.

Чт окт 21, 2021 14:48:23

Для чтения state вы передаете команду из 5 байт. DATA[4] - контрольная сумма, как она вычислялась (0xDB)? Наверное без правильной контрольной суммы ответа не будет.
Зачем массивы из одного элемента 16 бит?
Код:
 uint8_t tem[1];
 uint16_t volt[1];
 uint16_t sp[1];
 uint16_t enc[1];

Serial.read() принимает 1 байт (8 бит).
После команды чтения state должно быть получено 13 байт.
Сделать массив из 13 байт типа unsigned char rxbuf[13];
И принять можно типа так:
Код:
i = 0;
while(Serial.available()>0){
    rxbuf[i]=Serial.read();
    i++;
   if(i >=13) break;
  }

Потом разбирать байты на составляющие.
з.ы. мог и ошибиться - надо проверять



Спасибо буду пробовать, всегда решение где то на поверхности лежит. Сумму я считаю нормально, без сумм мотор бы не работал. там что в шапке сумма что в конце кадра.
Может есть какие то материалы или книги по теме байтов битов, старших, младших. потому что я доолго мучался с передачей данных в мотор, так как делятся на старший и младший биты.
Ответить