1

Тема: Cчетчик готовой продукции

Обсуждение статей:

  • Счетчики. Вариант 4 - Энергонезависимый счетчик готовой продукции

  • Счетчики. Вариант 3 - Stattrak или счетчик фрагов из CS:GO

  • Счетчики. Вариант 2 - Счетчик запусков или защита своего проекта от недобросовестного заказчика (Обновлено)

  • Счетчики. Вариант 1 - Простейший счетчик на базе Arduino

2

Re: Cчетчик готовой продукции

Для пользователя Артур

Дополненный счетчик из статьи: Счетчики. Вариант 1 - Простейший счетчик на базе Arduino

#include "TM1637.h"

void DispUpdate(void);
boolean DebounceButton(int ScanPort, boolean last);

#define INC 2 //Пин подключения датчика готовой продукции  
#define RES 3 //Пин подключения кнопки сброса счетчика

#define CLK 4 //TM1637 CLK
#define DIO 5 //TM1637 DIO

#define RELAY 12 // Реле.

int8_t CountDisp[] = {0x00,0x00,0x00,0x00};

static int Counter = 0; //Значение счетчика будет сохраняться здесь
static int totalCounter = 100; //Необходимое количество продукции.

bool INCCurr = false;
bool INCPrev = false;

/*
 * Создаем объект tm1637 класса TM1637
 * в качестве параметров передаём ему
 * номера пинов к которым подключен модуль
 * с дисплеем
 */
TM1637 tm1637(CLK, DIO);

void setup() 
{
  pinMode(INC, INPUT);  //Определяем пины подключения кнопки сброса 
  pinMode(RES, INPUT);  //и датчика готовой продукции как входные

  pinMode(RELAY, OUTPUT);  //Определяем пины подключения реле
  digitalWrite(RELAY, HIGH); //Включаем станок.
  
  //Инициализация дисплея на базе драйвера TM1637
  tm1637.init();
  /*
   * Установка яркости свечения сегментов
   * возможные значения:  BRIGHT_TYPICAL либо 2
   *                      BRIGHT_DARKEST либо 0
   *                      BRIGHTEST      либо 7
   * Также можно вводить значения от 0 до 4
   * при вводе начения свыше 4 визуального различия   
   * в яркости свечения не наблюдается поэтому решено
   * остановиться на 3
   */
  tm1637.set(2);  
}

void loop()
{
  // Как только произвели нужное нам количество продукции.
  if (Counter >= totalCounter)
  {
    digitalWrite(RELAY, LOW); //Выключаем станок.
  }      
    
  //Обнуление счетчика
  if(digitalRead(RES))
  {
    Counter = 0;
  }
  
  //Проверка кнопки инкремента - нажатие и обработка "Антидребезг"
  INCCurr = DebounceButton(INC, INCPrev);
  
  if(INCPrev == false && INCCurr == true)
  {
    if(Counter == 9999)
    {
      Counter = 0;
    }
    else
    {
      Counter ++;
    }
  }
  INCPrev = INCCurr;
  
  DispUpdate();
}

//Функция подавления дребезга контактов концевого датчика
boolean DebounceButton(int ScanPort, boolean last)
{
  boolean current = digitalRead(ScanPort);
  if(current != last)
  {
    delay(10);
    current = digitalRead(ScanPort); 
  }
  return current;
}

//Функция обновления дисплея
//Вывод значения счетчика на дисплей
void DispUpdate(void)
{
  int intValue = Counter;
  int divValue;
  
  for(int i = 3; i >= 0; i --)
  {
    divValue = intValue % 10;
    intValue = intValue / 10;
    
    CountDisp[i] = divValue;
  }
  tm1637.display(CountDisp);
}

Рекомендую добавить энкодер для управления переменной totalCounter. Таким образом можно будет выставлять нужное количество продукции.

3

Re: Cчетчик готовой продукции

Спасибо большое. Попробую энкодер добавить. Потом отпишусь.

4

Re: Cчетчик готовой продукции

Привет. Сможешь добавить в этот скетч энкодер, за вознаграждение?

5

Re: Cчетчик готовой продукции

#include "TM1637.h"

void DispUpdate(void);
boolean DebounceButton(int ScanPort, boolean last);

#define INC 2 //Пин подключения датчика готовой продукции  
#define RES 3 //Пин подключения кнопки сброса счетчика

#define CLK 4 //TM1637 CLK
#define DIO 5 //TM1637 DIO

#define RELAY 12 // Реле
#define ENCODER_CLK 6 // KY-040 CLK
#define ENCODER_DT 7  // KY-040 DT
#define ENCODER_SW 8  // KY-040 SW
 
int8_t CountDisp[] = {0x00,0x00,0x00,0x00};

static int Counter = 0; //Значение счетчика будет сохраняться здесь
static int totalCounter = 100; //Необходимое количество продукции.
static unsigned char encoder_A, encoder_B, encoder_A_prev = LOW;
static bool INCCurr, INCPrev = false;
static bool ENCCurr, ENCPrev, ENCMode = false;
/*
 * Создаем объект tm1637 класса TM1637
 * в качестве параметров передаём ему
 * номера пинов к которым подключен модуль
 * с дисплеем
 */
