Подскажите библиотеку для UART

lluceu
lluceu аватар
Offline
Зарегистрирован: 21.07.2020

Уважаемые форумчане, новичку требуется ваша помощь!
С ПК приходят такие команды строчкой для управления ШД:
MOVE Y (Y номер мотора, передвинуть на позицию заданную X)
SET X Y (Y номер мотора, X - позиция для этого мотора. Задаёт значения X для мотора Y)
MCAL Y (Y - номер мотора, двигает мотор до концевика и обнуляет X)
Вопрос: каким образом на принимающей ардуине можно принять эти строки и разбить на переменные?
p.s. это не грайвер и не 3D-принтер

MaksVV
Offline
Зарегистрирован: 06.08.2015

В конце строчки есть перевод строки и каретки? Если используете аппаратный UART библиотека не требуется. А парсинг пишется ручками

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

lluceu пишет:
принять эти строки и разбить на переменные?
Вам нужна библиотека для регулярных выражений? Вот, неплохая.

lluceu
lluceu аватар
Offline
Зарегистрирован: 21.07.2020

К сожалению не смог приспособить то что было там, пришлось что-то сделать самому. Оно вроде бы работает, но очень медленно и не совсем правильно. Можно вас попросить помочь с этим?
 

String Data = "";
String Otv1 = "MOVE";
String Otv2 = "SET";
String str = "";
String Y="";
String X="";
void setup() {
  Serial.begin(9600);
}
void loop() {
  while (Serial.available() > 0 && str!=" ") {
    str+= (char)Serial.read();
    if(str!=" "){
    Data +=str;
    str="";
    }
  }
  Serial.println(Data);
  if (Data == Otv1){
    while (Serial.available() > 0){
      Y += (char)Serial.read();
    }
    Serial.println(Y);
  }
  if (Data == Otv2){
    while (str!=" "){
      str+=(char)Serial.read();
      if(str!=" "){
      Y +=str;
      }
    }
    str="";
    Serial.println(Y);
    while (Serial.available() > 0){
      str+=(char)Serial.read();
      if(str!=" "){
      X +=str;
      }
    }
    str="";
    Serial.println(X);
  }
  delay(500);
  X=""; Y="";
  Data = "";
  str="";
}

Как писал выше, на ардуину может прийти две команды - MOVE Y и SET X Y
Где Y (1-3), а X(0-250). Как можно, желательно не создавая велосипедов, вынуть из пришедшей строки эти integer-ы ? 

lluceu
lluceu аватар
Offline
Зарегистрирован: 21.07.2020

Методом около-научного тыка выяснил, что "Y" вообще ничего не отправляет, всё отправляется через "X"..
 

String Data = "";
String Otv1 = "MOVE";
String Otv2 = "SET";
String Otv3 = "MCAL Y";
String str = "";
String Y="";
String X="";
void setup() {
  Serial.begin(9600);
}
void loop() {
  while (Serial.available() > 0 && str!=" ") {
    str+= (char)Serial.read();
    if(str!=" "){
    Data +=str;
    str="";
    }
  }
  Serial.println(Data);
  if (Data == Otv1){
    while (Serial.available() > 0){
      Y += (char)Serial.read();
    }
    Serial.println(Y);
  }
  if (Data == Otv2){
    while (str!=" "){
      str+=(char)Serial.read();
      if(str!=" "){
      Y +=str;
      }
    }
    str="";
    delay(20);
    Serial.println(Y);
    while (Serial.available() > 0){
      str+=(char)Serial.read();
      if(str!=" "){
      X +=str;
      }
    }
    str="";
    Serial.println(X);
    Serial.println(X); // добавил двойной вывод X
  }
  delay(500);
  X=""; Y="";
  Data = "";
  str="";
}

 

MaksVV
Offline
Зарегистрирован: 06.08.2015

А где ответ на #1 ?

Клапауций 9999
Offline
Зарегистрирован: 27.11.2020

MaksVV пишет:
А где ответ на #1 ?

ага... где-где - в лоно Родины... там исчи.

lluceu
lluceu аватар
Offline
Зарегистрирован: 21.07.2020

Благодарю за помощь, сильно увлёкся вашим ответом
 

