261

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

dmytry ©:

хоть и дороже чем кран

Чем кран и клапан. А может и не дороже.

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

262

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

Kusnezov Oleg ©:

Чем кран и клапан. А может и не дороже.

А если посчитать сборку управления клапаном, то не дороже.
Вообщем надо тему оформлять. :)

263 (2019-12-10 23:39:22 отредактировано brc)

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

kvic ©:

Сам скетч без изменений

Предложение автору: управление по i2c(на рассмотрение)
переносим переменные в структуру

typedef struct 
{
   uint16_t rate;  //int16  - не думаем про выравнивание в памяти(+1 байт)
   uint16_t drinkVolume    = 0;             // Шаг рОзлива
   uint16_t totalVolume    = 0;             // Общий объем отбора мл
   uint16_t currentMode;   
}slave_data_t;
//команда от мастера
typedef struct 
{
   uint16_t cmd;//int16...выравнивание
   uint16_t val;
}master_cmd_t;
#define I2C_ADDR (0x1e) //наш адрес
slave_data_t dz;

void requestEvent(){
//все данные в структуре, просто выдаем...
  Wire.write((uint8_t*)&dz,sizeof(dz));
}


//пару дефайнов
#define SET_RATE              21              //
#define CLEAR_COUNTERS        22              //
//Аля модбус
void receiveEvent(int howMany) {
  master_cmd_t cmd;
  uint8_t data[howMany];
  int x=0;
  while (Wire.available()>0) { // loop through all but the last
    data[x] = Wire.read(); // receive byte as a character
    x++;
  }
  if ((howMany)==sizeof(cmd)){
      memcpy(&cmd,&data,sizeof(cmd));
      switch (cmd.cmd){
        case RUNNING:{
          resumeRun();
        }
        break;        
        case PAUSED_BY_EXT:{
          dz.currentMode = cmd.cmd;
        }
        break;
        case SELECT_VOL:{
          dz.drinkVolume=cmd.val;
          drinkBackCounter = (uint32_t)dz.drinkVolume * stepsForOneMl - 1;
        }
        break;            
        case CLEAR_COUNTERS:{
          stepsCount = 0;
          dz.totalVolume = 0;
          drinkBackCounter = (uint32_t)dz.drinkVolume * stepsForOneMl - 1;
        }
        break;      
        case SET_RATE:{
          if (cmd.val>maximumRate)dz.rate=maximumRate;
          else dz.rate=cmd.val;
          calcOCR1A();
          resumeRun();
        }
        break;   
               
      }
  }
  calcTotalVolume();
//все данные в структуре, заносить ничего не надо
}


void setup()
{
  Wire.begin(I2C_ADDR);
  Wire.onRequest(requestEvent);
  Wire.onReceive(receiveEvent);
//...
}

Забыл, есть проблема, слетает слейв адрес.
Кто портит регистр TWAR  - не нашел.
Временный костыль:

#define TWI_SA (I2C_ADDR<<1)
//проверяем в loop
void loop()
{
if (TWAR!=TWI_SA) TWAR=TWI_SA;
///...

}

264 (2019-12-11 07:13:04 отредактировано kvic)

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

brc ©:

Предложение автору: управление по i2c(на рассмотрение)

А что там рассматривать ?
Лично я приветствую.
Ибо:

kvic ©:

Всё на свой страх и риск с осознанием возможных последствий.
Так же всё отдаётся в свободное использование и модификацию.

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

РК 35х1600

265 (2019-12-11 00:23:32 отредактировано brc)

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

kvic ©:

Только просьба модифицированный скетч выкладывать целиком.

Внимание!!!Пины переназначены

#include <EEPROM.h>                           // Стандартная библиотека
#include "GyverEncoder.h"                     // Библиотеки с сайта 
#include "GyverTM1637.h"                      // не могу публиковать ссылки
#include "directTimers.h"                     //не могу публиковать ссылки 
#include "Wire.h"
#include <avr/wdt.h>
//------------------------------------------------------------------------------------------
//**********************************************************************************************************
#define STEP8     // Закомментировать, если используется шаг/4, раскомментировать, если используется шаг/8 *
//**********************************************************************************************************
//--------------------------- Настройка железа ---------------------------------------------
// Подключение энкодера
#define SW1 A2                                // Сигнал энкодера 1 // Если кручение влево/вправо перепутано,
#define SW2 A1                               // Сигнал энкодера 2 // можно поменять местами или изменить сигнал DIR на DRV8825
#define KEY A3                                // Кнопка энкодера
Encoder enc1(SW1, SW2, KEY, TYPE1);

// Подключение TM1637
#define CLK 13                                // Тактовые импульсы TM1637
#define DIO 12                                // Данные для TM1637
GyverTM1637 disp(CLK, DIO);

// Подключение DRV8825
#define STEP 2                                // Тактовые импульсы на драйвер ШД
// Внешнее управление
#define TMAS  5                               // Сюда подключаем управление от TMAS, низкий уровень вызовет паузу
#define LED   13                              // Встроенный светодиод
#define PIEZO 11
#define soundA B00000101
#define soundB B00011111


