121

Re: Узел отбора на перистальтическом насосе

kvic ©:

В двух словах можно пояснить ?

Не... Я лучше тебя послушаю (серьезно). Везде вроде говорится, что встроенные слишком большое сопротивление имеют. Что такое слишком? Я не знаю...

С уважением, Олег Кузнецов.

122

Re: Узел отбора на перистальтическом насосе

Kusnezov Oleg, мне тоже особо на эту тему сказать нечего, я ими просто пользуюсь.
Думал, может где-то что-то упустил.
Вот и поинтересовался.

Kusnezov Oleg ©:

слишком большое сопротивление имеют

Я это утверждение тоже не воспринимаю без конкретного уточнения требований.
Для чего-либо высокоскоростного может быть.
Завал фронтов, запаздывание по фазе, прочие высокомудрые слова...  :D
----
В наших медленных процессах предлагаю не заморачиваться на несущественных (по моему мнению) деталях.

РК 35х1600

123

Re: Узел отбора на перистальтическом насосе

kvic, ну вот, что меня в свое время смутило (типичная цитата):
"Как выбрать номинал для подтягивающего резистора? Общая рекомендация - это, как правило, 10кОм. Где-то от 5кОм и ниже считается сильной подтяжкой, 20..100кОм - слабая. Подтягивающие резисторы Ардуино имеют номинал 20..50кОм (конкретное значение подбирается и устанавливается на заводе изготовителе), т.е. являются слабыми. Поэтому в документации к различным устройствам можно увидеть рекомендации использовать более сильные подтягивающие резисторы. Особенно это актуально для устройств, работающих в неблагоприятных условиях или при значительной длине проводников, когда увеличивается вероятность возникновения электромагнитных помех".
Я так понял, что ты считаешь это избыточным для "наших" устройств, если, конечно, кнопка не вынесена метров на 10.

С уважением, Олег Кузнецов.

124 (2019-09-24 23:39:37 отредактировано kvic)

Re: Узел отбора на перистальтическом насосе

Kusnezov Oleg, в общем да.
Подтяжка ради самой себя на внешних резисторах в большинстве случаев будет лишней.
Если только зверские помехи, но тут одними подтяжками скорее всего не обойтись.

Димон ©:

что за трубка там?

Четланин уже уточнил.
Есть у меня смутное подозрение, что в оригинальной поставке стоит трубка 4/2,2 или 4/2,4 (OD/ID).
Либо сильно мягкая 4/2.
Специально пытал китайца на предмет размера, он, как партизан, настаивал на 4/2 мм.
Поверил, ради проверки прикупил 4/2.
У другого китайца. Дабы не поощрять монополистические поползновения.
Пришла на ощупь жёстче оригинала.
Сначала думал не взлетит, ан нет, слегка смазал ПМС-200 (силиконовая смазка такая) и всё пошлО.
Даже перекалибровывать пришлось на совсем чуть-чуть.
Её и оставил, благо в запасе аж 2 метра лежит.
В случае чего замена займет пару минут, не больше.

РК 35х1600

125

Re: Узел отбора на перистальтическом насосе

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

Александр63 ©:

не помешают друг другу?

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

126

Re: Узел отбора на перистальтическом насосе

Четланин, для чего в коде переменная t=i*2?

Я то свою меру отлично знаю, а вот вас... вас я давно наблюдаю. (с)

127

Re: Узел отбора на перистальтическом насосе

Димон, молодец  *THUMBSUP* , заметил. А говорил, что не шаришь в ардуинах.  :D
Это было на этапе разработки, подчистил скетч.

// дисплей ТМ 1637
//  8 microsteps/step
const int stepPin = 2;
 int i=0;
 int ml=0;
#define CLK 9
#define DIO 10
#include "GyverTM1637.h"
GyverTM1637 disp(CLK, DIO);
#include <RotaryEncoder.h>
// Setup a RoraryEncoder for pins A2 and A3:
RotaryEncoder encoder(A2, A3);
void setup()
{
   disp.clear();
 disp.brightness(7);  // яркость минимум =0, стандарт=2,  максимум=7)
    Serial.begin(57600);
  pinMode(stepPin, OUTPUT);
    // You may have to modify the next 2 lines if using other pins than A2 and A3
  PCICR |= (1 << PCIE1);    // This enables Pin Change Interrupt 1 that covers the Analog input pins or Port C.
  PCMSK1 |= (1 << PCINT10) | (1 << PCINT11);  // This enables the interrupt for pin 2 and 3 of Port C.
}
// The Interrupt Service Routine for Pin Change Interrupt 1
// This routine will only be called on any signal change on A2 and A3: exactly where we need to check.
ISR(PCINT1_vect) {
  encoder.tick(); // just call tick() to check the state.
}