String Data = "";
String str = "";
String Y="";
String X="";
String Z="";
void setup() {
  Serial.begin(9600);
}
void loop() {
  while (Serial.available() > 0 && str!=" ") {
    str+= (char)Serial.read();
    if(str!=" "){
    Data +=str;
    str="";
    }
  }
  str="";
  if(Data!=""){
  Serial.println(Data);
  }
  if (Data == "MOVE"){
    while (Serial.available() > 0){
      str+=(char)Serial.read();
      if(str!=" "){
      Y +=str;
      str="";
    }
    }
    delay(20);
    Serial.println(Y);
    str="";
  }
  if (Data == "SET"){
    while (Serial.available() > 0 && str!=" "){
      str+=(char)Serial.read();
      if(str!=" "){
      X +=str;
      str="";
    }
    }
    while (Serial.available() > 0 && str!=" "){
      str+=(char)Serial.read();
      if(str!=" "){
      Y +=str;
      str="";
    }
    str="";
  }
  Serial.println(X);
  Serial.println(Y);
  }
  if (Data == "MCAL"){
    while (Serial.available() > 0){
      str+=(char)Serial.read();
      if(str!=" "){
      Y +=str;
      str="";
    }
    }
    str="";
    delay(20);
    Serial.println(Y);
  }
  if (Data == "ACTIVATE"){
  while (Serial.available() > 0 && str!=" "){
    str+=(char)Serial.read();
    if(str!=" "){
    Y +=str;
    str="";
  }
  str="";
  }
  while (Serial.available() > 0){
    str+=(char)Serial.read();
    if(str!=" "){
    Z +=str;
    str="";
  }
  }
  str="";
  delay(20);
  Serial.println(Y);
  Serial.println(Z);
  }
  if (Data == "SILENT"){
  while (Serial.available() > 0 && str!=" "){
    str+=(char)Serial.read();
    if(str!=" "){
    Y +=str;
    str="";
  }
  str="";
  }
  delay(20);
  Serial.println(Z);
  if(Z=="0"){
    Serial.println("Off");
  }
  if(Z=="1"){
    Serial.println("On");
  }
  }
  delay(20);
  X=""; Y="";
  Data = "";
  str="";
}

Возник вопрос касаемо вот этого фрагмента:

  if (Data == "SILENT"){
  while (Serial.available() > 0 && str!=" "){
    str+=(char)Serial.read();
    if(str!=" "){
    Z +=str;
    str="";
  }
  str="";
  }
  delay(20);
  if(Z=="0"){
    Serial.println("Off");
  }
  if(Z=="1"){
    Serial.println("On");
  }
  }

Принимается строка до пробела, если принятое "SILENT" то начинает считывать дальше уже в этом цикле.
Но, считывает в String, а нужно что бы символы в строке переводились в число и записывались в переменную Integer intZ. В данном примере работает и так, но тут всего два числа, а вот здесь:

  if (Data == "SET"){
    while (Serial.available() > 0 && str!=" "){
      str+=(char)Serial.read();
      if(str!=" "){
      X +=str;
      str="";
    }
    }
    while (Serial.available() > 0 && str!=" "){
      str+=(char)Serial.read();
      if(str!=" "){
      Y +=str;
      str="";
    }
    str="";
  }
  Serial.println(X);
  Serial.println(Y);
  }

X - принимает значение от 0 до 100, не делать же * if(X==47) * 100 раз для каждого возможного числа? X - это значение для STEP/DIR драйвера ШД, и оно должно извлекаться из String в Integer, но я никак не могу понять, как сделать это преобразование String to Integer 

lluceu
lluceu аватар
Offline
Зарегистрирован: 21.07.2020

Чувствую себя сейчас очень тупым, но ещё летом с неделю потратил на то, что бы найти какое-то решение данной проблемы, но ничего тогда не нашёл, хотя всё решалось элементарно:
 

int intZ = Z.toInt();

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Ещё оптимальный использовать бинарный формат обмена, а не кодировать/парсить туда-сюда.

lluceu
lluceu аватар
Offline
Зарегистрирован: 21.07.2020

Можно подробнее в рамках моей задачи? Я смогу таким образом определять строки? Насколько это будет сложнее чем то, что уже сделано? Будет большая выгода по скорости исполнения кода?

sadman41
Offline
Зарегистрирован: 19.10.2016

Строки контроллеру вообще не нужны, он оперирует числами. Которые, в том числе, соответствуют образам букв, складывающимся в строки. 

Будет ли сложнее для понимания? Возможно.
Будет ли более быстро? Да, но Вы этого не заметите.
Будет ли стабильней? Определённо да - в условиях малого объёма RAM оперировать цифрами с известной размерностью правильней, чем строками с неизвестной.