//--------------------------------------------------------------------------------------
// Наименования режимов работы
//----------------------------------------------
#define RUNNING               0               //
#define PAUSED                1               //
#define PAUSED_BY_EXT         2               //
#define PAUSED_BY_VOL         3               //
#define SELECT_VOL            4               //
#define TUNING                10              //
#define TUNING_PAUSE          11              //
#define SET_RATE              21              //
#define CLEAR_COUNTERS        22              //
//----------------------------------------------
// Константы
//----------------------------------------------
#define maximumRate           2500            //  Максимальная скорость отбора мл/час
#define rateStep              10              //  Мелкий шаг регулировки отбора
#define rateMidStep           50              //  Средний шаг регулировки отбора
#define rateBigStep           100             //  Крупный шаг регулировки отбора
#define volStep               10              //  Шаг регулировки дозатора
#define volMidStep            50              //  Средний шаг регулировки дозатора
#define volBigStep            500             //  Крупный шаг регулировки дозатора
#define maxDrinkVol           5000            //  Максимальный объем, выдаваемый дозатором
#define defaultDrink          0               //  Объем дозатора по умолчанию. 0 - без ограничения.
#define defaultStepsFor100ml  400000          //  Количество шагов потребное для отбора 100 мл по умолчанию при шаге/4
#define minStepsFor100ml      150000          //  Минимально возможное число шагов для отбора 100 мл при шаге/4    
#ifdef STEP8
#define defaultStepsFor100ml  800000          //  Количество шагов потребное для отбора 100 мл по умолчанию при шаге/8
#define minStepsFor100ml      550000          //  Минимально возможное число шагов для отбора 100 мл при шаге/8
#endif
//----------------------------------------------
// Переменные
//----------------------------------------------
unsigned long stepsFor100ml;                  //  Количество шагов потребное для отбора 100 мл
unsigned int  stepsForOneMl;                  //  Количество шагов потребное для отбора 1 мл
unsigned long stepsCount     = 0;             //  Счетчик количества шагов
unsigned long drinkBackCounter = 0;           //  Обратный счётчик шагов дозатора
unsigned long temp           = 0;             //  Временная переменная для разнообразных нужд
unsigned int  timer1EndValue = 65535;         //  Значение при котором происходит прерывание от таймера 1 (11739)
byte          thousandth     = 0;             //
byte          tenth          = 0;             //
byte          backCounter0   = 0;             //
byte          backCounter1   = 0;             //
byte          counterA       = 0;             //
//byte          currentMode    = RUNNING;       // Текущий режим работы
byte          pattern        = 0;             //
//int           rate           = 0;             // Скорость отбора мл/час 0 - maximumRate
//int           totalVolume    = 0;             // Общий объем отбора мл
//int           drinkVolume    = 0;             // Шаг рОзлива
bool          newSecond      = false;
bool          newTenth       = false;
bool          stepEnabled    = false;
bool          tmasStop       = false;
bool          drinkStop      = false;
bool          infoEnable     = false;
bool          bc0flag        = false;
bool          bc1flag        = false;
bool          sndFlag        = false;

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

typedef struct 
{
   uint16_t rate;
   uint16_t drinkVolume    = 0;             // Шаг рОзлива
   uint16_t totalVolume    = 0;             // Общий объем отбора мл
   uint16_t currentMode;   
}slave_data_t;

typedef struct 
{
   uint16_t cmd;
   uint16_t val;
}master_cmd_t;

void resumeRun();
void increaseRate();
void decreaseRate();
void calcOCR1A();
void calcTotalVolume();
void oneTenthSub(); 
void tryToSaveStepsFor100ml(); 
#define I2C_ADDR (0x1e)
#define TWI_SA (I2C_ADDR<<1)

slave_data_t dz;
/*
void set_var(){
  dz.rate           = 0;             // Скорость отбора мл/час 0 - maximumRate
  dz.totalVolume    = 0;             // Общий объем отбора мл
  dzdrinkVolume    = 0; 
  currentMode    = RUNNING;
}
*/
void requestEvent(){
  Wire.write((uint8_t*)&dz,sizeof(dz));
}
void receiveEvent(int howMany) {
  master_cmd_t cmd;
  uint8_t data[howMany];
  int x=0;
  while (Wire.available()>0) { // loop through all but the last
    data[x] = Wire.read(); // receive byte as a character
    x++;
  }
  if ((howMany)==sizeof(cmd)){
      memcpy(&cmd,&data,sizeof(cmd));
      switch (cmd.cmd){
        case RUNNING:{
          resumeRun();
        }
        break;        
        case PAUSED_BY_EXT:{
          dz.currentMode = cmd.cmd;
        }
        break;
        case SELECT_VOL:{
          dz.drinkVolume=cmd.val;
          drinkBackCounter = (uint32_t)dz.drinkVolume * stepsForOneMl - 1;
        }
        break;            
        case CLEAR_COUNTERS:{
          stepsCount = 0;
          dz.totalVolume = 0;
          drinkBackCounter = (uint32_t)dz.drinkVolume * stepsForOneMl - 1;
        }
        break;      
        case SET_RATE:{
          if (cmd.val>maximumRate)dz.rate=maximumRate;
          else dz.rate=cmd.val;
          calcOCR1A();
          resumeRun();
        }
        break;   
               
      }
  }
  calcTotalVolume();
}