void loop()
{
  static int pos = 10;
  int newPos = encoder.getPosition();
  if (pos != newPos) {
       if (newPos <1) newPos=1;
    pos = newPos;
    
   ml=newPos*10;//шаг 10мл
   if (ml>2500)ml=2500;
   i=220000/ml;
 
   disp.displayInt(ml);
  }
    digitalWrite(stepPin, HIGH);
    delayMicroseconds(i);
    digitalWrite(stepPin, LOW);
    delayMicroseconds(i);
}

128

Re: Узел отбора на перистальтическом насосе

Четланин, не шарю ничего, 2 дня всего читаю и пытаюсь понять что у тебя в скетче.
Все что в setup для меня тёмный лес. Что в loop вроде понятно.

Я то свою меру отлично знаю, а вот вас... вас я давно наблюдаю. (с)

129

Re: Узел отбора на перистальтическом насосе

Димон, там часть кода для работы энкодера. Нашёл на просторах инета, сам ничего не понимаю, но работает зараза.

130

Re: Узел отбора на перистальтическом насосе

Четланин, это похоже активация обработки прерываний на пинах А2 и А3 и вызов какой-то функции (из библиотеки наверное) по наличию события на пинах. Короче, темный лес.

Я то свою меру отлично знаю, а вот вас... вас я давно наблюдаю. (с)

131 (2019-09-25 17:15:28 отредактировано Kusnezov Oleg)

Re: Узел отбора на перистальтическом насосе

Мой вариант...
Тумблер трехпозиционный. Постоянно опрашивается в loop. 1-ая  позиция - скорость отбора №1. 2-ая позиция - скорость отбора №2. Позиция "нейтраль" - опрашивается энкодер - скорость устанавливается оператором.
Задействовано прерывание таймера 1 для управления драйвером двигателя и морганием светодиода.
Всё с внешними подтягивающими резисторами.
Пины 2 и 5 используются в качестве GND для удобства монтажа разъемов.
Управление микрошагом и направлением вращения подключены, но не используются. В скетче калибровочного пересчета  "паузы" в мл/час нет.
Для энкодера, таймера и дисплея используются библиотеки
Я не программист. Но как иллюстрация - возможно, вреда не нанесет *DRINK* .


// энкодер с 3 внешнми подтягивающими резисторами 10К

#include "GyverEncoder.h" //  библиотека    https://alexgyver.ru/encoder/
#include <TimerOne.h>
#include <TM1637.h>


// Подключенме энкодера
#define CLK_EN 6
#define DT 7
#define SW 8
#define ENCODER_GND 5 // GND энкодера подключено к этому пину для удобства монтажа

// подключение драйвера шагового двигателя
#define M_0 12 // установка микрошага
#define M_1 13
#define M_2 14
#define STEP_PIN 15
#define DIR_PIN  16  // направление вращения

// подключение трехпозиционного тумблера
#define SW_0 4
#define SW_1 3
#define SW_GND 2 // GND тумблера подключено к этому пину для удобства монтажа

// подключение светодиода
#define LED 9

// подключение TM1637
#define CLK 10 //pin TM1637
#define DIO 11 //pin TM1637


Encoder enc1(CLK_EN, DT, SW); //экземпляр энодера

TM1637 tm1637(CLK,DIO); // экземпляр объекта типа TM1637

int const KOEFF_LED = 50; // отношение (нужно подобрать)скорости смены импульсов на двигателе и скорости мигания светодиода
int const REG_B = 2; // базовая скорость отбора "тела"
int const REG_H = 70; // базовая скорость отбора "голов"

byte inFlagSw = 0; // состояние тумблера
bool MICRO_STEP [3] = {0,0,0}; // задает микрошаг
bool DIRECTION = false; // направление вращения

// служебные переменные для прерывания по таймеру
volatile unsigned int motorTimerCount = 0;
volatile unsigned long int ledTimerCount = 0; 
volatile unsigned int encoderTimerCount = 0;
int const long  TIMER_PERIOD = 250; // период срабатывания таймера
volatile  bool ledState = false; // задает состояние светодиода
volatile  int motorPulsPause = 77; // пауза между импульсами шагового двигателя (тики таймера)
volatile bool flagMotorRun = true;  // запрет/разрешение работы двигателя
volatile bool motorPulse = false; //служебная переменная, чередование пдачи импудьса на мотор 0 1
int const MINIMUM_PAUSE = 1; //максимальная скорость вращение (количество тиков паузы)
int const MAXIMUM_PAUSE = 100; //минимальная скорость вращение (количество тиков паузы


