Контроль диаметра нити

Enlan
Offline
Зарегистрирован: 17.04.2016

Вобщем собрал экструдер для нити 3D принтера...

Все хорошо екструдер работает шнек вращяется плачстик плавится нитка пошла.

Но чтоб диаметр нити был равномерным Я решил собрать не большую конструкцию для получения значений диаметра с помощю фоторезистора и светодиода, а какк эти значения заставить работать ... тут я так понимаю нужно использовать if else но как правильно? если к примеру когда нить нужного диаметра показатили примерно 610 это уже выводит монитор порта...

сейчас шаговик тянет нить с выставленой задержкой 60 но это примерно и нить тянется не нужного диаметра но тянется... что нужно дописать чтобы это значение менялось на необходимое чтоб показатели с фоторезистора колибались в раене 620-600

вот пример скетча

int PhotoRes = 0;
int stp = 13;
int dir = 12;

void setup(){
  Serial.begin(9600);
  pinMode (PhotoRes, INPUT);
  pinMode(stp, OUTPUT);
  pinMode(dir, OUTPUT);
}

void loop() {
  Serial.println(analogRead(PhotoRes));
  delay(10);
  digitalWrite(stp, HIGH);
  delay(60);
  digitalWrite(stp, LOW);
  delay(60);
}

 

Enlan
Offline
Зарегистрирован: 17.04.2016

Не одного коментария, ну и не удивительно), все заходят читают и думают что за идиот )

Я не обижаюсь), Я уже привык), мне просто трудновато дается программирование)

но все же прошу вашей помощи с написанием алгоритма...

а пока у меня выходит такая эксперементальная картина:

#include <AccelStepper.h>
AccelStepper Stepper1(1,13,12);
int PhotoRes = 0;
int stp = 13;
int dir = 12;


void setup(){
  Serial.begin(9600);
  pinMode (PhotoRes, INPUT);
}

void loop() {
  Serial.println(analogRead(PhotoRes));
  Stepper1.move(analogRead(PhotoRes));
  Stepper1.run(); 
}

Движок вращяется со скоростю получаемой с фоторезистора, а мне нужно чтобы скорость вращения двигателя колебалась, в нужние моменты притормаживал либо наоборот ускорялся для удержания нужного значения к примеру "610"

MaksVV
Offline
Зарегистрирован: 06.08.2015
#include <AccelStepper.h>
AccelStepper Stepper1(1,13,12);
#define PhotoRes 0
int Speed = 610;  // начальная скорость 
int diameter = 0;
int interval=100; // здесь задаем задержку,мс (скорость изменения скорости вращения)
int stp = 13;
int dir = 12;
unsigned long prev = 0;


void setup(){
  Serial.begin(9600);
  pinMode (PhotoRes, INPUT);
}

void loop() {
diameter = analogRead(PhotoRes);
Serial.println(diameter);

if (millis()-prev>interval) {
  
    if (diameter>610) Speed++;
    else if (diameter<610)Speed--;
  
   prev=millis();
  
  }


Stepper1.move(Speed);

  Stepper1.run(); 
}

 

Araris
Offline
Зарегистрирован: 09.11.2012

Коллеги, а вы уверены, что функция stepper.move(distance) имеет какое-то отношение к скорости вращения двигателя ?

Здесь http://www.airspayce.com/mikem/arduino/AccelStepper/classAccelStepper.html подробно расписано.

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

я просто написал как переменную скорости менять, а уж двигателем рулить думал ТС уже умеет. 

наверное так надо? 

#include <AccelStepper.h>
AccelStepper Stepper1(1,13,12);
#define PhotoRes 0
int Speed = 610;  // начальная скорость 
int diameter = 0;
int interval=100; // здесь задаем задержку,мс (скорость изменения скорости вращения)
int stp = 13;
int dir = 12;
unsigned long prev = 0;


void setup(){
  Serial.begin(9600);
  pinMode (PhotoRes, INPUT);
}

void loop() {

diameter = analogRead(PhotoRes);
Serial.println(diameter);

if (millis()-prev>interval) {
  
     if (diameter>610) Speed++;
else if (diameter<610) Speed--;

Stepper1.setSpeed (Speed);    

   prev=millis();

  }



 // Stepper1.runSpeed(); 
  Stepper1.run(); 
}

 

Enlan
Offline
Зарегистрирован: 17.04.2016

Шикарно) огромное спасибо

а как отключить инверсию?

Если лначение падает ниже 0 двигатель в другую сторону начинаетт вращятся...

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

в строку 26 добавить : 

if (Speed<0) Speed=0;

 

 

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Enlan пишет:

Вобщем собрал экструдер для нити 3D принтера...

Все хорошо екструдер работает шнек вращяется плачстик плавится нитка пошла.

Но чтоб диаметр нити был равномерным Я решил собрать не большую конструкцию для получения значений диаметра с помощю фоторезистора и светодиода, а какк эти значения заставить работать ... тут я так понимаю нужно использовать if else но как правильно? если к примеру когда нить нужного диаметра показатили примерно 610 это уже выводит монитор порта...

сейчас шаговик тянет нить с выставленой задержкой 60 но это примерно и нить тянется не нужного диаметра но тянется... что нужно дописать чтобы это значение менялось на необходимое чтоб показатели с фоторезистора колибались в раене 620-600

вот пример скетча

int PhotoRes = 0;
int stp = 13;
int dir = 12;

void setup(){
  Serial.begin(9600);
  pinMode (PhotoRes, INPUT);
  pinMode(stp, OUTPUT);
  pinMode(dir, OUTPUT);
}

void loop() {
  Serial.println(analogRead(PhotoRes));
  delay(10);
  digitalWrite(stp, HIGH);
  delay(60);
  digitalWrite(stp, LOW);
  delay(60);
}

 