MaksVV
Offline
Зарегистрирован: 06.08.2015
#define BUF_SIZE 30     // размер буфера парсилки
char currStr[BUF_SIZE]; // буфер парсилки  

const char MOVE[] = "MOVE";
const char SET[]  = "SET";
const char MCAL[] = "MCAL";

#define MOTOR_QUANTITY 5 // количество моторов

int x[MOTOR_QUANTITY+1] = {0};  // целевая координата движения мотора

#define X strstr(currStr, SET)+strlen(SET) // для парсинга числа из текста
#define Y strchr(X+1, ' ')                 // для парсинга числа из текста


//--------------------------------
void moveMotor (int motorNumber)
{
Serial.println (MOVE);
if  (!MotorCorrect(motorNumber)) return;
Serial.print ("Dvigaem motor ");  Serial.print (motorNumber);
Serial.print (" na koordinatu "); Serial.println (x[motorNumber]);
}

//--------------------------------
void MoveToEnd_Motor (int motorNumber)
{
Serial.println (MCAL);
if  (!MotorCorrect(motorNumber)) return;
x[motorNumber] = 0;
Serial.print ("Dvigaem motor "); Serial.print (motorNumber);
Serial.println (" na konez hoda. x=0"); 
}

//--------------------------------
void set()
{
  Serial.println (SET);  
  int motorNumber = atoi(Y);
  if  (!MotorCorrect(motorNumber)) return;
  x[motorNumber] = atoi (X); 
  Serial.print ("x = "); Serial.println (x[motorNumber]);
  Serial.print ("Motor #"); Serial.println (motorNumber);
}

//--------------------------------

bool MotorCorrect (int motorNumbeR)
{
if  (motorNumbeR>MOTOR_QUANTITY || motorNumbeR <= 0) {Serial.println ("Nomer motora zadan ne correctno!"); return 0;}
else return 1;
}
//--------------------------------
void BUS_read()
{
  if (!Serial.available()) return; // если данных нет игнорируем эту функцию
  char currSymb[2] = {0};
  currSymb[0] = Serial.read();  // читаем очередой 
  static bool stringEnd = 0;    // флаг переполнения буфера
if (currSymb[0] == '\r')        // если получили строку - парсим
  {
 
      if (strstr(currStr, MOVE)>0)  {moveMotor (atoi (strstr(currStr, MOVE)+strlen(MOVE)));} 
 else if (strstr(currStr, SET  )>0) {set ();}
 else if (strstr(currStr, MCAL )>0) {MoveToEnd_Motor (atoi (strstr(currStr, MCAL)+strlen(MCAL)));} 


 currStr[0] = 0; stringEnd = 0; // конце парсинга нулим буфер
  } 

// если не конец строки, то прибавляем очередной байт к буферу : 
else if ( currSymb[0] != '\n')  strcat (currStr,currSymb); 
// если буфер закончился , то режем строку на этом месте: 
     if (strlen(currStr)>=BUF_SIZE-2) {stringEnd = 1;}

}

//--------------------------------

void setup() 
{
 Serial.begin(9600);
}

void loop() 
{

BUS_read();
}


 

lluceu
lluceu аватар
Offline
Зарегистрирован: 21.07.2020

Сильно.. Спасибо! Сейчас буду сидеть, изучать ваш код

MaksVV
Offline
Зарегистрирован: 06.08.2015

есть ещё такой вариант)) причесал типа

#define BUF_SIZE 30     // размер буфера парсилки
char currStr[BUF_SIZE]; // буфер парсилки  

enum {MOVE, SET, MCAL}; 
const char comm[][6] = {"MOVE", "SET", "MCAL"};

#define MOTOR_QUANTITY 5            // количество моторов

int x[MOTOR_QUANTITY+1] = {0};      // целевая координата движения мотора

#define X sTr+strlen(comm[command]) // для парсинга числа из текста
#define Y strchr(pX(SET)+1, ' ')    // для парсинга числа из текста
 char *sTr;


int ATOI (byte command) {return (atoi(X));}

char *pX (byte command) {return (X);}

//--------------------------------
void moveMotor (int motorNumber)
{
 Serial.println (comm[MOVE]);
 if  (!MotorCorrect(motorNumber)) return; // если прилетел неправильный номер мотора, ругаемся и выходим
 Serial.print ("Dvigaem motor ");  Serial.print (motorNumber);
 Serial.print (" na koordinatu "); Serial.println (x[motorNumber]);
}