unsigned int ledTimerPause = 0;  // определяет частоту мигания светодиода

int dispDigits = 9999; // переменная для вывода на дисплей

//==============================================================================================
void setup() {
Serial.begin(9600);
setPinsMode (); //  установка и инициализация пинов вынесена в отдельную процедуру
enc1.setType(TYPE2);    // тип энкодера TYPE1 одношаговый, TYPE2 двухшаговый. "Если ваш энкодер работает странно, смените тип"
tm1637.init();// инициализация TM1637
tm1637.set(5);//установка яркости дисплея 0-7
tm1637.clearDisplay(); 
Timer1.initialize(TIMER_PERIOD); // инициализация таймера 1, период  
Timer1.attachInterrupt(timerInterrupt, TIMER_PERIOD); // задаем обработчик прерываний

}
//==============================================================================================
void loop() {
//если тумблер в положенн "вверх" устанавливаем скорость вращения regB     
if ( ! digitalRead(SW_0)){
  motorPulsPause = REG_B;
  if ( !(inFlagSw == 1)) {
    dispDigits = motorPulsPause;
    displayShow(); // выводим значение на дисплей
  }
  inFlagSw = 1;
 }
//если тумблер в положенн "вниз" устанавливаем скорость вращения regH
if ( ! digitalRead(SW_1)){
motorPulsPause = REG_H;
 if ( !(inFlagSw == 2)) {
    dispDigits = motorPulsPause;
     displayShow(); // выводим значение на дисплей
  }
  inFlagSw = 2;
 }
//если тумблер в положенн "среднее"  читаем энкодер
if ( digitalRead(SW_0) &  digitalRead(SW_1) ){
  inFlagSw = 3;
  readEncoder();
}
}
//==============================================================================================
void readEncoder(){
  if (enc1.isRight()) motorPulsPause++;      // если был поворот направо, увеличиваем на 1
  if (enc1.isLeft()) motorPulsPause--;      // если был поворот налево, уменьшаем на 1
  if (enc1.isFastR()) motorPulsPause = motorPulsPause + 10; // если был быстрый поворот направо, увеличиваем на 10
  if (enc1.isFastL()) motorPulsPause = motorPulsPause - 10; // если был быстрый поворот налево, уменьшаем на 10
 
  
  if (enc1.isRightH()) {
    digitalWrite (LED , true);  // если было удержание + поворот направо,
    flagMotorRun = true; // разрешаем вращение
  }
  if (enc1.isLeftH()) {
    digitalWrite (LED , false); // если было удержание + поворот налево, 
    flagMotorRun = false; // запрещаем вращение
  }

   if (enc1.isTurn()) {       // если был совершён поворот (индикатор поворота в любую сторону)
 // проверяем границы диапазона
      if ( motorPulsPause <= MINIMUM_PAUSE){
          motorPulsPause  = MINIMUM_PAUSE; 
      }
      if ( motorPulsPause > MAXIMUM_PAUSE){
         motorPulsPause  = MAXIMUM_PAUSE; 
      }

   
   dispDigits = motorPulsPause; 
   displayShow();// выводим значение при повороте
 //   Serial.println(motorPulsPause);  // выводим значение при повороте
  }  
}
void displayShow(){
 tm1637.clearDisplay(); 
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// Внимание ! Здесь можно пересчитать паузу в милилитры в час при калибровке
 tm1637.display(dispDigits);  
 
 }


void timerInterrupt() {
 enc1.tick();
 motorTimerCount++;
 if ( motorTimerCount >= motorPulsPause) {
 // после того как количество тиков таймера сравняется с motorPulsPause   
// изменяется на противоположный уровень на STEP_PIN и сбрасывается счетчик
    motorTimerCount = 0;
    if ( flagMotorRun) { 
        motorPulse = !motorPulse;
          
        digitalWrite (STEP_PIN , motorPulse);
 // управление миганием светодиода (забавы ради)        
 // пусть мигает примерно с частотой падания капель        
       ledTimerCount++;
       if ( ledTimerCount >= motorPulsPause * KOEFF_LED) {
        ledTimerCount = 0;
        ledState = !ledState;
        digitalWrite (LED , ledState);
         }
       }
   }
}