void setup()
{
  Wire.begin(I2C_ADDR);
  Wire.onRequest(requestEvent);
  Wire.onReceive(receiveEvent);
  Wire.setTimeout( 500 );

  Serial.begin(115200);
  // Настройка входов и выходов
  pinMode(STEP, OUTPUT);
  pinMode(CLK,  OUTPUT);
  pinMode(DIO,  OUTPUT);
  pinMode(LED,  OUTPUT);
  pinMode(PIEZO, OUTPUT);
  pinMode(SW1,  INPUT_PULLUP);
  pinMode(SW2,  INPUT_PULLUP);
  pinMode(KEY,  INPUT_PULLUP);
  pinMode(TMAS, INPUT_PULLUP);
  digitalWrite(STEP, 1);
  digitalWrite(PIEZO, 1);

  // Настройка таймера 1, он задаёт частоту шагания двигателя
  TIMER1_setClock(PRESCALER_64);            // Частота тактирования таймера 1: 16/64 = 0.25 МГц при шаге/4
#ifdef STEP8
  TIMER1_setClock(PRESCALER_8);           // Частота тактирования таймера 1: 16/8 = 2 МГц при шаге/8
#endif
  TIMER1_setMode(CTC_MODE);                 // Режим работы таймера - сравнение со значением, прерывание и рестарт
  TIMER1_COMPA_setValue(timer1EndValue);    // Значение для сравнения
  TIMER1_attach_COMPA();                    // Прерывание от таймера 1 по сравнению

  // Настройка таймера 2, он отсчитывает временные интервалы для работы программы
  TIMER2_setClock(PRESCALER_128);           // Частота тактирования таймера 2: 16/128 = 0.125 МГц
  TIMER2_setMode(CTC_MODE);                 // включаем сброс таймера по совпадению
  TIMER2_COMPA_setValue(124);               // настраиваем следование прерываний с частотой 1000 гц
  TIMER2_attach_COMPA();                    // прерывание с опросом энкодера

  // Настройка дисплея и вывод привета.
  disp.clear();
  disp.brightness(1);

  int8_t welcome_banner[] = { _empty, _empty, _dash, _dash, _r, _u, _n, _dash, _dash, _empty, _empty};
  disp.runningString(welcome_banner, sizeof(welcome_banner), 200);
  disp.displayInt(0);
  dz.rate = 0;
  dz.totalVolume = 0;
  stepsCount = 0;

  // Попытка прочитать установки из EEPROM
  EEPROM.get(0, stepsFor100ml);
  if ((stepsFor100ml < minStepsFor100ml) or (stepsFor100ml > minStepsFor100ml * 4)) // Если в EEPROM не установлено число шагов на 100 мл, то
  {
    stepsFor100ml = defaultStepsFor100ml;                     // Установим число шагов на 100 мл по умолчанию
  }
  stepsForOneMl = round((float)stepsFor100ml / 100);
  calcOCR1A();
  dz.drinkVolume = defaultDrink;
  drinkBackCounter = (uint32_t)dz.drinkVolume * stepsForOneMl - 1;
  if (!digitalRead(KEY)) {
    dz.currentMode = TUNING;
    byte troll[4] = {_t, _u, _n, _E};
    disp.displayByte(troll);
    backCounter0 = 0;
    infoEnable = false;
    enc1.isHolded();
  }
  else {
    dz.currentMode = RUNNING;
    infoEnable = true;
  }
  Serial.println(dz.drinkVolume);          //
  Serial.println(stepsFor100ml);        //
  Serial.println(stepsForOneMl);        //
  Serial.println(drinkBackCounter);     //
  Serial.println("--READY--");
  //Serial.end();
  //wdt_enable(WDTO_8S);
}
//--------------------------------------------------------------------------------------
//---------------------- Начало основного цикла ----------------------------------------