//--------------------------------
void MoveToEnd_Motor (int motorNumber)
{
 Serial.println (comm[MCAL]);
 if (!MotorCorrect(motorNumber)) return; // если прилетел неправильный номер мотора, ругаемся и выходим
 x[motorNumber] = 0;
 Serial.print ("Dvigaem motor "); Serial.print (motorNumber);
 Serial.println (" na konez hoda. x=0"); 
}

//--------------------------------
void set(int motorNumber)
{
 Serial.println (comm[SET]);  
 if (!MotorCorrect(motorNumber)) return;// если прилетел неправильный номер мотора, ругаемся и выходим
 x[motorNumber] = ATOI(SET); 
 Serial.print ("x = "); Serial.println (x[motorNumber]);
 Serial.print ("Motor #"); Serial.println (motorNumber);
}

//--------------------------------

bool MotorCorrect (int motorNumbeR)
{
 if  (motorNumbeR>MOTOR_QUANTITY || motorNumbeR <= 0) 
 {
  Serial.println ("Nomer motora zadan ne correctno!"); return 0;
 }
 else return 1;
}

//--------------------------------
void BUS_read()
{
  if (!Serial.available()) return; // если данных нет игнорируем эту функцию
  char currSymb[2] = {0};       // символьный кэш
  currSymb[0] = Serial.read();  // читаем очередной символ
  static bool stringEnd = 0;    // флаг переполнения буфера
if (currSymb[0] == '\r')        // если получили строку - парсим
  {


      if ((sTr =strstr(currStr, comm[MOVE]))>0) {moveMotor (ATOI(MOVE));} // если комманда MOVE
 else if ((sTr =strstr(currStr, comm[SET]  ))>0){set (atoi(Y));}          // если комманда SET
 else if ((sTr =strstr(currStr, comm[MCAL] ))>0){MoveToEnd_Motor (ATOI(MCAL));} // если комманда MCAL
 else Serial.println ("Commanda necorrectna!");

 currStr[0] = 0; stringEnd = 0; // в конце парсинга нулим буфер
  } 

// если не конец строки, то прибавляем очередной байт к буферу : 
else if ( currSymb[0] != '\n')  strcat (currStr,currSymb); 
// если буфер закончился , то режем строку на этом месте: 
     if (strlen(currStr)>=BUF_SIZE-2) {stringEnd = 1;}

}

//--------------------------------

void setup() 
{
 Serial.begin(9600);
}

void loop() 
{
BUS_read(); // функция чтения из UART
// тут остальной код
}

 

lluceu
lluceu аватар
Offline
Зарегистрирован: 21.07.2020

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

String Data = "";
String str = "";
String Y="";
String X="";
String Z="";
#include <GyverStepper.h>
GStepper<STEPPER2WIRE> CH1(800, 44, 42, 4);
GStepper<STEPPER2WIRE> CH2(800, 48, 46, 4);
GStepper<STEPPER2WIRE> CH3(800, 52, 50, 4);
void setup() {
  Serial.begin(115200);
  CH1.setMaxSpeed(500);
  CH1.setAcceleration(300);
  CH1.setRunMode(FOLLOW_POS);
  CH2.setMaxSpeed(500);
  CH2.setAcceleration(300);
  CH2.setRunMode(FOLLOW_POS);
}
int X1,X2,X3,Y1,Y2,Y3,intX,intY=0;
void loop() {
  while (Serial.available() > 0 && str!=" ") {
    str+= (char)Serial.read();
    if(str!=" "){
    Data +=str;
    str="";
    }
  }
  str="";
  if(Data!=""){
  Serial.println(Data);
  }
  if (Data == "MOVE"){
    while (Serial.available() > 0){
      str+=(char)Serial.read();
      if(str!=" "){
      Y +=str;
      str="";
    }
    }
    delay(20);
    Serial.println(Y);
    str="";
    if(Y=="1");
    CH1.setTarget(X1);
    }
    if(Y=="2"){
    CH2.setTarget(X2);
    }
    if(Y=="3"){
    CH3.setTarget(X3);
    }
  if (Data == "SET"){
    while (Serial.available() > 0 && str!=" "){
      str+=(char)Serial.read();
      if(str!=" "){
      X +=str;
      str="";
    }
    }
    while (Serial.available() > 0 && str!=" "){
      str+=(char)Serial.read();
      if(str!=" "){
      Y +=str;
      str="";
    }
    str="";
    delay(1000);
  }
  Serial.print(X);Serial.print(", ");Serial.print(Y);
    if(Y=="1"){
    X1 = X.toInt();
    Serial.print("CH1 = ");Serial.println(X1);
    }
    if(Y!="2"){
    X2 = X.toInt();
    Serial.print("CH2 = ");Serial.println(X2);
    }
    if(Y=="3"){
    X3 = X.toInt();
    Serial.print("CH3 = ");Serial.println(X3);
    }
  }
  if (Data == "MCAL"){
    while (Serial.available() > 0){
      str+=(char)Serial.read();
      if(str!=" "){
      Y +=str;
      str="";
    }
    }
    str="";
    delay(20);
    Serial.println(Y);
  }
  if (Data == "ACTIVATE"){
  while (Serial.available() > 0 && str!=" "){
    str+=(char)Serial.read();
    if(str!=" "){
    Y +=str;
    str="";
  }
  str="";
  }
  while (Serial.available() > 0){
    str+=(char)Serial.read();
    if(str!=" "){
    Z +=str;
    str="";
  }
  }
  str="";
  delay(20);
  Serial.println(Y);
  Serial.println(Z);
  }
  if (Data == "SILENT"){
  while (Serial.available() > 0 && str!=" "){
    str+=(char)Serial.read();
    if(str!=" "){
    Z +=str;
    str="";
  }
  str="";
  }
  delay(20);
  int intZ = Z.toInt();
  if(intZ==0){
    Serial.println("Off");
  }
  if(intZ==1){
    Serial.println("On");
  }
  }
  delay(20);
  X=""; Y=""; Z="";
  Data = "";
  str="";
}