TM1637 tm1637(CLK, DIO);

void setup() 
{
  pinMode(INC, INPUT);  //Определяем пины подключения кнопки сброса 
  pinMode(RES, INPUT);  //и датчика готовой продукции как входные

  pinMode(RELAY, OUTPUT);  //Определяем пины подключения реле
  digitalWrite(RELAY, HIGH); //Включаем станок.

  pinMode(ENCODER_CLK, INPUT);
  pinMode(ENCODER_DT,  INPUT);
  pinMode(ENCODER_SW,  INPUT);
  
  //Инициализация дисплея на базе драйвера TM1637
  tm1637.init();
  /*
   * Установка яркости свечения сегментов
   * возможные значения:  BRIGHT_TYPICAL либо 2
   *                      BRIGHT_DARKEST либо 0
   *                      BRIGHTEST      либо 7
   * Также можно вводить значения от 0 до 4
   * при вводе начения свыше 4 визуального различия   
   * в яркости свечения не наблюдается поэтому решено
   * остановиться на 3
   */
  tm1637.set(2);  
}

void loop()
{
  // Обработка энкодера.
  encoder_A = digitalRead(ENCODER_CLK);
  encoder_B = digitalRead(ENCODER_DT);
  if(!encoder_A && encoder_A_prev)
  {
    if (encoder_B) totalCounter++; else totalCounter--;
    if (totalCounter >= 9999) totalCounter = 0;
  }
  encoder_A_prev = encoder_A;
  
  // Как только произвели нужное нам количество продукции.
  if (Counter >= totalCounter)
  {
    digitalWrite(RELAY, LOW); //Выключаем станок.
  }      

  //Обнуление счетчика
  if(digitalRead(RES))
  {
    Counter = 0;
  }

  //Проверка кнопки энкодера - нажатие и обработка "Антидребезг"
  ENCCurr = DebounceButton(ENCODER_SW, ENCPrev);
  if(ENCPrev == false && ENCCurr == true)
  {
    ENCMode = !ENCMode;
  }
  ENCPrev = ENCCurr;
  
  //Проверка кнопки инкремента - нажатие и обработка "Антидребезг"
  INCCurr = DebounceButton(INC, INCPrev);
  if(INCPrev == false && INCCurr == true)
  {
    if(Counter == 9999) Counter = 0; else Counter ++;
  }
  INCPrev = INCCurr;
  
  DispUpdate();
}

//Функция подавления дребезга контактов концевого датчика
boolean DebounceButton(int ScanPort, boolean last)
{
  boolean current = digitalRead(ScanPort);
  if(current != last)
  {
    delay(10);
    current = digitalRead(ScanPort); 
  }
  return current;
}

//Функция обновления дисплея
//Вывод значения счетчика на дисплей
void DispUpdate(void)
{
  int intValue = (ENCMode) ? totalCounter : Counter;
  int divValue;
  
  for(int i = 3; i >= 0; i --)
  {
    divValue = intValue % 10;
    intValue = intValue / 10;
    
    CountDisp[i] = divValue;
  }
  tm1637.display(CountDisp);
}

Проверьте

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

Если энкодер считает при вращении по часовой стрелке в отрицательную сторону то поменяйте порты CLK и DT местами.

Об спасибо - позже.

6

Re: Cчетчик готовой продукции

Энкодер заказал, придет недели через 3. Очень оперативно помог, спасибо. Как испытаю скетч, так об договоримся.

7 (изменено: rrafik_k, 31-03-2020 21:47:57)

Re: Cчетчик готовой продукции

не поможете ввести кнопку Старт, таймер, два светодиода (начала работы и конец работы) и блокировку счетчика готовой продукции при истечении назначенного времени?
У самого почему не получается, мозгов не хватает к сожалению

8

Re: Cчетчик готовой продукции

В скетч который выше или у вас есть другой? Если есть другой то выложите его!

9

Re: Cчетчик готовой продукции

genaonyx пишет:

В скетч который выше или у вас есть другой? Если есть другой то выложите его!

да, в этот скетч, сам попытался но не получается

10

Re: Cчетчик готовой продукции

#include "TM1637.h"

void DispUpdate(void);
boolean DebounceButton(int ScanPort, boolean last);

#define WORK_TIME 600 000 // 10 * 60 * 1000 (10 минут)

#define INC 2 //Пин подключения датчика готовой продукции  
#define RES 3 //Пин подключения кнопки сброса счетчика

#define CLK 4 //TM1637 CLK
#define DIO 5 //TM1637 DIO

#define RELAY 12 // Реле
#define ENCODER_CLK 6 // KY-040 CLK
#define ENCODER_DT 7  // KY-040 DT
#define ENCODER_SW 8  // KY-040 SW

#define LED_ON 9     // Пин светодиода "Включен"
#define LED_OFF 10   // Пин светодиода "Выключен"
#define BTN_START 11 // Пин кнопки "Включить"
 
int8_t CountDisp[] = {0x00,0x00,0x00,0x00};

