Развлекалочка. Или контроллер сварочного аппарата

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

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

Для проверки “а пойдет” рисую схему

schema

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

pcb_example

Потом посмотрел, как оно будет выглядеть “в реале”

3dmodel

Вроде ничего, гламурно даже. Правда, в процессе пайки мне стало лень паять столько резисторов и я взял резисторную сборку. Ну и немного поменял расположение компонентов, ибо макетная плата у меня “не ровная”. В общем, получилось вот так

overview

Теперь добавляем щепотку “магии”

#include <EEPROM.h>
int pinAch = 2; //Энкодер вывод А включен на interrupt 0 (D2)
int pinBch = 3; // Энкодер вывод Б - D3

int pinled = 5; // Куда включен первый сетодиодик
int ledcount = 8; // Сколько светодиодиков

int pinButton = A5; // куда включена кнопка "пуск"
int pinRelay = A0; // Куда подключено реле

int impulsTime = 50; // Время включения реле по умолчанию (50 мс)
int relayShift = 2; // Время реакции реле
unsigned long bl; // переменная для хранения состояния "мигающего" светодиода
unsigned long dr; // переменная для антидребезга энкодера
int out=0; // мы бабахнули?

void setup() {                
  Serial.begin(9600);

  pinMode(pinAch, INPUT_PULLUP);  
  pinMode(pinBch, INPUT_PULLUP);

  pinMode(pinled, OUTPUT);
  pinMode(pinled+1, OUTPUT);
  pinMode(pinled+2, OUTPUT);
  pinMode(pinled+3, OUTPUT);
  pinMode(pinled+4, OUTPUT);
  pinMode(pinled+5, OUTPUT);
  pinMode(pinled+6, OUTPUT);
  pinMode(pinled+7, OUTPUT);

  pinMode(13, OUTPUT); // светодиодик, впаянный в ардуинку

  pinMode(pinButton, INPUT_PULLUP);
  pinMode(pinRelay, OUTPUT);

  digitalWrite(pinled, HIGH); // все светодидиоды включить для проверки
  digitalWrite(pinled+1, HIGH);
  digitalWrite(pinled+2, HIGH);
  digitalWrite(pinled+3, HIGH);
  digitalWrite(pinled+4, HIGH);
  digitalWrite(pinled+5, HIGH);
  digitalWrite(pinled+6, HIGH);
  digitalWrite(pinled+7, HIGH);

  digitalWrite(pinRelay,LOW); // для безопасности

  dr=millis();
  bl=millis();
  if(EEPROM.read(0)==1)
    {
      impulsTime=EEPROM.read(1);
    }
  attachInterrupt(0, encoderClick, RISING);
}


void loop() {
  // Зажигаем светодиодики в зависимости от уровня impulsTime
  for(int i=pinled;i<(pinled+ledcount);i++)
  {
    int s=(i-pinled+1)*10; // время импульса для зажигания светодиода
    // то есть для 1 светодиода 10, для 2 - 20 и так далее

    if((impulsTime-s)<0 && (impulsTime-s)>-10) // этот светодиодик промежуточный, поэтому пусть мигает.
    {
      if((millis()-bl)<500)
      {
        digitalWrite(i,HIGH);
      }
      else
      {
        digitalWrite(i,LOW);
        if((millis()-bl)>1000)
        {
          bl=millis();
        }
      }
    }
    else
    {
      if(s<=impulsTime)
      {
        digitalWrite(i,HIGH);
      }
      else
      {
        digitalWrite(i,LOW);
      }
    } 
  }
  
  if(digitalRead(pinButton)==LOW && out==0) // оппа, кнопку нажали и еще не бабахали
    {
      delay(100); // ждем 100мс - вдруг рука дрогнула
      if(digitalRead(pinButton)==LOW) // точно нажата?
        {
          digitalWrite(13,HIGH);
          digitalWrite(pinRelay,HIGH);
          out=1;
          delay(impulsTime+relayShift);
          digitalWrite(13,LOW);
          digitalWrite(pinRelay,LOW);
          out=1;
          EEPROM.write(0, 1); // ставим флаг
          EEPROM.write(1, impulsTime);
        }
    }
    
  if(digitalRead(pinButton)==HIGH && out==1) // Кнопку отпустили после бабханья
    {
      delay(100); // ждем 100мс - вдруг рука дрогнула
      if(digitalRead(pinButton)==HIGH) // до сих пор отпущена?
        {
          out=0; // Хорошо, можно еще раз бабахнуть
        }
    }


//  Serial.println(impulsTime);
//  delay(300);
}


// обработка энкодера
void encoderClick(){
  if((millis()-dr)>10) // От предидущего прерывания прошло больше 10мс? если нет, то это дребезг
  {
    dr=millis();
    int valA = digitalRead(pinAch);
    int valB = digitalRead(pinBch);

    if (valA != valB){
      impulsTime--;
    }
    else{
      impulsTime++;
    }

    if(impulsTime < 5) {
      impulsTime=5;
    }

    if(impulsTime > 100) {
      impulsTime=100;
    }
  Serial.println(impulsTime); 
  }
}

И проверяем, насколько полученное устройство соответствует заявленным мной же спецификациям

Импульс в 20 миллисекунд

20ms

В 50

50ms

и 75, что бы не было ровных чисел.

75ms

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

Задача выполнена быстро и с перерасходом ресурсов, как и положено для такого класса задач 🙂