В таких вещах я думаю необходимо применение закона регулирования, П например или ПИ заглаза хватит.

В коде от MaksVV

Вместо (при таком подходе реакция будет медленной, т.к. при каждом этом событии скорость регулируеться на +-1)


if (millis()-prev>interval) {
  
     if (diameter>610) Speed++;
else if (diameter<610) Speed--;

Stepper1.setSpeed (Speed);    

   prev=millis();

  }

нужно примерно это (В этом коде при каждом проходе скорость будеть изменяться пропорционально ошибке регулирования СРАЗУ на необходимую величину для устранения рассогласования)

Пример П (пропорционального регулятора)


if (millis()-prev>interval) {

int error=(610-diametr);//рассоглосование (задание - текущее значение)
Speed=error*kP;//kP - коэффициент пропорциональности (подбирается эксперементально)
//для обеспечения минимальной ошибки регулирования
//и не допущения колебательного процесса

Stepper1.setSpeed (Speed);    

   prev=millis();

  }

Но лучше применить ПИ регулятор который позволить более точно регулировать толшину нити и со временем скомпенсировать износ механизма подачи) ,а значения полученные с аналогово входа необходимо какнибудь фильтровать или усреднять для получения стабильной величины которую принимаем за дествительное значение толщины нити.

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

всё правда, но может и мой простой вариант будет норм работать, если задержкой interval поиграться (поменьше сделать) или вообще в луп поставить. 

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

MaksVV пишет:

всё правда, но может и мой простой вариант будет норм работать, если задержкой interval поиграться (поменьше сделать) или вообще в луп поставить. 


Все равно как часто будет вызываться расчет скорости, если скорость будет меняется +-1. Для выхода на нужное значение потребуется время, а по П закону сразу получаем первое приближение необходимой скорости, но с ним невозможно выдти на задание т.к. при рассогласовании равном 0 скорость тоже будет равна 0…
Так что лучше использовать ПИ закон, он и реакцию даст и точность.

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

yul-i-an пишет:
Все равно как часто будет вызываться расчет скорости, если скорость будет меняется +-1. Для выхода на нужное значение потребуется время

как это все равно? Если чаще прибавлять/убавлять +-1, скорость быстрее меняться и будет. 

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

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

MaksVV пишет:

yul-i-an пишет:
Все равно как часто будет вызываться расчет скорости, если скорость будет меняется +-1. Для выхода на нужное значение потребуется время

как это все равно? Если чаще прибавлять/убавлять +-1, скорость быстрее меняться и будет. 

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

Да я грубо говорю что время уйдет, понятно что это быстро происходит, но П еще быстрей. Если скорость необходимо на 10 поднять, то прибавляя по 1 надо 10 проходов, а П регулятор в первом же проходе на 10 увеличит сразу грубо говоря.

Enlan
Offline
Зарегистрирован: 17.04.2016

Ребятя огромное вам спасибо! Все действительно не так гладко...
Я сейчас все єто тестирую и думаю еще внести изменения добавить щетчик оборотов шнека...
Скоро напишу
Еще раз большое спасибо!

gmixaz
Offline
Зарегистрирован: 12.11.2017

А какова точность измерения диаметра нити фоторезистором? вы вобще меряли как изменяются показания в зависимости от диаметра? я думаю что это будет на уровне шума... Ну или фоторезистор нужен специальный, или там оптика к ниму. Вобще такие вещи  лазером меряются имхо.

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

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

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

https://gloimg.gbtcdn.com/gb/2015/201507/goods-img/1502212953347191875.jpg

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

https://www.google.ru/search?newwindow=1&q=%D0%B0%D1%80%D0%B4%D1%83%D0%B...

точность на порядки выше чем фоторезистор и т.д.

Enlan
Offline
Зарегистрирован: 17.04.2016

С новым годом! важаемие!

с этим кодом получается немножко не то...

Подскажите пожалуйста как добавить диапазон при котором скорость будет равна последнему значению до вхождения в этот диапазон типа не ">=555" и не "<=550"

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Enlan пишет:

С новым годом! важаемие!

с этим кодом получается немножко не то...

Подскажите пожалуйста как добавить диапазон при котором скорость будет равна последнему значению до вхождения в этот диапазон типа не ">=555" и не "<=550"


А код где?

Enlan
Offline
Зарегистрирован: 17.04.2016
#include <AccelStepper.h>
AccelStepper m(1,12,11);
#define p 1
int f = 250;  // диаметр
int s;  //  скорость 
int d;
int i = 100; // здесь задаем задержку,мс (скорость изменения скорости вращения)
int stp = 12;
int dir = 11;
unsigned long v;


void setup(){
  Serial.begin(115200);
  pinMode (p, INPUT);
  m.setMaxSpeed(2000); // предельная скорость

}

void loop() {
  d = analogRead(p);
 // Serial.print(s);
  Serial.println(d);


  if (millis()-v>i) 
  {
    if (d<f) s++;
   else if (d>f) s--;

    v = millis();
  }

  if (s<1) s=1;

  m.setAcceleration(500); // ускорение двигателя
  m.move(s);
  m.run(); 
}

Немного притерпел изменений...

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

#include <AccelStepper.h>
AccelStepper m(1,12,11);
#define p 1
int f = 250;  // диаметр
int s;  //  скорость 
int d;
int i = 100; // здесь задаем задержку,мс (скорость изменения скорости вращения)
int stp = 12;
int dir = 11;
unsigned long v;

void setup(){
  Serial.begin(115200);
  pinMode (p, INPUT);
  m.setMaxSpeed(2000); // предельная скорость

}