static int Counter = 0; //Значение счетчика будет сохраняться здесь
static int totalCounter = 100; //Необходимое количество продукции.
static unsigned char encoder_A, encoder_B, encoder_A_prev = LOW;
static bool INCCurr, INCPrev = false;
static bool ENCCurr, ENCPrev, ENCMode = false;
static bool BTNCurr, BTNPrev = false;
static bool start_work = false;
unsigned long Time1 = 0;
/*
 * Создаем объект tm1637 класса TM1637
 * в качестве параметров передаём ему
 * номера пинов к которым подключен модуль
 * с дисплеем
 */
TM1637 tm1637(CLK, DIO);

void setup() 
{
  pinMode(INC, INPUT);  //Определяем пины подключения кнопки сброса 
  pinMode(RES, INPUT);  //и датчика готовой продукции как входные

  pinMode(RELAY, OUTPUT);  //Определяем пины подключения реле
  digitalWrite(RELAY, LOW); //Выключаем станок.

  pinMode(ENCODER_CLK, INPUT);
  pinMode(ENCODER_DT,  INPUT);
  pinMode(ENCODER_SW,  INPUT);

  pinMode(LED_ON,    OUTPUT);
  pinMode(LED_OFF,   OUTPUT);
  pinMode(BTN_START, INPUT);
  
  //Инициализация дисплея на базе драйвера TM1637
  tm1637.init();
  /*
   * Установка яркости свечения сегментов
   * возможные значения:  BRIGHT_TYPICAL либо 2
   *                      BRIGHT_DARKEST либо 0
   *                      BRIGHTEST      либо 7
   * Также можно вводить значения от 0 до 4
   * при вводе начения свыше 4 визуального различия   
   * в яркости свечения не наблюдается поэтому решено
   * остановиться на 3
   */
  tm1637.set(2);  
}

void loop()
{
  // Обработка энкодера.
  encoder_A = digitalRead(ENCODER_CLK);
  encoder_B = digitalRead(ENCODER_DT);
  if(!encoder_A && encoder_A_prev)
  {
    if (encoder_B) totalCounter++; else totalCounter--;
    if (totalCounter >= 9999) totalCounter = 0;
  }
  encoder_A_prev = encoder_A;
  
  // Как только произвели нужное нам количество продукции.
  if (Counter >= totalCounter || Timer(&Time1, WORK_TIME))
  {
    start_work = false;
  }      

  //Обнуление счетчика
  if(digitalRead(RES))
  {
    Counter = 0;
    start_work = false; // !!! Выключаем станок по нажатию на экнодер. Убрать если ненадо.
  }
  
  // Работа станка.
  if (start_work)
  {
    digitalWrite(RELAY, HIGH); //Включаем станок.
    digitalWrite(LED_ON, HIGH); // Светодиод "Включен" - горит. 
    digitalWrite(LED_OFF, LOW); // Светодиод "Выключен" - не горит.
  } else
  {
    digitalWrite(RELAY, LOW); //Выключаем станок.
    digitalWrite(LED_ON, LOW); // Светодиод "Включен" - не горит. 
    digitalWrite(LED_OFF, HIGH); // Светодиод "Выключен" - горит.
  }
  
  //Проверка кнопки "Включить" - нажатие и обработка "Антидребезг"
  BTNCurr = DebounceButton(BTN_START, BTNPrev);
  if(BTNPrev == false && BTNCurr == true)
  {
    start_work = true; // Включаем станок.
    Time1 = millis(); // Включаем таймер.
  }
  BTNPrev = BTNCurr;  
  
  //Проверка кнопки энкодера - нажатие и обработка "Антидребезг"
  ENCCurr = DebounceButton(ENCODER_SW, ENCPrev);
  if(ENCPrev == false && ENCCurr == true)
  {
    ENCMode = !ENCMode;
  }
  ENCPrev = ENCCurr;
  
  //Проверка кнопки инкремента - нажатие и обработка "Антидребезг"
  INCCurr = DebounceButton(INC, INCPrev);
  if(INCPrev == false && INCCurr == true)
  {
    if(Counter == 9999) Counter = 0; else Counter ++;
  }
  INCPrev = INCCurr;
  
  DispUpdate();
}

bool Timer(uint32_t *startTime, uint32_t period)
{
  uint32_t currentTime = millis();
  bool result = (currentTime >= *startTime) ? currentTime >= *startTime + period : currentTime >= 4294967295 - *startTime + period;
  if (result) *startTime = currentTime;
  return result;
}

//Функция подавления дребезга контактов концевого датчика
boolean DebounceButton(int ScanPort, boolean last)
{
  boolean current = digitalRead(ScanPort);
  if(current != last)
  {
    delay(10);
    current = digitalRead(ScanPort); 
  }
  return current;
}

//Функция обновления дисплея
//Вывод значения счетчика на дисплей
void DispUpdate(void)
{
  int intValue = (ENCMode) ? totalCounter : Counter;
  int divValue;
  
  for(int i = 3; i >= 0; i --)
  {
    divValue = intValue % 10;
    intValue = intValue / 10;
    
    CountDisp[i] = divValue;
  }
  tm1637.display(CountDisp);
}