void loop()
{
if (TWAR!=TWI_SA) TWAR=TWI_SA;
  if (newSecond) {
    newSecond = false;

  if (infoEnable)
  {
    calcTotalVolume();
    disp.displayInt(dz.totalVolume % 10000);
  }
  }
  //C;
  if (newTenth)  {
    newTenth = false;
    oneTenthSub();
  }

  if (bc0flag)   {
    bc0flag = false;
    infoEnable = true;
  }

  //---------------------------------------------------------------
  switch (dz.currentMode)
  {
    //-------------------------------------------------------------
    // Режим калибровки насоса основной экран ---------------------
    //-------------------------------------------------------------
    case TUNING:            // Настройка количества шагов на 100 мл.
      {
        infoEnable = false;
        //--------------------
        if (bc1flag)
        {
          bc1flag = false;
          byte troll[4] = {_t, _u, _n, _E};
          disp.displayByte(troll);
        }
        //--------------------
        if (enc1.isRight()) // Поворот по часовой стрелке увеличивает частоту шагов
        {
          increaseRate();
          stepEnabled = true;
          disp.displayInt(dz.rate);
          backCounter1 = 20;
        }
        //--------------------
        if (enc1.isLeft()) // Поворот против часовой стрелки уменьшает частоту шагов
        {
          decreaseRate();
          if (dz.rate != 0)
          {
            stepEnabled = true;
          }
          disp.displayInt(dz.rate);
          backCounter1 = 20;
        }
        //--------------------
        if (enc1.isClick())
        {
          stepEnabled = false;
          dz.currentMode = TUNING_PAUSE;
          byte troll[4] = {_t, _P, _A, _u};
          disp.displayByte(troll);
        }
        //--------------------
        if (enc1.isHolded())
        {
          setup();
        }
        //--------------------
      }
      break;
    //-------------------------------------------------------------
    // Пауза в режиме калибровки насоса ---------------------------
    //-------------------------------------------------------------
    case TUNING_PAUSE:
      {
        //--------------------
        if (bc1flag)
        {
          bc1flag = false;
          counterA = 0;
          byte troll[4] = {_t, _P, _A, _u};
          disp.displayByte(troll);
        }
        //--------------------
        if (enc1.isRight()) // Поворот по часовой стрелке увеличивает частоту шагов
        {
          increaseRate();
          disp.displayInt(dz.rate);
          backCounter1 = 20;
        }
        //--------------------
        if (enc1.isLeft()) // Поворот против часовой стрелки уменьшает частоту шагов
        {
          decreaseRate();
          disp.displayInt(dz.rate);
          backCounter1 = 20;
        }
        //--------------------
        if (enc1.isClick())
        {
          stepEnabled = true;
          dz.currentMode = TUNING;
          byte troll[4] = {_t, _u, _n, _E};
          disp.displayByte(troll);
        }
        //--------------------
        if (enc1.isHolded())
        {
          stepsCount = 0;
          dz.totalVolume = 0;
          int8_t welcome_banner[] = {_c, _o, _u, _n, _t, _E, _r, _S, _empty, _c, _l, _E, _a, _r, _E, _d};
          disp.runningString(welcome_banner, sizeof(welcome_banner), 200);
          bc1flag = true;
        }
        //--------------------
        if (enc1.isRightH())
        {
          tryToSaveStepsFor100ml();
        }
        //--------------------
        if (enc1.isLeftH())
        {
          tryToSaveStepsFor100ml();
        }
        //--------------------
      }
      break;
    //-------------------------------------------------------------
    // Основной режим. Идёт отбор. --------------------------------
    //-------------------------------------------------------------
    case RUNNING:
      {
        //--------------------
        if (enc1.isClick()) // Клик на кнопку (режим RUNNING)
        {
          stepEnabled = false;
          dz.currentMode = PAUSED;
          byte troll[4] = {_S, _t, _o, _P};
          disp.displayByte(troll);
          backCounter0 = 0;
          infoEnable = false;
        }
        //--------------------
        if (tmasStop)      // Внешний сигнал, появление (режим RUNNING)
        {
          stepEnabled = false;
          dz.currentMode = PAUSED_BY_EXT;
          byte troll[4] = {_o, _u, _t, _S};
          disp.displayByte(troll);
          backCounter0 = 0;
          infoEnable = false;
          pattern = soundB;
          sndFlag = true;
        }
        //--------------------
        if (drinkStop)     // Налит запрошенный объем (режим RUNNING)
        {
          stepEnabled = false;
          drinkStop = false;
          dz.currentMode = PAUSED_BY_VOL;
          drinkBackCounter = (uint32_t)dz.drinkVolume * stepsForOneMl - 1;
          int8_t troll[4] = {_d, _o, _n, _E};
          disp.twistByte(troll, 20);
          //disp.displayByte(troll);
          backCounter0 = 0;
          infoEnable = false;
          pattern = soundA;
          sndFlag = true;
        }
        //--------------------
        if (enc1.isRight())     // Вращение по часовой (режим RUNNING)
        {
          if (backCounter0 != 0)
          {
            increaseRate();
            stepEnabled = true;
          }
          disp.displayInt(dz.rate);
          infoEnable = false;
          backCounter0 = 20;
        }
        //--------------------
        if (enc1.isLeft())      // Вращение против часовой (режим RUNNING)
        {
          if (backCounter0 != 0)
          {
            decreaseRate();
            if (dz.rate != 0)
            {
              stepEnabled = true;
            }
          }
          disp.displayInt(dz.rate);
          infoEnable = false;
          backCounter0 = 20;
        }
        //--------------------
        if (enc1.isHolded())    // Удержание кнопки (режим RUNNING)
        {
          if ((dz.rate == 0) and (stepsCount != 0))
          {
            stepsCount = 0;
            dz.totalVolume = 0;
            drinkBackCounter = (uint32_t)dz.drinkVolume * stepsForOneMl - 1;
            int8_t welcome_banner[] = {_c, _o, _u, _n, _t, _E, _r, _S, _empty, _c, _l, _e, _a, _r, _e, _d};
            disp.runningString(welcome_banner, sizeof(welcome_banner), 200);
          }
          else
          {
            if (infoEnable) {
              if (dz.drinkVolume == 0)
              {
                byte troll[4] = {_empty, _i, _n, _f};
                disp.displayByte(troll);
              }
              else
              {
                disp.displayInt((drinkBackCounter + 1) / stepsForOneMl);
              }
            }
            infoEnable = false;
            backCounter0 = 20;
          }
        }
        //--------------------
      }
      break;
    //-------------------------------------------------------------
    // Остановка по нажатию кнопки --------------------------------
    //-------------------------------------------------------------
    case PAUSED:
      {
        //--------------------
        if (bc1flag)
        {
          bc1flag = false;
          //stepEnabled = false;
          byte troll[4] = {_S, _t, _o, _P};
          disp.displayByte(troll);
          infoEnable = false;
        }
        //--------------------
        if (enc1.isClick())
        {
          resumeRun();
        }
        //--------------------
        if (enc1.isRight())
        {
          if (backCounter1 != 0)
          {
            increaseRate();
          }
          disp.displayInt(dz.rate);
          infoEnable = false;
          backCounter1 = 20;
        }
        //--------------------
        if (enc1.isLeft())
        {
          if (backCounter1 != 0)
          {
            decreaseRate();
          }
          disp.displayInt(dz.rate);
          infoEnable = false;
          backCounter1 = 20;
        }
        //--------------------
        if (enc1.isHolded())
        {
          infoEnable = false;
          dz.currentMode = SELECT_VOL;
          byte troll[4] = {_S, _t, _E, _P};
          disp.displayByte(troll);
        }
        //--------------------
      }
      break;
    //-------------------------------------------------------------
    // Остановка по внешнему сигналу ------------------------------
    //-------------------------------------------------------------
    case PAUSED_BY_EXT:
      {
        if (!tmasStop)
        {
          sndFlag = false;
          //backCounter1 = 10;
          resumeRun();
        }
        //--------------------
        if (enc1.isRight() || enc1.isLeft() || enc1.isClick())
        {
          //backCounter1 = 250;
          sndFlag = false;
        }
        //--------------------
        /*
        if ((!sndFlag) && (backCounter1 == 0))
        {
          sndFlag = true;
        }*/
      }
      break;
    //-------------------------------------------------------------
    // Остановка по достижению заданного разового объема отбора ---
    //-------------------------------------------------------------
    case PAUSED_BY_VOL:
      {
        //--------------------
        if (enc1.isHolded())
        {
          infoEnable = false;
          dz.currentMode = SELECT_VOL;
          byte troll[4] = {_S, _t, _E, _P};
          disp.displayByte(troll);
          sndFlag = false;                  // Заткнуть пищалку
        }
        //--------------------
        if (enc1.isClick())
        {
          sndFlag = false;                  // Заткнуть пищалку
          resumeRun();
        }
        //--------------------
        if (enc1.isRight())
        {
          sndFlag = false;                  // Заткнуть пищалку
        }
        //--------------------
        if (enc1.isLeft())
        {
          sndFlag = false;                  // Заткнуть пищалку
        }
        //--------------------
      }
      break;
    //-------------------------------------------------------------
    // Режим выбора разового объема -------------------------------
    //-------------------------------------------------------------
    case SELECT_VOL:
      {
        //--------------------
        if (bc1flag)
        {
          bc1flag = false;
          byte troll[4] = {_S, _t, _E, _P};
          disp.displayByte(troll);
        }
        //--------------------
        if (enc1.isHolded())
        {
          drinkBackCounter = (uint32_t)dz.drinkVolume * stepsForOneMl - 1;
          resumeRun();
        }
        //--------------------
        if (enc1.isClick())
        {
          dz.currentMode = PAUSED;
          drinkBackCounter = (uint32_t)dz.drinkVolume * stepsForOneMl - 1;
          byte troll[4] = {_S, _t, _o, _P};
          disp.displayByte(troll);
        }
        //--------------------
        if (enc1.isRight())
        {
          if (backCounter1 != 0)
          {
            if (dz.drinkVolume >= 1000) {
              dz.drinkVolume = dz.drinkVolume + volBigStep;
            } else {
              if (dz.drinkVolume >= 100) {
                dz.drinkVolume = dz.drinkVolume + volMidStep;
              } else {
                dz.drinkVolume = dz.drinkVolume + volStep;
              }
            }
            if (dz.drinkVolume >= maxDrinkVol) dz.drinkVolume = 5000;
          }
          disp.displayInt(dz.drinkVolume);
          backCounter1 = 20;
        }
        //--------------------
        if (enc1.isLeft())
        {
          if (backCounter1 != 0)
          {
            if (dz.drinkVolume >= (1000 + volBigStep)) {
              dz.drinkVolume = dz.drinkVolume - volBigStep;
            } else {
              if (dz.drinkVolume >= (100 + volMidStep)) {
                dz.drinkVolume = dz.drinkVolume - volMidStep;
              } else {
                dz.drinkVolume = dz.drinkVolume - volStep;
              }
            }
            if (dz.drinkVolume <= 0) dz.drinkVolume = 0;
          }
          disp.displayInt(dz.drinkVolume);
          backCounter1 = 20;
        }
        //--------------------
      }
      break;
    //-------------------------------------------------------------
    default:
      //-------------------------------------------------
      break;
  }
  //wdt_reset();
  //-------------------------------------------------
}
//---------------------- Конец основного цикла -----------------------------------------
//--------------------------------------------------------------------------------------
void resumeRun()
{
  byte troll[4] = {_dash, _G, _o, _dash};
  disp.displayByte(troll);
  dz.currentMode = RUNNING;
  if (dz.rate != 0)
  {
    stepEnabled = true;
  }
  backCounter0 = 5;
}
//--------------------------------------------------------------------------------------
// То, что выполняется каждую секунду --------------------------------------------------