void loop() {
  d = analogRead(p);
 // Serial.print(s);
  Serial.println(d);


  if (millis()-v>i) 
  {
//расчет скорости по ПИД закону регулирования
 //Параметры регулятора
 #define kP 150//коэффициент пропорциональности ПОДОБРАТЬ (примерно равен скорости при которой получается нужная толщина)
 #define p_min 0.0//минимум П составляющей - не < 0
 #define p_max 100.0//максимум П составляющей - не > 2000
 #define kI 0.100//коэффициент интегрирования ПОДБИРАТЬ
 #define i_min 0.0//минимум И составляющей
 #define i_max 700.0//максимум И составляющей
 #define kd 0//коэффициент диференциирования ПОДБИРАТЬ если надо
 #define d_ctl 300.0//зона пропорциональности ust-d_ctl ПОДБИРАТЬ
 #define out_min 0//минимальная скорость 
 #define out_max 2000//максимальная скорость
 
 //Расчет скорости
  uint8_t out = 0;
  static float i = 0;
  static float ed = 0;
  float e, p;
  float d;
  e = (f- d); //ошибка регулирования
  p = (d< f- d_ctl) ? p_max : (d> f) ? p_min : (kP * e); //П составляющая
  i = (i < i_min) ? i_min : (i > i_max) ? i_max : i + (kI * e); //И составляющая
  d = kd * (e - ed); //Д составляющая
  ed = e;
  out = (p + i + d < out_min) ? out_min : (p + i + d > out_max) ? out_max : p + i + d;


    v = millis();
  }

  
  m.setAcceleration(500); // ускорение двигателя
  m.move(s);
  m.run(); 
}

С применением ПИ регулятора

Както так.

Еще необходимо добавить фильтрацию аналогового входа и вывод в порт для настройки регулятора

Enlan
Offline
Зарегистрирован: 17.04.2016

мне уже страшно от этого кода... мозг взорвется

#include <AccelStepper.h>
AccelStepper m(1,12,11);
#define p 1
int f = 280;  // диаметр
int s;  //  скорость 
int d;
int i = 100; // здесь задаем задержку,мс (скорость изменения скорости вращения)
int stp = 12;
int dir = 11;
unsigned long v;

void setup(){
  Serial.begin(115200);
  pinMode (p, INPUT);
  m.setMaxSpeed(2000); // предельная скорость

}

void loop() {
  d = analogRead(p);
 // Serial.print(s);
  Serial.println(d);


  if (millis()-v>i) 
  {
//расчет скорости по ПИД закону регулирования
 //Параметры регулятора
 #define kP 150//коэффициент пропорциональности ПОДОБРАТЬ (примерно равен скорости при которой получается нужная толщина)
 #define p_min 279.0//минимум П составляющей - не < 0
 #define p_max 281.0//максимум П составляющей - не > 2000
 #define kI 0.100//коэффициент интегрирования ПОДБИРАТЬ
 #define i_min 100.0//минимум И составляющей
 #define i_max 50.0//максимум И составляющей
 #define kd 1//коэффициент диференциирования ПОДБИРАТЬ если надо
 #define d_ctl 100.0//зона пропорциональности ust-d_ctl ПОДБИРАТЬ
 #define out_min 10//минимальная скорость 
 #define out_max 2000//максимальная скорость
 
 //Расчет скорости
  uint8_t out = 0;
  static float i = 0;
  static float ed = 0;
  float e, p;
  float d;
  e = (f- d); //ошибка регулирования
  p = (d< f- d_ctl) ? p_max : (d> f) ? p_min : (kP * e); //П составляющая
  i = (i < i_min) ? i_min : (i > i_max) ? i_max : i + (kI * e); //И составляющая
  d = kd * (e - ed); //Д составляющая
  ed = e;
  out = (p + i + d < out_min) ? out_min : (p + i + d > out_max) ? out_max : p + i + d;


    v = millis();
  }

  
  m.setAcceleration(500); // ускорение двигателя
  m.move(s);
  m.run(); 
}

 

ino.ino: In function 'void loop()':
ino.ino:44: error: expected unqualified-id before numeric constant
ino.ino:47: error: lvalue required as left operand of assignment

а можно както по проще ну хотяби  типа

if diametr = 279, 280, 281, то  speed = (последней урегулированой скорости)

else if diametr  < 279, то speed++

else if diametr  > 281 то speed--

 

ну гдето примерно так...

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Enlan пишет:

мне уже страшно от этого кода... мозг взорвется

#include <AccelStepper.h>
AccelStepper m(1,12,11);
#define p 1
int f = 280;  // диаметр
int s;  //  скорость 
int d;
int i = 100; // здесь задаем задержку,мс (скорость изменения скорости вращения)
int stp = 12;
int dir = 11;
unsigned long v;

void setup(){
  Serial.begin(115200);
  pinMode (p, INPUT);
  m.setMaxSpeed(2000); // предельная скорость

}

void loop() {
  d = analogRead(p);
 // Serial.print(s);
  Serial.println(d);


  if (millis()-v>i) 
  {
//расчет скорости по ПИД закону регулирования
 //Параметры регулятора
 #define kP 150//коэффициент пропорциональности ПОДОБРАТЬ (примерно равен скорости при которой получается нужная толщина)
 #define p_min 279.0//минимум П составляющей - не < 0
 #define p_max 281.0//максимум П составляющей - не > 2000
 #define kI 0.100//коэффициент интегрирования ПОДБИРАТЬ
 #define i_min 100.0//минимум И составляющей
 #define i_max 50.0//максимум И составляющей
 #define kd 1//коэффициент диференциирования ПОДБИРАТЬ если надо
 #define d_ctl 100.0//зона пропорциональности ust-d_ctl ПОДБИРАТЬ
 #define out_min 10//минимальная скорость 
 #define out_max 2000//максимальная скорость
 
 //Расчет скорости
  uint8_t out = 0;
  static float i = 0;
  static float ed = 0;
  float e, p;
  float d;
  e = (f- d); //ошибка регулирования
  p = (d< f- d_ctl) ? p_max : (d> f) ? p_min : (kP * e); //П составляющая
  i = (i < i_min) ? i_min : (i > i_max) ? i_max : i + (kI * e); //И составляющая
  d = kd * (e - ed); //Д составляющая
  ed = e;
  out = (p + i + d < out_min) ? out_min : (p + i + d > out_max) ? out_max : p + i + d;


    v = millis();
  }

  
  m.setAcceleration(500); // ускорение двигателя
  m.move(s);
  m.run(); 
}

 

