Счетчик длины кабеля, сделать умным и связать с ПК

exclus
Offline
Зарегистрирован: 10.09.2016

Добрый день, уважаемые форумчане.

Имеется вот такой 

ИДМ-20. Измеритель длины кабеля http://www.smol-kabel.ru/index.php?module=catalog&show=fulldesc&id=64&item=385

Задача: Заменить счетчик на ардуино + ПК

ТЗ к ардуино:

1. Подключить  индуктивные датчики от счетчика. (два цифровы пина)

2. Подключить  6 исполнительных механизмов. (мотор (М), красный краситель (R), зеленный краситель (G), желтый краситель ( Y),  резак (С), cигнал готово (S))

Алгоритм работы следующий: 

Есть переменные a=0 (полученная от ПК длина кабеля) и b=0 (измеренная длина кабеля)

Ардуино получает по uart с ПК строку ввида: "5;R;15;G;35;C"

Ардуино записывает а=5

Работает условие если a>b включить (М) , влючается мотор начинает мотаться кабель через счетчик (в счетчике два индуктивных сенсора) он считает в обе стороны.

Как только a=b, выключается (М), ардуино отправляет значие "b" в uart  фразой (5 м, ok) , считает следущее значение из порта R и включает касный краситель (время сработки задаем в сетапе), ардуино отправляет в uart  фразой (Red, ok) 

Читает дальше 15, записавает а=а+15

Работает условие если a>b включить (М) , влючается мотор начинает мотаться кабель через счетчик (в счетчике два индуктивных сенсора) он считает в обе стороны.

Как только a=b, выключается (М), ардуино отправляет значие "b" в uart  фразой (20 м, ok) , считает следущее значение из порта G и включает зеленный краситель (время сработки задаем в сетапе), ардуино отправляет в uart  фразой (  Green, ok) 

Читает дальше 35, записавает а=а+35

Работает условие если a>b включить (М) , влючается мотор начинает мотаться кабель через счетчик (в счетчике два индуктивных сенсора) он считает в обе стороны.

Как только a=b, выключается (М), ардуино отправляет значие "b" в uart  фразой (55 м, ok) , считает следущее значение из порта C и включает резак (время сработки задаем в сетапе), ардуино отправляет в uart  фразу (Сut, ok),

Ардуино обнуляет а=0 и b=0, ардуино замыкает сигнал готово S и отправляет в uart  фразу (Ready)

После того как ПК получил (сигнал, или ready в com port, то он отдается следующую стороку "10;R;4;R;5;G;10;R;25;C"

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

 

exclus
Offline
Зарегистрирован: 10.09.2016

Жду предложений по цене реализации скетча. Возможны вопросы по схемотехнике, подключение оконечных устройств.

Gippopotam
Gippopotam аватар
Offline
Зарегистрирован: 12.09.2014

exclus пишет:

Жду предложений по цене реализации скетча. Возможны вопросы по схемотехнике, подключение оконечных устройств.

Есть вопросы и по подключению и по конструктиву.

ПК - это вообще обязательное условие?

StudioGippopotam@gmail.com

exclus
Offline
Зарегистрирован: 10.09.2016

ПК не обязательно, это может быть планшет, обязательно прочитать строку из uart

Onkel
Offline
Зарегистрирован: 22.02.2016

есть несколько вопросов, но сделать могу конечно независимо от ответов, ответы могут влиять лишь на цену

1 uart штука такая не очень помехоустойчивая, я обычно делаю связь с пк через Rs485, но если комп близко и продублировать передачу данных, можно и на uart оставить. В то же время интерфейсы rs485/usb cтоит столько же, сколько интерфейс  uart/usb

2 У меня есть платы входов / выходов в индустриальном исполнении, на дин рейку, с защитами входов и выходами как в виде реле, так и мосфитов, ну есть и на симисторах - но это не тот случай. Что является нагрузкой контроллера - достаточно ттл сигналов или нужно коммутировать 220, или 12/ 24 В оборудование? Вот примеры модулей

http://uniel.ru/catalog/1639

 

но можно и на ардуино, хотя в промышленности аруиновские штыречки и шильдики не очень надежная штука

3 Мой адрес ydom@mail.ru , связывайтесь, когда будут ответы на вопросы 1-2 смогу посчитать. Большой опыт работы с АСУ ТП и МАХП, могу сделать программы на честном С, без ардуиновских костылей и тормозов, в том числе и на железе ардуино, если нужно строго на ардуино. Будет надежно.

exclus
Offline
Зарегистрирован: 10.09.2016

Ваши железки знаю, но задача очень простая для таких мощностей. ПК будет рядом. Сейчас мысль собрать рабочий прототип. Обвязку сделать смогу сам или почти сам. Основная задача скетч !!! Можно сделать проверку, получения данных ардуиной, что бы она посылала например "start" в уарт как только получила строку. А ПК бы слал строку с периодичстью пока не увидет start, на пример.

 

Onkel
Offline
Зарегистрирован: 22.02.2016

exclus пишет:

Ваши железки знаю, но задача очень простая для таких мощностей. ПК будет рядом. Сейчас мысль собрать рабочий прототип. Обвязку сделать смогу сам или почти сам. Основная задача скетч !!! Можно сделать проверку, получения данных ардуиной, что бы она посылала например "start" в уарт как только получила строку. А ПК бы слал строку с периодичстью пока не увидет start, на пример.

обычно проверку делают так- включают во все посылки контрольную сумму, и по получении сигнала посылат подтверждение. Поскольку намотка проволоки- не шибко быстрое действо, в вашем случае и подтверждение, и контрольные суммы предусмотреть можно.

Скетч так скетч, отпишите, я посчитаю сколько будет стоить. Но конечно хорошо бы на С, чтобы хотя бы прерывание по получению байта иметь, в arduino ide придется все время проверять, не пришел ли байт, или городить прерывание по изменению состояния пина D0, что чревато потерей байта, с ненулевой вероятностью, поэтому и рекомендую и контрольную сумму, и подтверждение. А то компрессор включат в соседнем цеху - и ваш аппарат отмотает на полную! Так что отработку неподтверждения тоже надо включить в код.

Ну адрес напомню ydom@mail.ru

pcb
Offline
Зарегистрирован: 02.04.2015

от 30 т.р. хекс прошивка для процессора, но это будет не ардуиностайл, а вполне пром. исполнение.

PCBADM на мэйлру.

Можете ознакомиться с некоторым количеством железа

exclus
Offline
Зарегистрирован: 10.09.2016

Дорого, спасибо, может когда и буду промышленный образец делать, тогда и обращусь ))

