Re: Узел отбора на перистальтическом насосе
В двух словах можно пояснить ?
Не... Я лучше тебя послушаю (серьезно). Везде вроде говорится, что встроенные слишком большое сопротивление имеют. Что такое слишком? Я не знаю...
Форум самогонщиков, винокуров, виноделов, пивоваров, бондарей и очень хороших людей |
с 121 по 140 из 1 059
В двух словах можно пояснить ?
Не... Я лучше тебя послушаю (серьезно). Везде вроде говорится, что встроенные слишком большое сопротивление имеют. Что такое слишком? Я не знаю...
Kusnezov Oleg, мне тоже особо на эту тему сказать нечего, я ими просто пользуюсь.
Думал, может где-то что-то упустил.
Вот и поинтересовался.
слишком большое сопротивление имеют
Я это утверждение тоже не воспринимаю без конкретного уточнения требований.
Для чего-либо высокоскоростного может быть.
Завал фронтов, запаздывание по фазе, прочие высокомудрые слова...
----
В наших медленных процессах предлагаю не заморачиваться на несущественных (по моему мнению) деталях.
kvic, ну вот, что меня в свое время смутило (типичная цитата):
"Как выбрать номинал для подтягивающего резистора? Общая рекомендация - это, как правило, 10кОм. Где-то от 5кОм и ниже считается сильной подтяжкой, 20..100кОм - слабая. Подтягивающие резисторы Ардуино имеют номинал 20..50кОм (конкретное значение подбирается и устанавливается на заводе изготовителе), т.е. являются слабыми. Поэтому в документации к различным устройствам можно увидеть рекомендации использовать более сильные подтягивающие резисторы. Особенно это актуально для устройств, работающих в неблагоприятных условиях или при значительной длине проводников, когда увеличивается вероятность возникновения электромагнитных помех".
Я так понял, что ты считаешь это избыточным для "наших" устройств, если, конечно, кнопка не вынесена метров на 10.
Kusnezov Oleg, в общем да.
Подтяжка ради самой себя на внешних резисторах в большинстве случаев будет лишней.
Если только зверские помехи, но тут одними подтяжками скорее всего не обойтись.
что за трубка там?
Четланин уже уточнил.
Есть у меня смутное подозрение, что в оригинальной поставке стоит трубка 4/2,2 или 4/2,4 (OD/ID).
Либо сильно мягкая 4/2.
Специально пытал китайца на предмет размера, он, как партизан, настаивал на 4/2 мм.
Поверил, ради проверки прикупил 4/2.
У другого китайца. Дабы не поощрять монополистические поползновения.
Пришла на ощупь жёстче оригинала.
Сначала думал не взлетит, ан нет, слегка смазал ПМС-200 (силиконовая смазка такая) и всё пошлО.
Даже перекалибровывать пришлось на совсем чуть-чуть.
Её и оставил, благо в запасе аж 2 метра лежит.
В случае чего замена займет пару минут, не больше.
Проверил свою схему на предмет подтягивающих резисторов: включены программно, наверное в библиотеке.
не помешают друг другу?
Если ставить модуль энкодера с встроенными подтягивающими резисторами, ничего страшного не будет.
Четланин, для чего в коде переменная t=i*2?
Димон, молодец , заметил. А говорил, что не шаришь в ардуинах.
Это было на этапе разработки, подчистил скетч.
// дисплей ТМ 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);
}
Четланин, не шарю ничего, 2 дня всего читаю и пытаюсь понять что у тебя в скетче.
Все что в setup для меня тёмный лес. Что в loop вроде понятно.
Димон, там часть кода для работы энкодера. Нашёл на просторах инета, сам ничего не понимаю, но работает зараза.
Четланин, это похоже активация обработки прерываний на пинах А2 и А3 и вызов какой-то функции (из библиотеки наверное) по наличию события на пинах. Короче, темный лес.
Мой вариант...
Тумблер трехпозиционный. Постоянно опрашивается в loop. 1-ая позиция - скорость отбора №1. 2-ая позиция - скорость отбора №2. Позиция "нейтраль" - опрашивается энкодер - скорость устанавливается оператором.
Задействовано прерывание таймера 1 для управления драйвером двигателя и морганием светодиода.
Всё с внешними подтягивающими резисторами.
Пины 2 и 5 используются в качестве GND для удобства монтажа разъемов.
Управление микрошагом и направлением вращения подключены, но не используются. В скетче калибровочного пересчета "паузы" в мл/час нет.
Для энкодера, таймера и дисплея используются библиотеки
Я не программист. Но как иллюстрация - возможно, вреда не нанесет .
// энкодер с 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);
}
Kusnezov Oleg, насколько я понял, от клапана ты не отказался? Чем не устраивает останов двигателя? Это равносильно закрытию клапана.
Четланин, от клапана конечно отказался (из скетча этого действительно не видно). Пока никак не определюсь как между электронными блоками связь организовать. Вариантов много... Пробую потихоньку , развлекаюсь .
работает зараза
темный лес
Да там же всё написано:
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
----
Т.е. вращение энкодера вызывает прерывание, а в прерывании уже идёт обработка и выдача чего-то куда-то.
В общем, не тратится время процессора на опрос состояния энкодера, он сам подаёт заявку на обслуживание.
Как то так.
kvic, все что ты пояснил, теоретически мне понятно, и по-аглицки боле-мене розумею. Но почему код именно такой и что такое порт С - убейте не понимаю.
И если скетч Четланина в принципе я понимаю, для чего там какая переменная и что с ней делается, то скетч Олега вообще не вкуриваю.
Ну это хрен с ним, буду пока в качестве потребителя. Может со временем чему-то научусь.
kvic, спасибо за разъяснения, будем грызть гранит науки.
Kusnezov Oleg свой скетч выложил, очередь за тобой.
свой скетч выложил, очередь за тобой
Четланин, зря ты так kvic скетчи писать не умеет, не дай бог свой код выложит... Аж страшно...
Четланин, увы, у меня нет скетча.
Kusnezov Oleg прав:
kvic скетчи писать не умеет
---
Код не буду выкладывать, ибо там самому страшно.
У меня в одной ардуине замешан некий автономный эквивалент ТМАС и управление этим насосом.
Жуткий гибрид.
Причём бОльшая часть программных бредней посвящена выводу на дисплей.
Может быть как-нибудь...
что такое порт С - убейте не понимаю
Да это просто ноги ввода/вывода разделены на группы по 8 разрядов и обозваны портами.
Для удобства работы ибо байт = 8 бит.
И, соответственно, обозваны A,B,C,D,E в разных контроллерах.
В ардуино нано наружу смотрят порты B,C,D, других нет.
Может быть как-нибудь...
Подождём...твою скетч.
Четланин, там уже не скетч, там придётся целую тему городить.
А я ишшо не готов.
И функционал ещё не весь реализован.
с 121 по 140 из 1 059