//--------------------------------------------------------------------------------------
// То, что выполняется каждую десятую долю секунды -------------------------------------
void oneTenthSub()
{
  tmasStop = !digitalRead(TMAS);
  digitalWrite(13, tmasStop);
  if ((sndFlag) and (tenth < 8))
  {
    if (bitRead(pattern, tenth))
    {
      digitalWrite(PIEZO, 0);
    }
    else
    {
      digitalWrite(PIEZO, 1);
    }
  }
  else
  {
    digitalWrite(PIEZO, 1);
  }
}
//--------------------------------------------------------------------------------------
// Прерывание таймера 2 (1000 раз в секунду) -------------------------------------------
ISR_T2_COMPA
{
  enc1.tick();
  thousandth++;                                         // Счетчик миллисекунд
  if (thousandth >= 100)                                // Началась новая десятая доля секунды
  { thousandth = 0; tenth++; newTenth = true;           // Счетчик десятых долей секунды
    if (backCounter0  != 0) {
      backCounter0--;
      if (backCounter0 == 0) {
        bc0flag = true;
      }
    }
    if (backCounter1  != 0) {
      backCounter1--;
      if (backCounter1 == 0) {
        bc1flag = true;
      }
    }
    if (tenth >= 10) {
      tenth = 0;  // Началась новая секунда
      newSecond = true;
    }
  }
}