Но я не понимаю одного момента:
 

if (Data == "SET"){
    while (Serial.available() > 0 && str!=" "){
      str+=(char)Serial.read();
      if(str!=" "){
      X +=str;
      str="";
    }
    }
    while (Serial.available() > 0 && str!=" "){
      str+=(char)Serial.read();
      if(str!=" "){
      Y +=str;
      str="";
    }
    str="";
    delay(1000);
  }
  Serial.print(X);Serial.print(", ");Serial.print(Y);
    if(Y=="1"){
    X1 = X.toInt();
    Serial.print("CH1 = ");Serial.println(X1);
    }
    if(Y!="2"){
    X2 = X.toInt();
    Serial.print("CH2 = ");Serial.println(X2);
    }
    if(Y=="3"){
    X3 = X.toInt();
    Serial.print("CH3 = ");Serial.println(X3);
    }
  }

После SET идёт X а за ним Y, но Y почему-то выводиться строго после проверки на условия, т.е. сначала пустая переменная Y проверяется на условия, а затем в неё парсятся данные из серийного порта, я не могу это объяснить, т.к. парсинг X и Y в моём коде одинаков.
Вот даже вставил Serial.print(Y); (если поставить Serial.println(Y); строка перенесётся на пустом месте после CH2 =) и ничего, парсит Y только после проверки на условия
Я не понимаю какой-то очевидной вещи, возможно даже в синтаксисе, но не могу понять какой именно..
Может мне кто-нибудь помочь?

sadman41
Offline
Зарегистрирован: 19.10.2016

Я тоже ничего не понял из объяснений, но сравните в последнем фрагменте строки 19 и 23 посимвольно. Это точно то, что вы хотели написать?

MaksVV
Offline
Зарегистрирован: 06.08.2015

lluceu пишет:
Спасибо, но я не силён в программировании, далее нужно так или иначе переделывать ваш код под себя, а я пока не владею теми элементами что вы использовали в своём коде. Поэтому принял решения дописать свой код из знакомых мне элементов.

А что не понятно то? Я специально везде комменты вставил, а там где их нет это Serial.print и так понятно что он делает. Вместо Serial.print или после него вставляете нужные вам действия вот и вся переделка.

А ваш код хоть сколь нибудь нормально работать не будет если будете кучу while и delay использовать. Про String я молчу. 

lluceu
lluceu аватар
Offline
Зарегистрирован: 21.07.2020

Да, я специально добавил  " != " что бы проверить, что в переменной действительно ничего нет. Вопрос лишь в том, почему ардуина начинает считывать Y из серийного порта только после проверки условий, хотя в коде она идёт намного раньше

lluceu
lluceu аватар
Offline
Зарегистрирован: 21.07.2020

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

MaksVV
Offline
Зарегистрирован: 06.08.2015

Ну вам виднее. Я будучи новичком старался прислушиваться к советам старожил

MaksVV
Offline
Зарегистрирован: 06.08.2015

lluceu пишет:
то как он работает в целом меня устраивает.