exclus
Offline
Зарегистрирован: 10.09.2016

Информация по счетчику который сейчас стоит на колесе http://www.smol-kabel.ru/files/SMOL_counter_id-2_200410.pdf

Датчики при попадании на дырку в колесе выдают +12v, потом на схеме стоит делитель напряжения на резисторах и уже atmega 16a все хавает.

В счетчике есть какой-то умножитель энкриментов,програмно аппаратный, так что потребуются математические функции какие-то.

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

Сделаю на Ардуино, недорого. Пишите htpicc@gmail.com, обсудим.

pcb
Offline
Зарегистрирован: 02.04.2015

exclus пишет:

Дорого, спасибо, может когда и буду промышленный образец делать, тогда и обращусь ))

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

exclus
Offline
Зарегистрирован: 10.09.2016

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

pcb
Offline
Зарегистрирован: 02.04.2015

Вообще без проблем :)
Заказов у меня хватит до след кризиса(2018).

А так были свои моталки, красилки, отрезалки и для маленьких проводов, и здоровенных кабелей. Поэтому подобные проекты далеко не тайна.

Надумаете - аре велком.

exclus
Offline
Зарегистрирован: 10.09.2016

Всем добрый день.

В связи с тем, что не получилось найти соотоношение цены и желаемого результата была произведена собственная работа.

Что получилось: Счетчик считает с точность 0,01 метр = как заводской, умеет принимать поочередно одну заданную длину из seriala, суммировать полученные длины, включать выключать мотор, сбрасывать показания.

Что не получается: 

Получение по Serial строики вида "5;R;15;G;35;C" (желательно произвольной длины, но последовательность статична всегда, сначала отматать отрезок, потом либо пометить, и отматать еще, либо отрезать), разибрать её на шаги выполнения программы, , управлять Y,R,C и после С писать в Serial "Ok!" 

Но для упращения задачи можно, применить максимум 10 шагов - отмотать, пометить, отмотать.... отрезать, но отрезать может быть на любом четном шаге после отмотать и после отрезать отправляем в serial "Ok!"

Фотографии устаройства https://www.dropbox.com/sh/2eqpqwmvifi3w4u/AAA2TbmTj4Nh4Xe9nVnFMhDra?dl=0

Библиотеку брал тут: http://www.pjrc.com/teensy/td_libs_Encoder.html

Мой код

// #define  ENCODER_OPTIMIZE_INTERRUPTS  //включаем оптимизацию (не работает какие-то ошибки в библиотеке) //
#include <Encoder.h>  //подключаем библиотеку обработки энкодера
Encoder myEnc(2, 3);  // назначаем входы А,В от энкодера
#define resetpin 4    // назначаем пин сброса счетчика
#define motor 13      // назначаем пин управления двигателем
#define yellowspray 5 // назначаем пин для желтой метки
#define redspray 6    // назначаем пин для красной метки
#define cut 7         // назначаем пин для резака

// Переменные механической части //

float kl = 0.01001 ;  // задаем коэфициент пересчета показаний энкодера в метры
int timespay = 5 ;    // задаем время на которое срабатывает спрей
int timecut = 5  ;    // задаем время на которое срабатывает резак
float kstop = 0.01 ;   // задаем уставку для отключения мотора, т.е. за какое растояние до назначенной длины выключить мотор, что бы погасить энерцию двжиения кабеля.
float meters = 0 ;    // создаем переменную для подсчета метров
int leght = 0 ;       // задаем переменную для хранения общей заданной длины
int nextleght = 0 ;   // задаем переменную для хранения заданной длины этапа

// Переменниые части протокола обмена //

String inputString = "";         // переменная типа string для сохранения входных данных
boolean stringComplete = false;  // флаг данные получены, опущен
boolean OkComplete = false;  // флаг Ok! отправлен, опущен

void setup() {
  Serial.begin(9600);                   // включаем обмен по Serial (на скорости)
  inputString.reserve(200);             // резервируем 200 байтов на запись в переменную inputString
  pinMode(resetpin, INPUT_PULLUP);      // задаем  resetpin, как вход, включаем внутренний подтягивающий резистор на 20 кОм
  pinMode(motor, OUTPUT);               // задаем motor, как выход
  digitalWrite(motor, LOW);             // по умолчанию выход motor, выключен
  pinMode(yellowspray, OUTPUT);         // задаем yellowspray, как выход
  digitalWrite(yellowspray, LOW);       // по умолчанию выход yellowspray, выключен
  pinMode(redspray, OUTPUT);            // задаем redspray, как выход
  digitalWrite(redspray, LOW);          // по умолчанию выход redspray, выключен
  pinMode(cut, OUTPUT);                 // задаем cut, как выход
  digitalWrite(cut, LOW);               // по умолчанию выход cut, выключен
  Serial.println("Cable meters start"); // отправляем в serial строку, что наш контроллер готов к работе
  Serial.println("Ok!"); // отправляем в serial строку, что наш контроллер готов к работе
}
long oldPosition  = -999; // задаем переменную для хранения старой позиции, записываем -999 (было изначально в примере)