void setPinsMode () {

 pinMode(LED, OUTPUT);
 digitalWrite (LED , true);
 
 pinMode(M_0, OUTPUT);
 pinMode(M_1, OUTPUT);
 pinMode(M_2, OUTPUT); 
 pinMode(STEP_PIN, OUTPUT); 
 pinMode(DIR_PIN, OUTPUT);  
 pinMode(ENCODER_GND, OUTPUT);  
 pinMode(SW_GND, OUTPUT);

 pinMode(SW_0, INPUT);
 pinMode(SW_1, INPUT);

 digitalWrite (M_0 , MICRO_STEP [0]);
 digitalWrite (M_1 , MICRO_STEP [1]); 
 digitalWrite (M_2 , MICRO_STEP [2]);
 digitalWrite (DIR_PIN , DIRECTION);
 digitalWrite (ENCODER_GND , false);
 digitalWrite (SW_GND , false);
  
}
  • схема.jpg
    size: 170.99Кб type: jpg
  • схема2.jpg
    size: 151.53Кб type: jpg
С уважением, Олег Кузнецов.

132

Re: Узел отбора на перистальтическом насосе

Kusnezov Oleg, насколько я понял, от клапана ты не отказался? Чем не устраивает останов двигателя? Это равносильно закрытию клапана.

133

Re: Узел отбора на перистальтическом насосе

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

С уважением, Олег Кузнецов.

134

Re: Узел отбора на перистальтическом насосе

Четланин ©:

работает зараза

Димон ©:

темный лес

Да там же всё написано:

Четланин ©:

PCICR |= (1 << PCIE1);    // This enables Pin Change Interrupt 1 that covers the Analog input pins or Port C.

Разрешает прерывание по изменению уровня на выводах порта С.

Четланин ©:

PCMSK1 |= (1 << PCINT10) | (1 << PCINT11);  // This enables the interrupt for pin 2 and 3 of Port C.

А это маска того прерывания.
Чтобы оно происходило только при изменениях на разрядах 2 или 3 порта С.
К которым и подключен тот энкодер.
А на изменение состояния всех остальных разрядов порта С кладётся болт с прибором.
Ибо в данной ситуации оно не надо.
----
В даташите описания этого см.:
13.2.4 PCICR – Pin Change Interrupt Control Register
13.2.7 PCMSK1 – Pin Change Mask Register 1
14.3.2 Alternate Functions of Port C
----
Т.е. вращение энкодера вызывает прерывание, а в прерывании уже идёт обработка и выдача чего-то куда-то.
В общем, не тратится время процессора на опрос состояния энкодера, он сам подаёт заявку на обслуживание.
Как то так.

РК 35х1600

135

Re: Узел отбора на перистальтическом насосе

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

Я то свою меру отлично знаю, а вот вас... вас я давно наблюдаю. (с)

136

Re: Узел отбора на перистальтическом насосе

kvic, спасибо за разъяснения, будем грызть гранит науки. *En*
Kusnezov Oleg свой скетч выложил, очередь за тобой.

137

Re: Узел отбора на перистальтическом насосе

Четланин ©:

свой скетч выложил, очередь за тобой

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

С уважением, Олег Кузнецов.

138 (2019-09-25 23:45:15 отредактировано kvic)

Re: Узел отбора на перистальтическом насосе

Четланин, увы, у меня нет скетча.  :[
Kusnezov Oleg прав:

Kusnezov Oleg ©:

kvic  скетчи писать не умеет

*DONT_KNOW*
---
Код не буду выкладывать, ибо там самому страшно.
У меня в одной ардуине замешан некий автономный эквивалент ТМАС и управление этим насосом.
Жуткий гибрид.  :o
Причём бОльшая часть программных бредней посвящена выводу на дисплей.
Может быть как-нибудь...

Димон ©:

что такое порт С - убейте не понимаю

Да это просто ноги ввода/вывода разделены на группы по 8 разрядов и обозваны портами.
Для удобства работы ибо байт = 8 бит.
И, соответственно, обозваны A,B,C,D,E в разных контроллерах.
В ардуино нано наружу смотрят порты B,C,D, других нет.

РК 35х1600

139

Re: Узел отбора на перистальтическом насосе

kvic ©:

Может быть как-нибудь...

Подождём...твою скетч. :)

140

Re: Узел отбора на перистальтическом насосе

Четланин, там уже не скетч, там придётся целую тему городить.
А я ишшо не готов.
И функционал ещё не весь реализован.

РК 35х1600