lluceu пишет:
В данный момент всё упёрлось именно в этот злосчастный "Y" распознавание которого почему-то происходит после проверки его на условия..

имхо, как то две фразы противоречат друг другу. Вы уж определитесь. 

MaksVV
Offline
Зарегистрирован: 06.08.2015

ТС, добавил твоего Гивера, если уж и здесь не разберешься, то увольте... комментов больше чем кода

ПС. из терминала команды слать в соответствии с постом #0. Не забываем ставить перевод строки и каретки и скорость 115200

#include <GyverStepper.h>

#define BUF_SIZE 30       // размер буфера парсилки
char currStr[BUF_SIZE+3]; // буфер парсилки  

enum {MOVE, SET, MCAL , COMMAND_QUANTITY};      // список команд
const char comm[][6] = {"MOVE", "SET", "MCAL"}; // массив строк команд

#define MOTOR_QUANTITY 3          // количество моторов

int x[MOTOR_QUANTITY] = {0};      // массив целевых координат движения моторов

// ниже создаем массив объектов моторов с количеством элементов, равным количеству моторов 
GStepper<STEPPER2WIRE> motor[MOTOR_QUANTITY] = 
  {
  GStepper<STEPPER2WIRE>(800, 44, 42, 4),     // мотор 1
  GStepper<STEPPER2WIRE>(800, 48, 46, 4),     // мотор 2
  GStepper<STEPPER2WIRE>(800, 52, 50, 4)      // мотор 3
  }; 

char *sTr; // для парсинга

//------------------------------функция исполнения команды
void runCommand(byte command)
{
  byte motorNumber = 0; 
 Serial.println (comm[command]); 
 // ниже парсим номер мотора из команды:
 if   (command != SET) motorNumber = atoi (sTr+strlen(comm[command]))-1;// если не SET то из первого числа
 else motorNumber = atoi(strchr(sTr+strlen(comm[command])+1, ' '))-1;   // если SET то из второго числа
 
 // если прилетел неправильный номер мотора, ругаемся и выходим:
 if  (motorNumber>MOTOR_QUANTITY-1 || motorNumber < 0) {Serial.println (F("Nomer motora zadan ne correctno!")); return;}
 
 Serial.print (F("Motor #")); Serial.print (motorNumber+1);
 if      (command == SET) {x[motorNumber] = atoi(sTr+strlen(comm[command]));} // если SET, то парсим позицию X для выбранного мотора
 else if (command == MCAL)
 {
 // здесь добавляем строки кода для движения мотора в крайнее положение, т.к. это команда MCAL
 
 x[motorNumber] = 0;  // нулим целевую координату соотвествующего мотора
 }
 else if (command == MOVE) {motor[motorNumber].setTarget(x[motorNumber]);} // если MOVE, двигаем нужный мотор на нужную позицию

      Serial.print (F("  x = ")); Serial.println (x[motorNumber]);
     
      if (command!=SET)    Serial.print (F("Dvigaem motor na"));  
      if (command == MCAL) Serial.println (F(" konez hoda")); 
 else if (command == MOVE) Serial.println (F(" koordinatu < x >")); 
 Serial.println();
}

//------------------------функция чтения информации из UART
void UART_read()
{
  if (!Serial.available()) return; // если данных нет игнорируем эту функцию
  char currSymb[2] = {0};          // символьный кэш
  currSymb[0] = Serial.read();     // читаем очередной символ
  static bool stringEnd = 0;       // флаг переполнения буфера

 if (currSymb[0] == '\r')          // если полностью получили строку - парсим:
 {
  bool commCorrect = 0;   // флаг найдена ли нужная команда
  
  // парсим все команды:
  for (int i=0; i<COMMAND_QUANTITY; i++) {if ((sTr =strstr(currStr, comm[i]))>0) {runCommand (i); commCorrect = 1; break;}}
  
  if (!commCorrect)Serial.println ("Commanda necorrectna!"); // поругаемся, если нет такой команды

  currStr[0] = 0; stringEnd = 0; // в конце парсинга нулим буфер
 } 

// если не конец строки, то прибавляем очередной байт к буферу : 
else if ( currSymb[0] != '\n')  strcat (currStr,currSymb); 
// если буфер закончился , то режем строку на этом месте: 
     if (strlen(currStr)>=BUF_SIZE) {stringEnd = 1;}

}

//--------------------------------

void setup() 
{
 Serial.begin(115200);
 // ниже настраиваем одинаковые параметры для всех моторов:
 for (int i =0; i<MOTOR_QUANTITY; i++)
 {
  motor[i].setMaxSpeed(500);
  motor[i].setAcceleration(300);
  motor[i].setRunMode(FOLLOW_POS);
 }
}