ino.ino: In function 'void loop()':
ino.ino:44: error: expected unqualified-id before numeric constant
ino.ino:47: error: lvalue required as left operand of assignment

а можно както по проще ну хотяби  типа

if diametr = 279, 280, 281, то  speed = (последней урегулированой скорости)

else if diametr  < 279, то speed++

else if diametr  > 281 то speed--

 

ну гдето примерно так...


Ну тогда в своём коде частоту изменения скорости увеличьте хотябы до 1 сек.
И фильтрацию значений с аналогового входа добавьте, хотябы среднее из 10.

Enlan
Offline
Зарегистрирован: 17.04.2016

как это пишется?) пожалуйста!

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

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

Enlan
Offline
Зарегистрирован: 17.04.2016

Я не знаю как зафиксировать показатели последней скорости...

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Enlan пишет:

как это пишется?) пожалуйста!


Если (диам<100 и диам>300){
Если (диам<100) скорость++;
Иначе если (диам>300) скорость--;
}
Примерно
А по фильтрам в поиск.

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

yul-i-an пишет:
Если (диам<100 и диам>300)

такого не будит

Enlan
Offline
Зарегистрирован: 17.04.2016

как соеденить сюда еще дисплей? Я подключил дисплей, дисплей работает виводит диаметр но двигатель отваливается(((

#include <AccelStepper.h>
AccelStepper m(1,12,11);
#include <SPI.h>                                  
#include <Wire.h>
#include <Adafruit_SSD1306.h>                 // Подключаем библиотеку программных драйверов для монохромных дисплеев
#include <Adafruit_GFX.h>                     // Подключаем библиотеку для работы с текстом и графикой
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);
#define p 1
//int f = 245;
int s;  // начальная скорость 
int d;
int i = 1; // здесь задаем задержку,мс (скорость изменения скорости вращения)
int stp = 12;
int dir = 11;
unsigned long v;


void setup(){
  display.begin(SSD1306_SWITCHCAPVCC);         //Активируем дисплей
 // Serial.begin(115200);
  pinMode (p, INPUT);
  m.setMaxSpeed(2000);
  display.clearDisplay();                                                        // Очищаем дисплей и буфер перед выводом
  display.setTextColor(WHITE);                                                   // Устанавливаем цвет шрифта (WHITE, BLACK)
  display.setTextSize(4);                                                        // Устанавливаем размер шрифта (от 1 до 4)                                                       // Выводим слово Temp 
  display.setCursor(30,20);                                                       // Устанавливаем позицию вывода (x,y - левый верхний угол области вывода)
  display.print(String(d));                                               // Записываем показания датчика в строковом формате в буфер
  display.display();
}

void loop() {

  d = analogRead(p);
  
  m.setAcceleration(2000);
  m.move(s);
  m.run(); 

  if (millis()-v>i) 
  {
    if (d>231) s--;
   else if (d<229) s++;
  else if (d=230)s;
    v = millis();
  }

  if (s<1) s=1;



  display.clearDisplay();                                                        // Очищаем дисплей и буфер перед выводом
  display.setTextColor(WHITE);                                                   // Устанавливаем цвет шрифта (WHITE, BLACK)
  display.setTextSize(4);                                                        // Устанавливаем размер шрифта (от 1 до 4)                                                       // Выводим слово Temp 
  display.setCursor(30,20);                                                       // Устанавливаем позицию вывода (x,y - левый верхний угол области вывода)
  display.print(String(d));                                               // Записываем показания датчика в строковом формате в буфер
  display.display();


}

 

Enlan
Offline
Зарегистрирован: 17.04.2016

точнее он крутится но ели ели и не меняется скорость

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

MaksVV пишет:

yul-i-an пишет:
Если (диам<100 и диам>300)

такого не будит


Я паражен... Откуда я могу знать что у Вас будет. Я просто пример написал. А вы перед тем как скорость регулировать сначала проверьте толщину и уж если она не в пределах то переходите к регулировке скорости.

Enlan
Offline
Зарегистрирован: 17.04.2016

Как совместить дисплей с движком?

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Del

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

yul-i-an пишет:
MaksVV пишет:

yul-i-an пишет:
Если (диам<100 и диам>300)

такого не будит

Я паражен... Откуда я могу знать что у Вас будет. Я просто пример написал. А вы перед тем как скорость регулировать сначала проверьте толщину и уж если она не в пределах то переходите к регулировке скорости.

я не ТС. Я про то, что условие никогда не выполнится. тут нужно "или"

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

MaksVV пишет:

я не ТС. Я про то, что условие никогда не выполнится. тут нужно "или"

Пардон. С замечанием согласен.

Dyrman
Offline
Зарегистрирован: 10.04.2017

Только ради Вас и немножечко себя... Идея не нова...
В течении месяца попробуем написать скетч для Arduino nano, uno... измерение толщины будет производится механически, через рычаг или разницу плеч, с помощью датчика холла, или даже нескольких... протяжка, униполярным двигателем и энкодер помощь...
за основу взят аналоговый датчик ss49e и его возможность "открываться" или закрываться при поднесении к нему магнита. Работает от 5v и не нужны ни какие дополнительныесть резисторы.

Будет реализовано несколько режимов работы.

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

Работа. Двигатель вращается и подстраивается под "эталонное" значение, это значение задается 3 режимом, долгим удержанием кнопки, в зависимости от отклонения, а на 1 см около 1000 значений, двигатель ускоряется или замедляется на 0.1 оборота, так же с энкодера.

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

Так же энкодер можно заменить 2 кнопками....

Возможно чуть позже реализуем расчет скорости для компенсации растояния от экструдера до датчика.

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Уважаемый Dyrman не изобретайте велосипед. Для регулировки тощины необходим ПИД регулятор, а не какойто расчет скорости для компенсации...

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

В Вашем случае главное это измерить тощину с необходимой точностью и пременить ПИД регулятор для потдержания неоходимой.

Dyrman
Offline
Зарегистрирован: 10.04.2017

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

Какой раствор в ванной? Охлаждается ли ванная или она теплая? Присутствует ли сушка? На промышленных линиях находил микрометр, на али 900р, работал он через подвижный валик-подшипник, на Вашей линии так же было? Какая сила была на натяжителе?

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

Я основывают на видео "Линия производства нити для 3D принтера" красный филамент из бокового экструдера

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012
Dyrman пишет:
Ну значит будем регулировать скорость экструдера. А нятяжка будет постоянной, делов то, перекинуть управление. Тут же основное в том что бы точно измерить пластик.... если работали с промышленным экструдер ом, поделитесь опытом... Какой раствор в ванной? Охлаждается ли ванная или она теплая? Присутствует ли сушка? На промышленных линиях находил микрометр, на али 900р, работал он через подвижный валик-подшипник, на Вашей линии так же было? Какая сила была на натяжителе? Сразу хочу сказать, опыта в этом деле пока что нет, поэтому хотел скоростью экструдера регулировать текучесть, а протяжкой толщину, то есть чем быстрее протяжка, тем тоньше нить, и на оборот... с экструдер ом так же, чем дольше пластик внутри, тем больше он вариться и тем самым он более ждикий на выходе... как бы двойная регулировка для поиска золотой середины. Я основывают на видео "Линия производства нити для 3D принтера" красный филамент из бокового экструдера
В моем случае толщина нитей не была критичной, т.к. в конце процесса они нарубались на гранулы. На шнеке экструдера 3-4 зоны в которых потдерживалась разная температура (на зонах присутствовал как нагрев так и охлаждение (гдето водяное, гдето воздушное) по нарастающей к выходу), на конце экструдера головка (тоже с подогревом) из нее выходило около 8-10 нитей. Нити погружались в ванную при помощи направляющих роликов. В ванной обычная вода с небольшим расходом (чтобы не перегрелась). на выходе из ванной стояла рейка с жатым воздухом для сдува капеь оставшейся воды. Ну и в конце нити проходили через протягивающие валики и нарубающую их на гранулы фрезу. Но я думаю вариации оборудования могут быть и иные.

Примерно так

Dyrman
Offline
Зарегистрирован: 10.04.2017

Да, на такие промышленные линии так же натыкался.

Все сходится. Может будет совет по шнеку? Есть разные отзывы на древесный бур и по бетону, какой лучше?

В проекте мы хотим сделать шоковую ванну, дно охлаждать элементами пелье, на их горячей стороне установить радиаторы, и через трубу выдувать теплый воздух на "сушилку", это 7 роликов на подшипниках, диаметром не более 10см, нить будет проходить от одного ролика к другому перекрестно, обдуваться, возможно будет мягкая щетка или губка, после чего попадает на центрующие ролики, измеритель толщины, протяжка, энкодер. Последние 3 стараюсь сделать в одном модуле. На счет намотки не думали даже, но думаю стоит посмотреть как наматывают нити, канаты, кабеля и тросы.

В остальном, жду Тарантулу, и буду все печатать... шредера чертеж нужен? Для лазера

Enlan
Offline
Зарегистрирован: 17.04.2016

Помучавшись некоторое время с екструдером получился следующий код и все вроде работает с помощю фоторезистора но со временем показания фоторезистора начинают падать и в результате измерения получаются не точные... вот код:

#include <AccelStepper.h>
AccelStepper m(1,12,11);
#define p 1
int minSpeed = 1000; 	//Минимальная скорость
int s; 			//cкорость последня
long d;			//Среднее показание прибора
int i = 10;		//здесь задаем задержку, мс (скорость изменения скорости вращения)

unsigned long v;

void setup(){
  Serial.begin(9600);
  m.setMaxSpeed(2700);
  m.setAcceleration(1000);

}


void loop(){
  if (millis() - v > i) {
    //Снимаем 10 раз показания прибора и считаем среднее значение.
    d = 0;
       for (int k=0; k<10; ++k) {
       d = d + analogRead(p);
    }
    d = d/10;
    Serial.println(d);
    Serial.println(-s);
    if (s < minSpeed)
      s = minSpeed;
    if (d > 140)
      s--;
    else if (d < 139)
      s++;
  v = millis();
if (s>2700)
s=2700;
if (s<1000)
s=1000;
  }

  m.setSpeed(s);
  m.runSpeed();
}

И мне пришла идея использовать датчик освещенности BH1750 у него показатели намного точнее и диапазон показаний намного шире...но как его правильно вписать в код? при моих попытках его туда запихнуть получается что шаговик остонавливается и показания виводимие в порт идет начальные на момент загрузки ардуино идальше не меняются и шаговик опять же стоит на месте тоесть все не работает( , и еще при заливке стандартного скетча идущего с библиотекой BH1750 максимальная скорость считывания 150милисекунд есле меньше то он точно так же зависает и показивает одну и туже цифру... вот код:

#include <Wire.h>
#include <BH1750.h>
BH1750 lightMeter(0x23);

#include <AccelStepper.h>
AccelStepper m(1, 12, 11);
int minSpeed = 1000;     //Минимальная скорость
int s;             //скорость последняя
long d;            //Среднее показание прибора
int i = 10;        //здесь задаем задержку, мс (скорость изменения скорости вращения)

unsigned long v;

void setup() {
  Serial.begin(9600);
  m.setMaxSpeed(2700);
  m.setAcceleration(1000);

  Wire.begin();
  if (lightMeter.begin(BH1750::CONTINUOUS_HIGH_RES_MODE_2));
}


void loop() {
  if (millis() - v > i) {
    //Снимаем 100 раз показания прибора и считаем среднее значение.
    d = 0;
    for (int k = 0; k < 10; ++k) {
      d = d + lightMeter.readLightLevel();
    }
    d = d / 10;
    Serial.println(d);
    Serial.println(-s);
    if (s < minSpeed)
      s = minSpeed;
    if (d > 140)
      s--;
    else if (d < 139)
      s++;
    v = millis();
    if (s > 2700)
      s = 2700;
    if (s < 1000)
      s = 1000;
  }
 
  m.setSpeed(s);
  m.runSpeed();
}

 

Помогите пожалуйста как ихи скомпоновать...

Dyrman
Offline
Зарегистрирован: 10.04.2017

я не уверен, но возможно эта статья Вам поможет, проверьте, идут ли данные с датчика.

ТЫК

или же если не получается, попробуйте подключить по i2c.

ТЫК

Enlan
Offline
Зарегистрирован: 17.04.2016

Да нет же сам датчик работает Я же говорю что сам датчик работает... и я же дал пример работы всей системи с фоторезистором но теперь в место фоторезистора нужно в код вписать етот датчик...

а вот пример со стандартной библиотеки с которым все работает в порт выходят данные....

/*

  Advanced BH1750 library usage example

  This example has some comments about advanced usage features.

  Connection:

    VCC -> 3V3 or 5V
    GND -> GND
    SCL -> SCL (A5 on Arduino Uno, Leonardo, etc or 21 on Mega and Due, on esp8266 free selectable)
    SDA -> SDA (A4 on Arduino Uno, Leonardo, etc or 20 on Mega and Due, on esp8266 free selectable)
    ADD -> (not connected) or GND

  ADD pin is used to set sensor I2C address. If it has voltage greater or equal to
  0.7VCC voltage (e.g. you've connected it to VCC) the sensor address will be
  0x5C. In other case (if ADD voltage less than 0.7 * VCC) the sensor address will
  be 0x23 (by default).

*/

#include <Wire.h>
#include <BH1750.h>

/*

  BH1750 can be physically configured to use two I2C addresses:
    - 0x23 (most common) (if ADD pin had < 0.7VCC voltage)
    - 0x5C (if ADD pin had > 0.7VCC voltage)

  Library uses 0x23 address as default, but you can define any other address.
  If you had troubles with default value - try to change it to 0x5C.

*/
BH1750 lightMeter(0x23);

void setup(){

  Serial.begin(9600);

  // Initialize the I2C bus (BH1750 library doesn't do this automatically)
  Wire.begin();
  // On esp8266 you can select SCL and SDA pins using Wire.begin(D4, D3);

  /*

    BH1750 has six different measurement modes. They are divided in two groups;
    continuous and one-time measurements. In continuous mode, sensor continuously
    measures lightness value. In one-time mode the sensor makes only one
    measurement and then goes into Power Down mode.

    Each mode, has three different precisions:

      - Low Resolution Mode - (4 lx precision, 16ms measurement time)
      - High Resolution Mode - (1 lx precision, 120ms measurement time)
      - High Resolution Mode 2 - (0.5 lx precision, 120ms measurement time)

    By default, the library uses Continuous High Resolution Mode, but you can
    set any other mode, by passing it to BH1750.begin() or BH1750.configure()
    functions.

    [!] Remember, if you use One-Time mode, your sensor will go to Power Down
    mode each time, when it completes a measurement and you've read it.

    Full mode list:

      BH1750_CONTINUOUS_LOW_RES_MODE
      BH1750_CONTINUOUS_HIGH_RES_MODE (default)
      BH1750_CONTINUOUS_HIGH_RES_MODE_2

      BH1750_ONE_TIME_LOW_RES_MODE
      BH1750_ONE_TIME_HIGH_RES_MODE
      BH1750_ONE_TIME_HIGH_RES_MODE_2

  */

  // begin returns a boolean that can be used to detect setup problems.
  if (lightMeter.begin(BH1750::CONTINUOUS_HIGH_RES_MODE)) {
    Serial.println(F("BH1750 Advanced begin"));
  }
  else {
    Serial.println(F("Error initialising BH1750"));
  }

}


void loop() {

  uint16_t lux = lightMeter.readLightLevel();
  Serial.print("Light: ");
  Serial.print(lux);
  Serial.println(" lx");
  delay(1000);

}

в delay пишу 150 вместо1000 тоесть одной секунды и все работает но дело не в етом, а в том что в последнем примере Я чтото не так указал и датчик выбивате одно значение полученое на момент замуска ардуинки и тулит его в порт постоянно и неизменно и при етом еще и шаговик стоит на месте а он должен вращятся хотмбы с мнимальной скоростю...

Ales
Offline
Зарегистрирован: 05.04.2020

yul-i-an пишет:


#include <AccelStepper.h>
AccelStepper m(1,12,11);
#define p 1
int f = 250;  // диаметр
int s;  //  скорость 
int d;
int i = 100; // здесь задаем задержку,мс (скорость изменения скорости вращения)
int stp = 12;
int dir = 11;
unsigned long v;

void setup(){
  Serial.begin(115200);
  pinMode (p, INPUT);
  m.setMaxSpeed(2000); // предельная скорость

}

void loop() {
  d = analogRead(p);
 // Serial.print(s);
  Serial.println(d);


  if (millis()-v>i) 
  {
//расчет скорости по ПИД закону регулирования
 //Параметры регулятора
 #define kP 150//коэффициент пропорциональности ПОДОБРАТЬ (примерно равен скорости при которой получается нужная толщина)
 #define p_min 0.0//минимум П составляющей - не < 0
 #define p_max 100.0//максимум П составляющей - не > 2000
 #define kI 0.100//коэффициент интегрирования ПОДБИРАТЬ
 #define i_min 0.0//минимум И составляющей
 #define i_max 700.0//максимум И составляющей
 #define kd 0//коэффициент диференциирования ПОДБИРАТЬ если надо
 #define d_ctl 300.0//зона пропорциональности ust-d_ctl ПОДБИРАТЬ
 #define out_min 0//минимальная скорость 
 #define out_max 2000//максимальная скорость
 
 //Расчет скорости
  uint8_t out = 0;
  static float i = 0;
  static float ed = 0;
  float e, p;
  float d;
  e = (f- d); //ошибка регулирования
  p = (d< f- d_ctl) ? p_max : (d> f) ? p_min : (kP * e); //П составляющая
  i = (i < i_min) ? i_min : (i > i_max) ? i_max : i + (kI * e); //И составляющая
  d = kd * (e - ed); //Д составляющая
  ed = e;
  out = (p + i + d < out_min) ? out_min : (p + i + d > out_max) ? out_max : p + i + d;


    v = millis();
  }

  
  m.setAcceleration(500); // ускорение двигателя
  m.move(s);
  m.run(); 
}

С применением ПИ регулятора

Както так.

Еще необходимо добавить фильтрацию аналогового входа и вывод в порт для настройки регулятора

Доброго времени! Хотя тема старая но интерес возник по ПИД регулированию датчиков света.

вопрос: от какого значения отталкиваться при подборе коэффициентов ПИД в этом коде?

и как можно реализовать фильтрацию аналогового входа и вывод в порт для настройки регулятора

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Ales пишет:

yul-i-an пишет:


#include <AccelStepper.h>
AccelStepper m(1,12,11);
#define p 1
int f = 250;  // диаметр
int s;  //  скорость 
int d;
int i = 100; // здесь задаем задержку,мс (скорость изменения скорости вращения)
int stp = 12;
int dir = 11;
unsigned long v;

void setup(){
  Serial.begin(115200);
  pinMode (p, INPUT);
  m.setMaxSpeed(2000); // предельная скорость

}

void loop() {
  d = analogRead(p);
 // Serial.print(s);
  Serial.println(d);


  if (millis()-v>i) 
  {
//расчет скорости по ПИД закону регулирования
 //Параметры регулятора
 #define kP 150//коэффициент пропорциональности ПОДОБРАТЬ (примерно равен скорости при которой получается нужная толщина)
 #define p_min 0.0//минимум П составляющей - не < 0
 #define p_max 100.0//максимум П составляющей - не > 2000
 #define kI 0.100//коэффициент интегрирования ПОДБИРАТЬ
 #define i_min 0.0//минимум И составляющей
 #define i_max 700.0//максимум И составляющей
 #define kd 0//коэффициент диференциирования ПОДБИРАТЬ если надо
 #define d_ctl 300.0//зона пропорциональности ust-d_ctl ПОДБИРАТЬ
 #define out_min 0//минимальная скорость 
 #define out_max 2000//максимальная скорость
 
 //Расчет скорости
  uint8_t out = 0;
  static float i = 0;
  static float ed = 0;
  float e, p;
  float d;
  e = (f- d); //ошибка регулирования
  p = (d< f- d_ctl) ? p_max : (d> f) ? p_min : (kP * e); //П составляющая
  i = (i < i_min) ? i_min : (i > i_max) ? i_max : i + (kI * e); //И составляющая
  d = kd * (e - ed); //Д составляющая
  ed = e;
  out = (p + i + d < out_min) ? out_min : (p + i + d > out_max) ? out_max : p + i + d;


    v = millis();
  }

  
  m.setAcceleration(500); // ускорение двигателя
  m.move(s);
  m.run(); 
}

С применением ПИ регулятора

Както так.

Еще необходимо добавить фильтрацию аналогового входа и вывод в порт для настройки регулятора

Доброго времени! Хотя тема старая но интерес возник по ПИД регулированию датчиков света.

вопрос: от какого значения отталкиваться при подборе коэффициентов ПИД в этом коде?

и как можно реализовать фильтрацию аналогового входа и вывод в порт для настройки регулятора

Для фильтрации данных с аналогового входа есть множество вариантов, например вычислять среднее из 10 измерений. Можно взять 9 замеров, ранжировать, взять 5е, при следующем измерении выкинуть первое, все сдвинуть на 1, на последнее место поставить новое поступившее значение, снова ранжировать и т.д.. Можно взять 20% от первого измерения и 80% от второго и посчитать среднее (на таком способе проблемы с реакцией).

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

В общем все эксперементально. Ну и в сети есть несколько стандартных способов тангенциальный и еще какието.

Удачи в изысканиях!

Если где неправильно написал поправьте.

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Enlan пишет:

Помучавшись некоторое время с екструдером получился следующий код и все вроде работает с помощю фоторезистора но со временем показания фоторезистора начинают падать и в результате измерения получаются не точные... вот код:

#include <AccelStepper.h>
AccelStepper m(1,12,11);
#define p 1
int minSpeed = 1000; 	//Минимальная скорость
int s; 			//cкорость последня
long d;			//Среднее показание прибора
int i = 10;		//здесь задаем задержку, мс (скорость изменения скорости вращения)

unsigned long v;

void setup(){
  Serial.begin(9600);
  m.setMaxSpeed(2700);
  m.setAcceleration(1000);

}


void loop(){
  if (millis() - v > i) {
    //Снимаем 10 раз показания прибора и считаем среднее значение.
    d = 0;
       for (int k=0; k<10; ++k) {
       d = d + analogRead(p);
    }
    d = d/10;
    Serial.println(d);
    Serial.println(-s);
    if (s < minSpeed)
      s = minSpeed;
    if (d > 140)
      s--;
    else if (d < 139)
      s++;
  v = millis();
if (s>2700)
s=2700;
if (s<1000)
s=1000;
  }

  m.setSpeed(s);
  m.runSpeed();
}

И мне пришла идея использовать датчик освещенности BH1750 у него показатели намного точнее и диапазон показаний намного шире...но как его правильно вписать в код? при моих попытках его туда запихнуть получается что шаговик остонавливается и показания виводимие в порт идет начальные на момент загрузки ардуино идальше не меняются и шаговик опять же стоит на месте тоесть все не работает( , и еще при заливке стандартного скетча идущего с библиотекой BH1750 максимальная скорость считывания 150милисекунд есле меньше то он точно так же зависает и показивает одну и туже цифру... вот код:

#include <Wire.h>
#include <BH1750.h>
BH1750 lightMeter(0x23);

#include <AccelStepper.h>
AccelStepper m(1, 12, 11);
int minSpeed = 1000;     //Минимальная скорость
int s;             //скорость последняя
long d;            //Среднее показание прибора
int i = 10;        //здесь задаем задержку, мс (скорость изменения скорости вращения)

unsigned long v;

void setup() {
  Serial.begin(9600);
  m.setMaxSpeed(2700);
  m.setAcceleration(1000);

  Wire.begin();
  if (lightMeter.begin(BH1750::CONTINUOUS_HIGH_RES_MODE_2));
}


void loop() {
  if (millis() - v > i) {
    //Снимаем 100 раз показания прибора и считаем среднее значение.
    d = 0;
    for (int k = 0; k < 10; ++k) {
      d = d + lightMeter.readLightLevel();
    }
    d = d / 10;
    Serial.println(d);
    Serial.println(-s);
    if (s < minSpeed)
      s = minSpeed;
    if (d > 140)
      s--;
    else if (d < 139)
      s++;
    v = millis();
    if (s > 2700)
      s = 2700;
    if (s < 1000)
      s = 1000;
  }
 
  m.setSpeed(s);
  m.runSpeed();
}

 

Помогите пожалуйста как ихи скомпоновать...

В этом коде можно немного подправить чтобы увеличить скорость реакции

Вместо

    if (d > 140)
      s--;
    else if (d < 139)
      s++;

Нужно увеличивать и уменьшать не на единицу, а на разницу между заданным и измеренным

error= 140 (заданная) - d
      s=s+error;
//тут проверять на выход из диапазона мин мах

Так будет пошустрее

Ales
Offline
Зарегистрирован: 05.04.2020

 

//тут проверять на выход из диапазона мин мах

Не могли бы пояснить это утверждение?

 

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Ales пишет:

 

//тут проверять на выход из диапазона мин мах

Не могли бы пояснить это утверждение?

 

Я так понимаю что s это скорость, соответственно она не может быть <0 и > максимальной.

if (s<s_min) {
s=s_min;
}
if (s>s_max) {
s=s_max;
}

примерно так.

Ales
Offline
Зарегистрирован: 05.04.2020

Да... 

А нельзя ли дальше оптимизировать, ставя вместо "int" ов  uint8_t или uint16_t?

Это может повлиять на скорость исполнения кода?

Или что может повлиять?

Или может если на STM32 загрузить может ли увеличится скорость?

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Оно и так должно все работать нормально.
А переменные нужно выбирать в соответствии с размерностью значений которые в них будут хранится.

Ales
Offline
Зарегистрирован: 05.04.2020
Доброго времени! Кажется подправил все, но выдает ошибку.
Не могли бы подправить?
#include <Wire.h>
#include <BH1750.h>
BH1750 lightMeter(0x23);

#include <AccelStepper.h>
AccelStepper m(1, 12, 11);
int minSpeed = 1000;     //Минимальная скорость
int s;             //скорость последняя
long d;            //Среднее показание прибора
int i = 10;        //здесь задаем задержку, мс (скорость изменения скорости вращения)

unsigned long v;

void setup() {
  Serial.begin(9600);
  m.setMaxSpeed(2700);
  m.setAcceleration(1000);

  Wire.begin();
  if (lightMeter.begin(BH1750::CONTINUOUS_HIGH_RES_MODE_2));
}


void loop() {
  if (millis() - v > i) {
    //Снимаем 100 раз показания прибора и считаем среднее значение.
    d = 0;
    for (int k = 0; k < 10; ++k) {
      d = d + lightMeter.readLightLevel();
    }
    d = d / 10;
    Serial.println(d);
    Serial.println(-s);
    if (s < minSpeed)
      s = minSpeed;
    error= 140 (заданная) - d
      s=s+error;
//тут проверять на выход из диапазона мин мах
   if (s<s_min) {
s=s_min;
}
if (s>s_max) {
s=s_max;
}           
        
            v = millis();
    if (s > 2700)
      s = 2700;
    if (s < 1000)
      s = 1000;
  }
 
  m.setSpeed(s);
  m.runSpeed();
}

 

 

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

Ales пишет:

но выдает ошибку

Принято к сведению.

Ales пишет:

Не могли бы подправить?

Нет.

Ales
Offline
Зарегистрирован: 05.04.2020

Нет так нет!  Не очень то и нужен! Просто для интереса. А чё такие вредные здесь? Кидаются...