void loop() {

  // часть для цикла протокола обмена //

  serialEvent(); //вызов функции получения данных из Serial
  if (stringComplete) {                   // если данные записаны в строку,
    Serial.print("nextleght=");           // печатаем ответ
    Serial.println(inputString);          // в COM-порт
    nextleght = (inputString.toInt());    // и присваем nextleght полученные данные, преобразованные в число
    leght = leght + nextleght ;           // и увеличиваем leght на nextleght
    inputString = "" ;                    // обнуляем строковую переменную
    stringComplete = false ;              // и опускаем флаг, что строка заполнена
  }

  //часть для цикла обработки механической части //

  long newPosition = myEnc.read();   // задаем переменную для хранения новой позиции,  записываем новая позиция = то что прочитанно с энкодера.
  if (newPosition != oldPosition) {  // если новая позиция энкодера не равна старой,
    oldPosition = newPosition;       // то записываем, старая позиция равна новой
    Serial.println(newPosition);     // печатаем в Serial, значение новой позиции
    meters = newPosition * kl;       // формула для пересчета подсчитанных инкрементов, в длину в метра, с двумя знаками после запятой
    Serial.print("leght=");
    Serial.println(leght);
    Serial.print("meters=");
    Serial.println(meters);
  }

  //управление мотором //

  if (leght - meters >= kstop) {           //если, заданная длина больше измеренной, более чем на уставку для отключения мотора
    digitalWrite(motor, HIGH) ;            //включаем мотор если,
  }
  else {
    digitalWrite(motor, LOW);              // и выключаем мотор
  }

  // сброс счетчиков //

  if (digitalRead(resetpin) == LOW) { // если нажимаем кнопку reset, сбрасываем счетчики
    myEnc.write(0);
    meters = 0 ;
    leght = 0 ;
  }
}

// чтение данных и Serial //

void serialEvent() {
  while (Serial.available()) {
    char inChar = (char)Serial.read();     // получить новый байт данных:
    inputString += inChar;                 // добавить новый байт к строковой переменной inputString:
    if (inChar == '\n') {                  // если входной символ является новой строкой, взвести флаг
      stringComplete = true;               // что бы основной цикл обработал принятую команду:
    }
  }
}

Если есть желающие помочь доделать проект, велкам !!

exclus
Offline
Зарегистрирован: 10.09.2016

Нашел функцию записи 10 шагов из строки, не могу понять почему нормально не преобразуется step1 в число

#include <string.h>

char step1[5];
char step2[5];
char step3[5];
char step4[5];
char step5[5];
char step6[5];
char step7[5];
char step8[5];
char step9[5];
char step10[5];

boolean step1ok;
boolean step2ok;
boolean step3ok;
boolean step4ok;
boolean step5ok;
boolean step6ok;
boolean step7ok;
boolean step8ok;
boolean step9ok;
boolean step10ok;

int test;

void setup() {
  // открываем порт
  Serial.begin(9600);
  pinMode(13, OUTPUT);
}

void loop() {

  int i = 0;        //задаем переменную i=0
  char buffer[100]; //задаем масив buffer размером 100 байт


  if (Serial.available()) { //если есть данные - читаем
    delay(100);     // пауза 100 милисекунд

    while ( Serial.available() && i < 99) {   //загоняем прочитанное в буфер
      buffer[i++] = Serial.read();
    }

    buffer[i++] = '\0';        //закрываем массив
  }


  if (i > 0) {              //если буфер наполнен


      sscanf(buffer, "%[^','],%[^','],%[^','],%[^','],%[^','],%[^','],%[^','],%[^','],%[^','],%[^','],%s", &step1, &step2, &step3, &step4, &step5, &step6, &step7, &step8, &step9, &step10); //разбераем его на части отделенные запятой
    //sscanf(buffer, "%i%s%d%s%d%s%d%s%d%s", &step1, &step2, &step3, &step4, &step5, &step6, &step7, &step8, &step9, &step10); //разбераем его на части отделенные пробелом
  }

  //Исполнительная часть
  //Проверяем какому устройству пришли данные

  //тестовое устройство 1
 if ((String) step1 == "1") { //test serial read
    Serial.print("step1:");
    Serial.println(step1);
    Serial.print("step2:");
    Serial.println(step2);
    Serial.print("step3:");
    Serial.println(step3);
    Serial.print("step4:");
    Serial.println(step4);
    Serial.print("step5:");
    Serial.println(step5);
    Serial.print("step6:");
    Serial.println(step6);
    Serial.print("step7:");
    Serial.println(step7);
    Serial.print("step8:");
    Serial.println(step8);
    Serial.print("step9:");
    Serial.println(step9);
    Serial.print("step10:");
    Serial.println(step10);
  }

  //пример выполнения команды устройством 013
  if ((String)step1 == "1") {

    if ((String)step2 == "on") {
      digitalWrite(13, HIGH);
      test =int(step1);
      Serial.print("test=");
      Serial.println(test);  // вот тут выдает 511 вместо 1

    }
    if ((String)step2 == "off") {
      digitalWrite(13, LOW);
    }
    step1 [0] = '\0';
    step2 [0] = '\0';
    step3 [0] = '\0';
    step4 [0] = '\0';
    step5 [0] = '\0';
    step6 [0] = '\0';
    step7 [0] = '\0';
    step8 [0] = '\0';
    step9 [0] = '\0';
    step10 [0] = '\0';



    Serial.print("step1:");
    Serial.println(step1);
    Serial.print("step2:");
    Serial.println(step2);
    Serial.print("step3:");
    Serial.println(step3);
    Serial.print("step4:");
    Serial.println(step4);
    Serial.print("step5:");
    Serial.println(step5);
    Serial.print("step6:");
    Serial.println(step6);
    Serial.print("step7:");
    Serial.println(step7);
    Serial.print("step8:");
    Serial.println(step8);
    Serial.print("step9:");
    Serial.println(step9);
    Serial.print("step10:");
    Serial.println(step10);
  }
}

 

Onkel
Offline
Зарегистрирован: 22.02.2016

для вашей задачи у arduino ide офигенный минус - нет прерывания по получению байта uart, без этого прерывания будет не работа, а гемор. Мое предложение остается в силе, с озвученными параметрами - написать нормальный код на честном С, без ардуиновских костылей, тормозов и глюков. Альтернатив много, тем более если вы собираетесь что- либо делать для пром. автоматики - то либо специализированные контроллеры, либо нормальный С. Кстати, смотрите что у Вас тут:

039
	  if (Serial.available()) { //если есть данные - читаем
040
	    delay(100);     // пауза 100 милисекунд
041
	 
042
	    while ( Serial.available() && i < 99) {   //загоняем прочитанное в буфер
043
	      buffer[i++] = Serial.read();
044
	    }

Есл Вы пошлете, например, 9 байт на свою резалку, то этот фрагмент подвесит  все течение программы на 0.1 секунду (ну кроме прерываний, которые будут выполняться),  вы умышленно это сделали? Зачем тут delay(100)?

 

 

SlavaRobotam
Offline
Зарегистрирован: 21.07.2015

плата какая?

Onkel
Offline
Зарегистрирован: 22.02.2016

а зачем у вас там две ардуины? Одна не справляется?

exclus
Offline
Зарегистрирован: 10.09.2016

Всем добрый день.
Onkel - delay осталось от примера который я взял за основу парсера строки.
Прерывание на uart, мне не нужно, т.к. Пк отправляет команду,только когда получит "Ок!" от ардуины, а она соответственно ничего не считает пока не получит команду.
SlavaRobotam - Arduino uno
Onkel- нет, ардуино одна я просто отдельно пишу механику и обмен, что-бы не запутаться. Осталось свести две программы в одну.

Кстати проблема с преобразованием char в int решил, в строке 89 из второго кода, нужно писать: test= atoi(step1);

Onkel
Offline
Зарегистрирован: 22.02.2016

Ну да, в принципе так можно - если ардуине делать нечего, то можно опрашивать буфер uart пока что надо не получишь.

usb не отваливается? А то в пром. условиях usb - не самый лучший вариант, отваливается только давай.

exclus
Offline
Зарегистрирован: 10.09.2016

Ахах, не на столе пока ничего не отвалилось, просмотрите фотки как это выглядит ))) Моя большая гордость, то что он уже считает с точностью до сантиметра !!!

Onkel
Offline
Зарегистрирован: 22.02.2016

exclus пишет:
Ахах, не на столе пока ничего не отвалилось, просмотрите фотки как это выглядит ))) Моя большая гордость, то что он уже считает с точностью до сантиметра !!!

я про отвал в программном смысле, помехи частенько (или иногда, зависит от уровня ЭМ помехи) приводят к потере виндой usb порта (vcp в случае ардуины).

exclus
Offline
Зарегистрирован: 10.09.2016

Доделал контроллер, 510 строк, умеет выполнять последавательно до 10 шагов, проверять наличие кабеля, считать, что следующий отрезок влезает в установленную бухту, сбрасывать показания. Если есть предложения где поправить буду рад информации. Видео  работы позже прикреплю. Код можно использовать в личных целях и для обучения. Для проверки кода отправить в сериал монитор строку: "test,5,2,y,4,r,3,y,2,r,6,c," 

#include <Encoder.h>      //подключаем библиотеку обработки энкодера
Encoder myEnc(2, 3);      // назначаем входы А,В от энкодера
#define resetpin 4        // назначаем пин сброса текущих счетчиков 
#define coilresetpin 9    // назначаем пин сброса счетчика бухты
#define motor 13          // назначаем пин управления двигателем
#define yellowspray 5     // назначаем пин для желтой метки
#define redspray 6        // назначаем пин для красной метки
#define cut 7             // назначаем пин для резака
#define sensor 8          // назначаем пин для сенсора наличия кабеля в станке

//****************** Переменные механической части ****************//

float kl = 0.01001 ;        // задаем коэфициент пересчета показаний энкодера в метры
int timespay = 500 ;        // задаем время на которое срабатывает спрей
int timecut = 500  ;        // задаем время на которое срабатывает резак
float kstop = 0.01 ;        // задаем уставку для отключения мотора, т.е. за какое растояние до назначенной длины выключить мотор, что бы погасить энерцию двжиения кабеля.
float meters = 0 ;          // создаем переменную для подсчета метров
int coilofcable = 0 ;       //задаем переменную для хранения длины загруженной бухты кабеля
int finishcoilofcable = 0 ; // задаем переменную для хранения общих заданных длин отрезков
int finishlenght = 0 ;      // задаем переменную для общей длины замера
int lenght = 0 ;            // задаем переменную для хранения общей заданной длины
int nextlenght = 0 ;        // задаем переменную для хранения заданной длины этапа

//**************** Переменниые части протокола обмена ***************//

char charcoilofcable[5];  //переменная для получения заданной длины бухты
char charfinishlenght[5]; //переменная для получения заданой общей длины отрезка
char step1[5];            //переменная для получения данных шага 1
char step2[5];            //переменная для получения данных шага 2
char step3[5];            //переменная для получения данных шага 3
char step4[5];            //переменная для получения данных шага 4
char step5[5];            //переменная для получения данных шага 5
char step6[5];            //переменная для получения данных шага 6
char step7[5];            //переменная для получения данных шага 7
char step8[5];            //переменная для получения данных шага 8
char step9[5];            //переменная для получения данных шага 9
char step10[5];           //переменная для получения данных шага 10



//******************Флаги для отслеживания последовательного выполнения шагов программы ****************//

int step1ok = 0;
int step2ok = 0;
int step3ok = 0;
int step4ok = 0;
int step5ok = 0;
int step6ok = 0;
int step7ok = 0;
int step8ok = 0;
int step9ok = 0;
int step10ok = 0;

//**************** Сетап ******************//

void setup() {
  Serial.begin(9600);                   // включаем обмен по Serial (на скорости)
  pinMode(resetpin, INPUT_PULLUP);      // задаем  resetpin, как вход, включаем внутренний подтягивающий резистор на 20 кОм
  pinMode(coilresetpin, INPUT_PULLUP);  // задаем  coilresetpin, как вход, включаем внутренний подтягивающий резистор на 20 кОм
  pinMode(sensor, INPUT_PULLUP);        // задаем  sensor, как вход, включаем внутренний подтягивающий резистор на 20 кОм
  pinMode(motor, OUTPUT);               // задаем motor, как выход
  digitalWrite(motor, LOW);             // по умолчанию выход motor, выключен
  pinMode(yellowspray, OUTPUT);         // задаем yellowspray, как выход
  digitalWrite(yellowspray, LOW);       // по умолчанию выход yellowspray, выключен
  pinMode(redspray, OUTPUT);            // задаем redspray, как выход
  digitalWrite(redspray, LOW);          // по умолчанию выход redspray, выключен
  pinMode(cut, OUTPUT);                 // задаем cut, как выход
  digitalWrite(cut, LOW);               // по умолчанию выход cut, выключен


  Serial.println("Cable meters start"); // отправляем в serial строку, что наш контроллер готов к работе
  Serial.println("Ok!");                // отправляем в serial строку, что наш контроллер готов к работе
}