void loop() 
{
UART_read(); // функция чтения из UART
// тут остальной код
}

 

 

Bruzzer
Offline
Зарегистрирован: 17.03.2020

MaksVV пишет:

ТС, добавил твоего Гивера, если уж и здесь не разберешься, то увольте... комментов больше чем кода

Только код "кривой". (Он может и рабочий (не проверял), но "кривой").

Например переменная stringEnd присваивается в нескольких местах, и нигде не проверяется.

sadman41
Offline
Зарегистрирован: 19.10.2016

Осталась ли на свете хоть одна библиотека, которую гивер не засрал?

lluceu
lluceu аватар
Offline
Зарегистрирован: 21.07.2020

Сколько ардуиной пользовался, всегда только на костылях и выезжал. Примером своего кода вы открыли мне очень много дверей! Спасибо!!!)

lluceu
lluceu аватар
Offline
Зарегистрирован: 21.07.2020

А что с ним не так? В порт выводит всё как надо, правда мотор стоит, но я пока играюсь с только что освоенными функциями из его примера, думаю разберусь.

sadman41
Offline
Зарегистрирован: 19.10.2016

Как начнутся проблемы - идите на его форум, здесь понимания не найдете.

MaksVV
Offline
Зарегистрирован: 06.08.2015

Bruzzer пишет:
переменная stringEnd присваивается в нескольких местах, и нигде не проверяется.

согласен, это забыл добавить. Скетч на коленке писался, не для себя же, также код не проверял в работе, нету у меня шаговиков. А на счет Гивера это не ко мне. 

исправленный вариант

#include <GyverStepper.h>

#define BUF_SIZE 30       // размер буфера парсилки
char currStr[BUF_SIZE+3]; // буфер парсилки  

enum {MOVE, SET, MCAL , COMMAND_QUANTITY};      // список команд
const char comm[][6] = {"MOVE", "SET", "MCAL"}; // массив строк команд

#define MOTOR_QUANTITY 3          // количество моторов

int x[MOTOR_QUANTITY] = {0};      // массив целевых координат движения моторов

// ниже создаем массив объектов моторов с количеством элементов, равным количеству моторов 
GStepper<STEPPER2WIRE> motor[MOTOR_QUANTITY] = 
  {
  GStepper<STEPPER2WIRE>(800, 44, 42, 4),     // мотор 1
  GStepper<STEPPER2WIRE>(800, 48, 46, 4),     // мотор 2
  GStepper<STEPPER2WIRE>(800, 52, 50, 4)      // мотор 3
  }; 

char *sTr; // для парсинга

//------------------------------функция исполнения команды
void runCommand(byte command)
{
  byte motorNumber = 0; 
 Serial.println (comm[command]); 
 // ниже парсим номер мотора из команды:
 if   (command != SET) motorNumber = atoi (sTr+strlen(comm[command]))-1;// если не SET то из первого числа
 else motorNumber = atoi(strchr(sTr+strlen(comm[command])+1, ' '))-1;   // если SET то из второго числа
 
 // если прилетел неправильный номер мотора, ругаемся и выходим:
 if  (motorNumber>MOTOR_QUANTITY-1 || motorNumber < 0) {Serial.println (F("Motor number is not correct!")); return;}
 
 Serial.print (F("Motor #")); Serial.print (motorNumber+1);
 if      (command == SET) {x[motorNumber] = atoi(sTr+strlen(comm[command]));} // если SET, то парсим позицию X для выбранного мотора
 else if (command == MCAL)
 {
 // здесь добавляем строки кода для движения мотора в крайнее положение, т.к. это команда MCAL
 
 x[motorNumber] = 0;  // нулим целевую координату соотвествующего мотора
 }
 else if (command == MOVE) {motor[motorNumber].setTarget(x[motorNumber]);} // если MOVE, двигаем нужный мотор на нужную позицию

      Serial.print (F("  x = ")); Serial.println (x[motorNumber]);
     
      if (command!=SET)    Serial.print (F("Move motor to"));  
      if (command == MCAL) Serial.println (F(" end position")); 
 else if (command == MOVE) Serial.println (F(" position < x >")); 
 Serial.println();
}