//--------------------------------------------------------------------------------------
// Прерывание по совпадению А в таймере 1 ----------------------------------------------
ISR_T1_COMPA
{
  if ((stepEnabled) or (!(stepEnabled) and !(digitalRead(STEP).
    // Если шаги разрешены или запрещены и уровень на тактовом выходе низкий, то:
  {
    digitalWrite(STEP, !digitalRead(STEP));   // Меняем уровень на шагательной ноге на противоположный
    if (digitalRead(STEP))                    // Если был переход 0->1,
    {
      stepsCount++;                           // то увеличиваем счетчик шагов
      TIMER1_COMPA_setValue(timer1EndValue);  // и перезагружаем значение сравнения счетчика.
      if (dz.drinkVolume != 0)                   // Если задан ненулевой объем наливайки
      {
        if (drinkBackCounter == 0)            // и налито, сколько запрошено,
        {
          stepEnabled = false;                // останавливаем отбор
          drinkStop = true;                   // и устанавливаем флаг готовности дринка. (обрабатывается в основном цикле)
        }
        else
        {
          drinkBackCounter--;                 // Иначе уменьшаем дринковый счетчик.
        }
      }
    }
  }
}

//--------------------------------------------------------------------------------------
// Расчет числа, загружаемого в OCR1A в зависимости от нужной скорости отбора ----------
void calcOCR1A()
{
  stepEnabled = false;
  temp = round((float)450000000 / stepsForOneMl); // шаг/4
#ifdef STEP8
  temp = round((float)3600000000 / stepsForOneMl); // шаг/8
#endif
  // OCR1A = (Fcpu*3600)/(2*N*K*R)-1
  temp = round((float)temp / dz.rate);             // Fcpu = 16000000 Гц, N - количество шагов на 1 мл,
  temp = temp - 1;                              // K - делитель перед счетчиком Т1 (64), R - скорость отбора мл/час
  if (temp >= 65535)
  {
    dz.rate = 0;
    disp.displayInt(dz.rate);
  }
  else
  {
    noInterrupts();                               // Обеспечиваем атомарность действия
    timer1EndValue = temp;                        //
    interrupts();                                 // Восстанавливаем прерывания
  }
}
//--------------------------------------------------------------------------------------
// Пересчёт количества шагов в миллилитры ----------------------------------------------
void calcTotalVolume()
{
  dz.totalVolume = stepsCount / stepsForOneMl;
}
//--------------------------------------------------------------------------------------
// Увеличение скорости отбора ----------------------------------------------------------
void increaseRate()
{
  if (dz.rate >= 1000) {
    dz.rate = dz.rate + rateBigStep;
  } else {
    if (dz.rate >= 200) {
      dz.rate = dz.rate + rateMidStep;
    } else {
      dz.rate = dz.rate + rateStep;
    }
  }
  if (dz.rate >= maximumRate) dz.rate = maximumRate;
  calcOCR1A();
}
//--------------------------------------------------------------------------------------
// Уменьшение скорости отбора ----------------------------------------------------------
void decreaseRate()
{
  if (dz.rate >= (1000 + rateBigStep)) {
    dz.rate = dz.rate - rateBigStep;
  } else {
    if (dz.rate >= (200 + rateMidStep)) {
      dz.rate = dz.rate - rateMidStep;
    } else {
      dz.rate = dz.rate - rateStep;
    }
  }
  if (dz.rate <= 0) dz.rate = 0;
  calcOCR1A();
}
//--------------------------------------------------------------------------------------
void tryToSaveStepsFor100ml()
{
  backCounter1 = 20;
  counterA++;
  if (counterA > 10)
  {
    if ((stepsCount > minStepsFor100ml) and (stepsCount < 4 * minStepsFor100ml))
    {
      EEPROM.put(0, stepsCount);
      int8_t welcome_banner[] = {_C, _A, _L, _i, _b, _r, _A, _t, _i, _n, _G, _empty, _d, _o, _n, _E, _empty, _r, _E, _S, _t, _A, _r, _t, _i, _n, _G, _empty, _empty};
      disp.runningString(welcome_banner, sizeof(welcome_banner), 200);
      setup();
    }
  }
}
//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------

У меня ведущее устройство esp32(код esp idf).
Если надо, набросаю код ведущего под arduino.

266

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

Небольшой комментарий про глобальные переменные используемые в обработчиках прерывания - их нужно обьявлять как volatile.

267 (2019-12-20 20:19:46 отредактировано Dimyn999)

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

Парни подскажите что делать. ошибка компиляции для ардуино нано прошивка из 198 поста Arduino: 1.8.5 (Windows 7), Плата:"Arduino Nano, ATmega168"

C:\Program Files\Arduino\arduino-builder -dump-prefs -logger=machine -hardware C:\Program Files\Arduino\hardware -hardware C:\Users\Teminator\AppData\Local\Arduino15\packages -tools C:\Program Files\Arduino\tools-builder -tools C:\Program Files\Arduino\hardware\tools\avr -tools C:\Users\Teminator\AppData\Local\Arduino15\packages -built-in-libraries C:\Program Files\Arduino\libraries -libraries C:\Users\Teminator\Documents\Arduino\libraries -fqbn=arduino:avr:nano:cpu=atmega168 -ide-version=10805 -build-path C:\Users\TEMINA~1\AppData\Local\Temp\arduino_build_43420 -warnings=none -build-cache C:\Users\TEMINA~1\AppData\Local\Temp\arduino_cache_488511 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.arduinoOTA.path=C:\Users\Teminator\AppData\Local\Arduino15\packages\arduino\tools\arduinoOTA\1.1.1 -prefs=runtime.tools.avr-gcc.path=C:\Users\Teminator\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\4.9.2-atmel3.5.4-arduino2 -prefs=runtime.tools.avrdude.path=C:\Users\Teminator\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino9 -verbose C:\Users\Teminator\Desktop\dozer\pump_v0\pump_v0.ino
C:\Program Files\Arduino\arduino-builder -compile -logger=machine -hardware C:\Program Files\Arduino\hardware -hardware C:\Users\Teminator\AppData\Local\Arduino15\packages -tools C:\Program Files\Arduino\tools-builder -tools C:\Program Files\Arduino\hardware\tools\avr -tools C:\Users\Teminator\AppData\Local\Arduino15\packages -built-in-libraries C:\Program Files\Arduino\libraries -libraries C:\Users\Teminator\Documents\Arduino\libraries -fqbn=arduino:avr:nano:cpu=atmega168 -ide-version=10805 -build-path C:\Users\TEMINA~1\AppData\Local\Temp\arduino_build_43420 -warnings=none -build-cache C:\Users\TEMINA~1\AppData\Local\Temp\arduino_cache_488511 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.arduinoOTA.path=C:\Users\Teminator\AppData\Local\Arduino15\packages\arduino\tools\arduinoOTA\1.1.1 -prefs=runtime.tools.avr-gcc.path=C:\Users\Teminator\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\4.9.2-atmel3.5.4-arduino2 -prefs=runtime.tools.avrdude.path=C:\Users\Teminator\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino9 -verbose C:\Users\Teminator\Desktop\dozer\pump_v0\pump_v0.ino
Using board 'nano' from platform in folder: C:\Users\Teminator\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21
Using core 'arduino' from platform in folder: C:\Users\Teminator\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21
Изменены опции сборки, пересобираем все
Detecting libraries used...
"C:\Users\Teminator\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\4.9.2-atmel3.5.4-arduino2/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics  -flto -w -x c++ -E -CC -mmcu=atmega168 -DF_CPU=16000000L -DARDUINO=10805 -DARDUINO_AVR_NANO -DARDUINO_ARCH_AVR   "-IC:\Users\Teminator\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\cores\arduino" "-IC:\Users\Teminator\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\variants\eightanaloginputs" "C:\Users\TEMINA~1\AppData\Local\Temp\arduino_build_43420\sketch\pump_v0.ino.cpp" -o "nul"
"C:\Users\Teminator\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\4.9.2-atmel3.5.4-arduino2/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics  -flto -w -x c++ -E -CC -mmcu=atmega168 -DF_CPU=16000000L -DARDUINO=10805 -DARDUINO_AVR_NANO -DARDUINO_ARCH_AVR   "-IC:\Users\Teminator\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\cores\arduino" "-IC:\Users\Teminator\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\variants\eightanaloginputs" "-IC:\Users\Teminator\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\libraries\EEPROM\src" "C:\Users\TEMINA~1\AppData\Local\Temp\arduino_build_43420\sketch\pump_v0.ino.cpp" -o "nul"
"C:\Users\Teminator\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\4.9.2-atmel3.5.4-arduino2/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics  -flto -w -x c++ -E -CC -mmcu=atmega168 -DF_CPU=16000000L -DARDUINO=10805 -DARDUINO_AVR_NANO -DARDUINO_ARCH_AVR   "-IC:\Users\Teminator\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\cores\arduino" "-IC:\Users\Teminator\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\variants\eightanaloginputs" "-IC:\Users\Teminator\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\libraries\EEPROM\src" "C:\Users\TEMINA~1\AppData\Local\Temp\arduino_build_43420\sketch\pump_v0.ino.cpp" -o "C:\Users\TEMINA~1\AppData\Local\Temp\arduino_build_43420\preproc\ctags_target_for_gcc_minus_e.cpp"
C:\Users\Teminator\Desktop\dozer\pump_v0\pump_v0.ino:2:85: fatal error: GyverEncoder.h: No such file or directory

 #include "GyverEncoder.h"                     // Библиотеки с сайта 

                                                                                     ^

compilation terminated.

Несколько библиотек найдено для "EEPROM.h"
 Используется: C:\Users\Teminator\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\libraries\EEPROM
Не используется: C:\Users\Teminator\Documents\Arduino\libraries\EEPROM
Используем библиотеку EEPROM версии 2.0 из папки: C:\Users\Teminator\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\libraries\EEPROM 
exit status 1

Ошибка компиляции для платы Arduino Nano.

все разобрался библиотеки не добавил :rolleyes:  :rolleyes:

Рк 42 1700 3кв

268

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

Доброго времени суток , собрал и запустил пересталический насос, подскажите у всех шаговик жутко греется, и как исправить?, и почему при нажатии на остановку моторчик свистит, ведь по идее с него должно сниматься все напряжение?

Рк 42 1700 3кв

269 (2019-12-24 19:38:44 отредактировано kvic)

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

Dimyn999 ©:

шаговик жутко греется, и как исправить?,

Жутко греется, если сильно завышен ток обмоток двигателя относительно номинального.
Исправляется вращением подстроечника на плате с DRV8825.
Где-то в предыдущих постах было как это сделать с приведением числовых значений.
Вот тут:
Узел отбора на перистальтическом насосе
примерно посередине поста.
---
С этим же связано:

Dimyn999 ©:

и почему при нажатии на остановку моторчик свистит,

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

РК 35х1600

270 (2019-12-25 08:39:52 отредактировано Dimyn999)

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

kvic ©:

Жутко греется, если сильно завышен ток обмоток двигателя относительно номинального.
Исправляется вращением подстроечника на плате с DRV8825.
Где-то в предыдущих постах было как это сделать с приведением числовых значений.
Вот тут:
Узел отбора на перистальтическом насосе
примерно посередине поста.
---
С этим же связано:

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

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

Рк 42 1700 3кв

271

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

Dimyn999, похоже блок питания чудит.
У меня совершенно спокойно от 24 вольт работает.
Правда на питание ардуины отдельно понижаю до 9 вольт.

РК 35х1600

272

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

kvic ©:

Правда на питание ардуины отдельно понижаю до 9 вольт.

я от 12в блок питания от старого модема, похоже все таки придется ставить отдельный стабилизатор

Рк 42 1700 3кв

273

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

Dimyn999 ©:

12в блок питания от старого модема

Не слабоват? Движок может ампер легко слопать. А то и больше.
Возьми от ноутбука БП.

РК 35х1600

274

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

kvic ©:

Не слабоват? Движок может ампер легко слопать. А то и больше.
Возьми от ноутбука БП.

у меня шаговик не такой большой и мощный, от принтера, есть бп на 14в на 5А, но боюсь от него мотор сдохнет

Рк 42 1700 3кв

275

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

Dimyn999 ©:

есть бп на 14в на 5А, но боюсь от него мотор сдохнет

Не сдохнет, ставь.
Драйвер не даст.

РК 35х1600

276

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

kvic ©:

Драйвер не даст.

а он не сдохнет?

Рк 42 1700 3кв

277 (2019-12-25 10:31:36 отредактировано kvic)

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

Dimyn999 ©:

а он не сдохнет?

Не должен.
Он по напряжению 45 вольт должен держать, а при 24 вольтах - 2,5 ампера по току на выход.
Кстати, у него минимум 8,2 вольта по питанию.
Так что низкое напряжение ему не очень хорошо.

РК 35х1600

278

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

На финальном испытании понял, что мне надо бы поменять направление вращения двигателя.
kvic, я так понимаю, что программно в скетче этого сделать нельзя?

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

279

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

Димон ©:

программно в скетче этого сделать нельз

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

РК 35х1600

280

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

kvic*ROSE*

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