long oldPosition  = -999; // задаем переменную для хранения старой позиции, записываем -999 (было изначально в примере)

//************ Цикл программы **********///

void loop() {

  //******** Часть для цикла протокола обмена *************//

  int i = 0;        //задаем переменную i и обнуляем каждый цикл
  char buffer[100]; //задаем масив buffer размером 100 байт

  if (Serial.available()) { //если есть данные - читаем
    delay(50);              // пауза 50 милисекунд, что бы заполнить буфер Serial

    while ( Serial.available() && i < 99) {   //пока идут данные по Serial и буфер не заполнился максимум 100 байт, загоняем прочитанное в масив buffer
      buffer[i++] = Serial.read();            //прибавляем в массив buffer по одному байту прочитанному из Serial
    }

    buffer[i++] = '\0';        //  закрываем массив, когда  увидели символ конца строки "\0"

  }
  if (i > 0) {       // если i ,больше ноля
    sscanf(buffer, "%[^','],%[^','],%[^','],%[^','],%[^','],%[^','],%[^','],%[^','],%[^','],%[^','],%[^','],%[^','],%s", &charcoilofcable, &charfinishlenght, &step1, &step2, &step3, &step4, &step5, &step6, &step7, &step8, &step9, &step10); //разбераем buffer на части отделенные запятой
  }

  //******************** !!! тест обмена !!!**************************** //

  if ((String) charcoilofcable == "test") { //если первой командой отправить test, печатаем полученные данные в столбик
    Serial.print("coilofcable:");
    Serial.println(charcoilofcable);
    Serial.print("finishlegth:");
    Serial.println(charfinishlenght);
    Serial.print("step1:");
    Serial.println(step1);
    Serial.print("step2:");
    Serial.println(step2);
    Serial.print("step3:");
    Serial.println(step3);
    Serial.print("step4:");
    Serial.println(step4);
    Serial.print("step5:");
    Serial.println(step5);
    Serial.print("step6:");
    Serial.println(step6);
    Serial.print("step7:");
    Serial.println(step7);
    Serial.print("step8:");
    Serial.println(step8);
    Serial.print("step9:");
    Serial.println(step9);
    Serial.print("step10:");
    Serial.println(step10);
    charcoilofcable [0] = '\0';   //и обнуляем все
    charfinishlenght [0] = '\0';
    step1 [0] = '\0';
    step2 [0] = '\0';
    step3 [0] = '\0';
    step4 [0] = '\0';
    step5 [0] = '\0';
    step6 [0] = '\0';
    step7 [0] = '\0';
    step8 [0] = '\0';
    step9 [0] = '\0';
    step10 [0] = '\0';
    meters = 0 ;
    lenght = 0 ;
    coilofcable = 0;
    finishcoilofcable = 0 ;
    finishlenght = 0;
    step1ok = 0 ;
    step2ok = 0 ;
    step3ok = 0 ;
    step4ok = 0 ;
    step5ok = 0 ;
    step6ok = 0 ;
    step7ok = 0 ;
    step8ok = 0 ;
    step9ok = 0 ;
    step10ok = 0 ;
  }

  //******************** !!! конец теста обмена !!!**************************** //

  //********************* ввод данных о длине бухты, и конечной длины текущего отрезка ****************** //

  coilofcable = atoi (charcoilofcable); // преобразуем charcoilofcable в число, записываем в coilofcable
  finishlenght = atoi (charfinishlenght); // преобразуем charfinishlenght в число, записываем в  finishlenght
  finishcoilofcable = finishcoilofcable + finishlenght; // наращиваем переменную  finishcoilofcable, прибавляя последовательно длины отрезков
  charfinishlenght [0] = '\0';  // обнуляем переменную

  //***************проверка наличия кабеля в станке***********************//
  if (digitalRead(sensor) == LOW) {
    Serial.println("!!!Error!!!No cable!!!");    // отправляем в serial строку, что нет кабеля
    digitalWrite(motor, LOW);                    // и выключаем мотор
  }


  //*************** проверка на то, что хватит бухты *********************//

  if (coilofcable - finishcoilofcable < 0) {
    Serial.print("coilofcable:");
    Serial.println(charcoilofcable);
    Serial.print("finishcoilofcable:");
    Serial.println(finishcoilofcable);
    Serial.println("!!!Error!!!Change coil!!!"); // отправляем в serial строку, что замените бухту
    digitalWrite(motor, LOW);                    // и выключаем мотор
    delay (2000)  ;                              // пауза 2 секунды
  }

  //********************** пошаговое выполнение команд **********************//

  // шаг 1 //

  if (lenght <= meters && step1ok < 1) {   // начало длина участка пустая, флаг шага один опущен
    nextlenght = atoi (step1);             // задаем число метров длины 1 этапа
    lenght = lenght + nextlenght ;         // приращиваем общую длину
    step1 [0] = '\0';                      // сбрасываем переменную step1
  }
  if (lenght > meters && step1ok < 1) {  // проверка на то, что контроллер принял следующую длину
    step1ok = 1 ;                        // меняем значение флага step1ok
  }

  // шаг 2 //

  if (lenght > 0 && lenght <= meters  && step1ok > 0 && step2ok < 1 ) {           // если, измеренный кабель сравнялся с прирощенной длинной, и шаг 1 -выполнены
    Serial.println("step1, Ok!");
    if ((String)step2 == "y") {                          // читаем символ 2 этапа, если "y"
      digitalWrite(yellowspray, HIGH);                   // включаем желтый спрей
      delay(timespay);                                   // на время на которое срабатывает спрей, задается в переменной
      digitalWrite(yellowspray, LOW);                    // выключаем желтый спрей
      step2ok = 1 ;                                      // меняем значение флага step2ok
      Serial.println("step2, Ok!");
    }
    if ((String)step2 == "r") {                          // читаем символ 2 этапа, если "r"
      digitalWrite(redspray, HIGH);                      // включаем красный спрей
      delay(timespay);                                   // на время на которое срабатывает спрей, задается в переменной
      digitalWrite(redspray, LOW);                       // выключаем красный спрей
      step2ok = 1 ;                                      // меняем значение флага step2ok
      Serial.println("step2, Ok!");
    }
    if ((String)step2 == "c") {                          // читаем символ 2 этапа, если "с"
      digitalWrite(cut, HIGH);                           // включаем резак
      delay(timecut);                                    // на время на которое срабатывает резак, задается в переменной
      digitalWrite(cut, LOW);                            // выключаем резак
      Serial.println("step2, Ok!");
      Serial.println("Ok!");          // отправляем в serial строку, что наш контроллер готов к работе
      myEnc.write(0);                 // сбрасываем счетчик энкодера
      meters = 0 ;                    // сбрасываем посчитанные метры
      lenght = 0 ;                    // сбрасываем общую длину
      step1ok = 0 ;                   // опускаем флаги
      step2ok = 0 ;                   // опускаем флаги
      step3ok = 0 ;                   // опускаем флаги
      step4ok = 0 ;                   // опускаем флаги
      step5ok = 0 ;                   // опускаем флаги
      step6ok = 0 ;                   // опускаем флаги
      step7ok = 0 ;                   // опускаем флаги
      step8ok = 0 ;                   // опускаем флаги
      step9ok = 0 ;                   // опускаем флаги
      step10ok = 0 ;                  // опускаем флаги
    }
  }

  // шаг 3 //

  if (lenght <= meters && step1ok > 0 && step2ok > 0 && step3ok < 1) { // если  шаг 1 и 2 выполнены
    nextlenght = atoi (step3);             // задаем число метров длины 3 этапа
    lenght = lenght + nextlenght ;         // приращиваем общую длину
    step3 [0] = '\0';                      // сбрасываем переменную step3
  }
  if (lenght > meters && step1ok > 0 && step2ok > 0 && step3ok < 1) { // проверка на то, что контроллер принял следующую длину
    step3ok = 1 ;                                                     // меняем значение флага step3ok
  }

  // шаг 4 //

  if (lenght > 0 && lenght <= meters && step1ok > 0 && step2ok > 0 && step3ok > 0 && step4ok < 1) {           // если, измеренный кабель сравнялся с прирощенной длинной, и шаги 1,2,3 -выполнены
    Serial.println("step3, Ok!");
    if ((String)step4 == "y") {                          // читаем символ 4 этапа, если "y"
      digitalWrite(yellowspray, HIGH);                   // включаем желтый спрей
      delay(timespay);                                   // на время на которое срабатывает спрей, задается в переменной
      digitalWrite(yellowspray, LOW);                    // выключаем желтый спрей
      step4ok = 1 ;                                      // меняем значение флага step4ok
      Serial.println("step4, Ok!");
    }
    if ((String)step4 == "r") {                          // читаем символ 4 этапа, если "r"
      digitalWrite(redspray, HIGH);                      // включаем красный спрей
      delay(timespay);                                   // на время на которое срабатывает спрей, задается в переменной
      digitalWrite(redspray, LOW);                       // выключаем красный спрей
      step4ok = 1 ;                                      // меняем значение флага step4ok
      Serial.println("step4, Ok!");
    }
    if ((String)step4 == "c") {                          // читаем символ 4 этапа, если "с"
      digitalWrite(cut, HIGH);                           // включаем резак
      delay(timecut);                                    // на время на которое срабатывает резак, задается в переменной
      digitalWrite(cut, LOW);                            // выключаем резак
      Serial.println("step4, Ok!");
      Serial.println("Ok!");            // отправляем в serial строку, что наш контроллер готов к работе
      myEnc.write(0);                   // сбрасываем счетчик энкодера
      meters = 0 ;                      // сбрасываем посчитанные метры
      lenght = 0 ;                      // сбрасываем общую длину
      step1ok = 0 ;                     // опускаем флаги
      step2ok = 0 ;                     // опускаем флаги
      step3ok = 0 ;                     // опускаем флаги
      step4ok = 0 ;                     // опускаем флаги
      step5ok = 0 ;                     // опускаем флаги
      step6ok = 0 ;                     // опускаем флаги
      step7ok = 0 ;                     // опускаем флаги
      step8ok = 0 ;                     // опускаем флаги
      step9ok = 0 ;                     // опускаем флаги
      step10ok = 0 ;                    // опускаем флаги
    }
  }

  // шаг 5 //

  if (lenght <= meters && step1ok > 0 && step2ok > 0 && step3ok > 0 && step4ok > 0 && step5ok < 1) { // если  шаг 1,2,3,4 выполнены
    nextlenght = atoi (step5);             // задаем число метров длины 5 этапа
    lenght = lenght + nextlenght ;         // приращиваем общую длину
    step5 [0] = '\0';                      // сбрасываем переменную step5
  }
  if (lenght > meters && step1ok > 0 && step2ok > 0 && step3ok > 0 && step4ok > 0 && step5ok < 1) { // проверка на то, что контроллер принял следующую длину
    step5ok = 1 ;                    // меняем значение флага step5ok
  }

  // шаг 6 //

  if (lenght > 0 && lenght <= meters && step1ok > 0 && step2ok > 0 && step3ok > 0 && step4ok > 0 && step5ok > 0 && step6ok < 1) {          // если, измеренный кабель сравнялся с прирощенной длинной, и шаги 1,2,3,4,5 -выполнены
    Serial.println("step5, Ok!");
    if ((String)step6 == "y") {                          // читаем символ 6 этапа, если "y"
      digitalWrite(yellowspray, HIGH);                   // включаем желтый спрей
      delay(timespay);                                   // на время на которое срабатывает спрей, задается в переменной
      digitalWrite(yellowspray, LOW);                    // выключаем желтый спрей
      step6ok = 1 ;                                      // меняем значение флага step6ok
      Serial.println("step6, Ok!");
    }
    if ((String)step6 == "r") {                          // читаем символ 6 этапа, если "r"
      digitalWrite(redspray, HIGH);                      // включаем красный спрей
      delay(timespay);                                   // на время на которое срабатывает спрей, задается в переменной
      digitalWrite(redspray, LOW);                       // выключаем красный спрей
      step6ok = 1 ;                                      // меняем значение флага step6ok
      Serial.println("step6, Ok!");
    }
    if ((String)step6 == "c") {                          // читаем символ 6 этапа, если "с"
      digitalWrite(cut, HIGH);                           // включаем резак
      delay(timecut);                                    // на время на которое срабатывает резак, задается в переменной
      digitalWrite(cut, LOW);                            // выключаем резак
      Serial.println("step6, Ok!");
      Serial.println("Ok!");             // отправляем в serial строку, что наш контроллер готов к работе
      myEnc.write(0);                    // сбрасываем счетчик энкодера
      meters = 0 ;                       // сбрасываем посчитанные метры
      lenght = 0 ;                       // сбрасываем общую длину
      step1ok = 0 ;                 // опускаем флаги
      step2ok = 0 ;                 // опускаем флаги
      step3ok = 0 ;                 // опускаем флаги
      step4ok = 0 ;                 // опускаем флаги
      step5ok = 0 ;                 // опускаем флаги
      step6ok = 0 ;                 // опускаем флаги
      step7ok = 0 ;                 // опускаем флаги
      step8ok = 0 ;                 // опускаем флаги
      step9ok = 0 ;                 // опускаем флаги
      step10ok = 0 ;                // опускаем флаги
    }
  }

  // шаг 7 //

  if (lenght <= meters && step1ok > 0 && step2ok > 0 && step3ok > 0 && step4ok > 0 && step5ok > 0 && step6ok > 0 && step7ok < 1) { // если  шаг 1,2,3,4,5,6 выполнены
    nextlenght = atoi (step7);             // задаем число метров длины 5 этапа
    lenght = lenght + nextlenght ;         // приращиваем общую длину
    step7 [0] = '\0';                      // сбрасываем переменную step7
  }
  if (lenght > meters && step1ok > 0 && step2ok > 0 && step3ok > 0 && step4ok > 0 && step5ok > 0 && step6ok > 0 && step7ok < 1) { // проверка на то, что контроллер принял следующую длину
    step7ok = 1 ;                    // меняем значение флага step7ok
  }


  // шаг 8 //

  if (lenght > 0 && lenght <= meters && step1ok > 0 && step2ok > 0 && step3ok > 0 && step4ok > 0 && step5ok > 0 && step6ok > 0 && step7ok > 0 && step8ok < 1) {           // если, измеренный кабель сравнялся с прирощенной длинной, и шаги 1,2,3,4,5,6,7 -выполнены
    Serial.println("step7, Ok!");
    if ((String)step8 == "y") {                          // читаем символ 8 этапа, если "y"
      digitalWrite(yellowspray, HIGH);                   // включаем желтый спрей
      delay(timespay);                                   // на время на которое срабатывает спрей, задается в переменной
      digitalWrite(yellowspray, LOW);                    // выключаем желтый спрей
      step8ok = 1 ;                                      // меняем значение флага step8ok
      Serial.println("step8, Ok!");
    }
    if ((String)step8 == "r") {                          // читаем символ 8 этапа, если "r"
      digitalWrite(redspray, HIGH);                      // включаем красный спрей
      delay(timespay);                                   // на время на которое срабатывает спрей, задается в переменной
      digitalWrite(redspray, LOW);                       // выключаем красный спрей
      step8ok = 1 ;                                      // меняем значение флага step8ok
      Serial.println("step8, Ok!");
    }
    if ((String)step8 == "c") {                          // читаем символ 8 этапа, если "с"
      digitalWrite(cut, HIGH);                           // включаем резак
      delay(timecut);                                    // на время на которое срабатывает резак, задается в переменной
      digitalWrite(cut, LOW);                            // выключаем резак
      Serial.println("step8, Ok!");
      Serial.println("Ok!");            // отправляем в serial строку, что наш контроллер готов к работе
      myEnc.write(0);                   // сбрасываем счетчик энкодера
      meters = 0 ;                      // сбрасываем посчитанные метры
      lenght = 0 ;                      // сбрасываем общую длину
      step1ok = 0 ;                 // опускаем флаги
      step2ok = 0 ;                 // опускаем флаги
      step3ok = 0 ;                 // опускаем флаги
      step4ok = 0 ;                 // опускаем флаги
      step5ok = 0 ;                 // опускаем флаги
      step6ok = 0 ;                 // опускаем флаги
      step7ok = 0 ;                 // опускаем флаги
      step8ok = 0 ;                 // опускаем флаги
      step9ok = 0 ;                 // опускаем флаги
      step10ok = 0 ;                // опускаем флаги
    }
  }

  // шаг 9 //

  if (lenght <= meters && step1ok > 0 && step2ok > 0 && step3ok > 0 && step4ok > 0 && step5ok > 0 && step6ok > 0 && step7ok > 0 && step8ok > 0 &&  step9ok < 1) { // если  шаг 1,2,3,4,5,6,7,8 выполнены
    nextlenght = atoi (step9);             // задаем число метров длины 9 этапа
    lenght = lenght + nextlenght ;         // приращиваем общую длину
    step9 [0] = '\0';                      // сбрасываем переменную step9
  }
  if (lenght > meters && step1ok > 0 && step2ok > 0 && step3ok > 0 && step4ok > 0 && step5ok > 0 && step6ok > 0 && step7ok > 0 && step8ok > 0 &&  step9ok < 1) { // проверка на то, что контроллер принял следующую длину
    step9ok = 1 ;                    // меняем значение флага step9ok
  }


  // шаг 10 //

  if (lenght > 0 && lenght <= meters && step1ok > 0 && step2ok > 0 && step3ok > 0 && step4ok > 0 && step5ok > 0 && step6ok > 0 && step7ok > 0 && step8ok > 0 && step9ok > 0 && step10ok < 1) {           // если, измеренный кабель сравнялся с прирощенной длинной, и шаги 1,2,3,4,5,6,7,8,9 -выполнены
    Serial.println("step9, Ok!");
    if ((String)step10 == "y") {                         // читаем символ 10 этапа, если "y"
      digitalWrite(yellowspray, HIGH);                   // включаем желтый спрей
      delay(timespay);                                   // на время на которое срабатывает спрей, задается в переменной
      digitalWrite(yellowspray, LOW);                    // выключаем желтый спрей
      step10ok = 1 ;                                     // меняем значение флага step10ok
      Serial.println("step10, Ok!");
    }
    if ((String)step10 == "r") {                         // читаем символ 10 этапа, если "r"
      digitalWrite(redspray, HIGH);                      // включаем красный спрей
      delay(timespay);                                   // на время на которое срабатывает спрей, задается в переменной
      digitalWrite(redspray, LOW);                       // выключаем красный спрей
      step10ok = 1 ;                                     // меняем значение флага step10ok
      Serial.println("step10, Ok!");
    }
    if ((String)step10 == "c") {                         // читаем символ 10 этапа, если "с"
      digitalWrite(cut, HIGH);                           // включаем резак
      delay(timecut);                                    // на время на которое срабатывает резак, задается в переменной
      digitalWrite(cut, LOW);                            // выключаем резак
      Serial.println("step10, Ok!");
      Serial.println("Ok!");            // отправляем в serial строку, что наш контроллер готов к работе
      myEnc.write(0);                   // сбрасываем счетчик энкодера
      meters = 0 ;                      // сбрасываем посчитанные метры
      lenght = 0 ;                      // сбрасываем общую длину
      step1ok = 0 ;                 // опускаем флаги
      step2ok = 0 ;                 // опускаем флаги
      step3ok = 0 ;                 // опускаем флаги
      step4ok = 0 ;                 // опускаем флаги
      step5ok = 0 ;                 // опускаем флаги
      step6ok = 0 ;                 // опускаем флаги
      step7ok = 0 ;                 // опускаем флаги
      step8ok = 0 ;                 // опускаем флаги
      step9ok = 0 ;                 // опускаем флаги
      step10ok = 0 ;                // опускаем флаги
    }
  }

  //********************** конец  пошагового выполнения команд **********************//

  //******** часть для цикла обработки механической части ****************************//

  long newPosition = myEnc.read();   // задаем переменную для хранения новой позиции,  записываем новая позиция = то что прочитанно с энкодера.
  if (newPosition != oldPosition) {  // если новая позиция энкодера не равна старой,
    oldPosition = newPosition;       // то записываем, старая позиция равна новой
    Serial.println(newPosition);     // печатаем в Serial, значение новой позиции
    meters = newPosition * kl;       // формула для пересчета подсчитанных инкрементов, в длину в метра, с двумя знаками после запятой
    Serial.print("lenght=");
    Serial.println(lenght);
    Serial.print("meters=");
    Serial.println(meters);
  }
  //*************** управление мотором ***************************//

  if (lenght - meters >= kstop) {           //если, заданная длина больше измеренной, более чем на уставку для отключения мотора
    digitalWrite(motor, HIGH) ;            //включаем мотор если,
  }
  else {
    digitalWrite(motor, LOW);              // и выключаем мотор
  }

  //********** сброс текущих счетчиков **************************//

  if (digitalRead(resetpin) == LOW) {  // если нажимаем кнопку reset, сбрасываем счетчики
    myEnc.write(0);                    // сбрасываем счетчик энкодера
    meters = 0 ;                       // сбрасываем посчитанные метры
    lenght = 0 ;                       // сбрасываем общую длину
    step1ok = 0 ;                 // опускаем флаги
    step2ok = 0 ;                 // опускаем флаги
    step3ok = 0 ;                 // опускаем флаги
    step4ok = 0 ;                 // опускаем флаги
    step5ok = 0 ;                 // опускаем флаги
    step6ok = 0 ;                 // опускаем флаги
    step7ok = 0 ;                 // опускаем флаги
    step8ok = 0 ;                 // опускаем флаги
    step9ok = 0 ;                 // опускаем флаги
    step10ok = 0 ;                // опускаем флаги
    Serial.println("lenght,meters - reset"); // отправляем в serial строку, что наш контроллер готов к работе
    Serial.println("Ok!");                   // отправляем в serial строку, что наш контроллер готов к работе
    delay (2000)  ;                          // пауза 2 секунды
  }
  //****************** сброс счетчика бухты ***********************//

  if (digitalRead(coilresetpin) == LOW) { // если нажимаем кнопку coilreset, сбрасываем счетчики
    myEnc.write(0);
    meters = 0 ;
    lenght = 0 ;
    coilofcable = 0;
    finishcoilofcable = 0 ;
    finishlenght = 0;
    charcoilofcable [0] = '\0';   // обнуляем переменную
    step1ok = 0 ;                 // опускаем флаги
    step2ok = 0 ;                 // опускаем флаги
    step3ok = 0 ;                 // опускаем флаги
    step4ok = 0 ;                 // опускаем флаги
    step5ok = 0 ;                 // опускаем флаги
    step6ok = 0 ;                 // опускаем флаги
    step7ok = 0 ;                 // опускаем флаги
    step8ok = 0 ;                 // опускаем флаги
    step9ok = 0 ;                 // опускаем флаги
    step10ok = 0 ;                // опускаем флаги
    Serial.println("Coil - reset");  // отправляем в serial строку, что наш контроллер готов к работе
    Serial.println("Ok!");           // отправляем в serial строку, что наш контроллер готов к работе
    delay (2000) ;                   // пауза 2 секунды
  }
}

 

exclus
Offline
Зарегистрирован: 10.09.2016

https://youtu.be/9cQ-1qWxFwI ссылка на видео.

Клапауций 232
Offline
Зарегистрирован: 05.04.2016
507     Serial.println("Ok!");           // отправляем в serial строку, что наш контроллер готов к работе
508     delay (2000) ;                   // пауза 2 секунды

в течении 2-х секунд готов быть кирпичём