//------------------------функция чтения информации из UART
void UART_read()
{
  if (!Serial.available()) return; // если данных нет игнорируем эту функцию
  char currSymb[2] = {0};          // символьный кэш
  currSymb[0] = Serial.read();     // читаем очередной символ
  static bool stringEnd = 0;       // флаг переполнения буфера

 if (currSymb[0] == '\r' || stringEnd == 1)   // если полностью получили строку - парсим:
 {
  bool commCorrect = 0;   // флаг найдена ли нужная команда
  
  // парсим все команды:
  for (int i=0; i<COMMAND_QUANTITY; i++) {if ((sTr =strstr(currStr, comm[i]))>0) {runCommand (i); commCorrect = 1; break;}}
  
  if (!commCorrect)Serial.println ("Command is not correct!"); // поругаемся, если нет такой команды

  currStr[0] = 0; stringEnd = 0; // в конце парсинга нулим буфер
 } 

// если не конец строки, то прибавляем очередной байт к буферу : 
else if ( currSymb[0] != '\n')  strcat (currStr,currSymb); 
// если буфер закончился , то режем строку на этом месте: 
     if (strlen(currStr)>=BUF_SIZE) {stringEnd = 1;}

}

//--------------------------------

void setup() 
{
 Serial.begin(115200);
 // ниже настраиваем одинаковые параметры для всех моторов:
 for (int i =0; i<MOTOR_QUANTITY; i++)
 {
  motor[i].setMaxSpeed(500);
  motor[i].setAcceleration(300);
  motor[i].setRunMode(FOLLOW_POS);
 }
}

void loop() 
{
for (int i =0; i<MOTOR_QUANTITY; i++) motor[i].tick(); 
UART_read(); // функция чтения из UART
// тут остальной код
}

 

MaksVV
Offline
Зарегистрирован: 06.08.2015

lluceu пишет:
правда мотор стоит

поправил, я в Гивере не разбирался, там в лупе добавил motor.tick();  наверное из этого не работал

MaksVV
Offline
Зарегистрирован: 06.08.2015

Bruzzer пишет:
Только код "кривой". (Он может и рабочий (не проверял), но "кривой")

а так жду более конструктивной критики

MaksVV
Offline
Зарегистрирован: 06.08.2015

sadman41 пишет:
Осталась ли на свете хоть одна библиотека, которую гивер не засрал?

Они киииборги, они заполонили...

lluceu
lluceu аватар
Offline
Зарегистрирован: 21.07.2020

Даа! Благодарю, теперь всё работает!!!

b707
Offline
Зарегистрирован: 26.05.2017

MaksVV пишет:

sadman41 пишет:
Осталась ли на свете хоть одна библиотека, которую гивер не засрал?

Они киииборги, они заполонили...

последний пипец - они там пишут теперь не более не менее чем "свое ядро для СТМ32". Я спросил - накуа??? - ответ гениален: "Чтобы удобные библиотеки Алекса(в смысле Гайвера) портировать на более мощную платформу"

Ничего святого у людей...

sadman41
Offline
Зарегистрирован: 19.10.2016

Зачем им более мощная платформа, если с его либами ардуина работает как пентиум 4?

Green
Offline
Зарегистрирован: 01.10.2015

Да потому что пудрят мозги неокрепшему организму. Народ ведь хавает что это "самое быстрое", "самое самое", а нафига, заради чего  - не понимает. Хотя не шарит и без этого.(

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

паматрел я код givertimers, ничего не изменилось

uint8_t _timer0_top = (_timer0_cycles < 256UL * 1024 ? (_timer0_cycles / _timer0_divider) : 256UL) ;
uint16_t _timer1_top = (_timer1_cycles < 65536UL * 1024 ? (_timer1_cycles / _timer1_divider) : 65536UL) ;
 
 
Green
Offline
Зарегистрирован: 01.10.2015

Тажело судить по этому фрагменту. Видно что выбирается максимум от (_timer0_cycles / _timer0_divider) и для 1 аналогично, и что?

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

А чего тут судить, если в uint8_t запихивается значение 256UL?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

sadman41 пишет:
Зачем им более мощная платформа, если с его либами ардуина работает как пентиум 4?
А тут будет как амд "бульдозер"
b707 пишет:
"Чтобы удобные библиотеки Алекса(в смысле Гайвера) портировать на более мощную платформу"
Это нормальное поведение жрецов любого бога - расширять зоны влияния своей религии, обращать язычников в истинную веру. Нормально.

Green
Offline
Зарегистрирован: 01.10.2015

andriano пишет:

А чего тут судить, если в uint8_t запихивается значение 256UL?


Согласен. С наскоку не заметил.(