Как нажимать (эмулировать нажатие) на сенсорные кнопки с помощью ардуины?

Vitaly_Ekb
Offline
Зарегистрирован: 08.05.2016

Есть панель управления вентиляцией на ATmega32A. К мк  по i2c подключена  микруха AD7148 по схеме см. ниже. Эта микруха отвечает за нажатие сенсорных клавиш на панели управления.

Подскажите, как можно нажимать (эмулировать нажатие) на сенсорные кнопки с помощью ардуины?

Даташит на есть здесь .

Схема подключения AD7148 к мк.

Заранее благодарен всем откликнувшимся. 

Logik
Offline
Зарегистрирован: 05.08.2014

Думаю никак. Датчик емкостной, срабатывает от небольшой емкости тушки. Ваша схема будет иметь тоже некоторую собственную емкость - емкость монтажа. От этой неуправляемой емкости и будет сработка.

Ищите другие пути - раземчик подпаять и т.д.

Vitaly_Ekb
Offline
Зарегистрирован: 08.05.2016

Logik пишет:

Ищите другие пути - раземчик подпаять и т.д.

Я вас правильно понял, что вы считаете что  даже подпоявшись к плате я не смогу никакак сэмулировать нажатие на сенсорные клавиши с помощью ардуины? 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Взять два сервомотора, сделать "робопалец" и им нажимать :)

Vitaly_Ekb
Offline
Зарегистрирован: 08.05.2016

ЕвгенийП пишет:

Взять два сервомотора, сделать "робопалец" и им нажимать :)

Громоздко получится )))

Vitaly_Ekb
Offline
Зарегистрирован: 08.05.2016

Vitaly_Ekb пишет:

ЕвгенийП пишет:

Взять два сервомотора, сделать "робопалец" и им нажимать :)

Громоздко получится )))

Сначало посмеялся, но сейчас похоже это единственный вариант.....

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Vitaly_Ekb, справедливости ради нужно всё таки добавить, что есть и более удобные варианты. (1) Создать на МК эмулятор этой микросхемы. По внешнему сигналу он отключит от шины i2c родной чип и пошлёт свой ответ. (2) переписать программу меги32 добавив дополнительные входы управления.  Но оба варианта - это серьёзная работа для опытного инженера-программиста.

Vitaly_Ekb
Offline
Зарегистрирован: 08.05.2016

dimax пишет:

......  Но оба варианта - это серьёзная работа для опытного инженера-программиста.

Это факт, я максимум осилю "робопальцы" :-)

nik182
Offline
Зарегистрирован: 04.05.2015

Не совсем понятно, что значит эмулировать? Совсем выкинуть AD? Поключить ардуину с несенсорными кнопками? Довольно просто. Надо в режиме i2c slave деруть ногу int и на запрос процессора-мастера отправить два 16 битных слова с координатами кнопок.

Vitaly_Ekb
Offline
Зарегистрирован: 08.05.2016

nik182 пишет:
.... Совсем выкинуть AD? Поключить ардуину с несенсорными кнопками? Довольно просто. Надо в режиме i2c slave деруть ногу int и на запрос процессора-мастера отправить два 16 битных слова с координатами кнопок.

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

Уважемый nik182,  а сколько это может стоить, и не возметесь ли вы помочь в этом?

nik182
Offline
Зарегистрирован: 04.05.2015
#include <Wire.h>

#define INTPIN 3
#define I2C_SLAVE_ADDRESS 2
#define reg_size 6

union {
  uint16_t AD_Reg[6];
  uint8_t i2cReg[12]; 
} AD7148;

volatile uint8_t reg_position, Button;

void requestEvent()
{  
    Wire.write(AD7148.i2cReg[reg_position]);
    reg_position++;
    if (reg_position >= reg_size)
    {
        reg_position = 0;
    }
}

void blinkInt(int)
{
        digitalWrite(INTPIN, LOW);
        delay(1);
        digitalWrite(INTPIN, HIGH);
}

void setup()
{
    digitalWrite(INTPIN, HIGH); 
    pinMode(INTPIN, OUTPUT); 
    Wire.begin(I2C_SLAVE_ADDRESS);
    Wire.onRequest(requestEvent);
}

void loop()
{
  if (Button>0){
    switch (Button){
      case 1: AD7148.AD_Reg[0]=100;AD7148.AD_Reg[1]=200;reg_position=0; blinkInt; break;
      case 2: AD7148.AD_Reg[0]=300;AD7148.AD_Reg[1]=400;reg_position=0; blinkInt; break;
    }
   Button=0;
  }
} 

Рабочая заготовка. Button кнопка или событие. Может быть сколько угодно. Нужно только заполнить AD_reg правильными цифрами для каждого события. Я этого сделать не могу. У меня нет этого оборудования и цифры взять неоткуда.

Vitaly_Ekb
Offline
Зарегистрирован: 08.05.2016

Уважемый nik182.

Большое вам спасибо за ответ и код. На  плате 4 сенсорные кнопки. Они подключены к AD7148 r  ногам 13,14,15,16  соответсвенно CIN0-CIN3. Этого достаточно для ".... заполнить AD_reg ".  К сожалению мои знания таковы, что кое что в вашем коде я не понимаю. 

Буду вам примного балгодарен за помощь. 

nik182
Offline
Зарегистрирован: 04.05.2015

Опишите, что вы не понимаете, я расшифрую.

Vitaly_Ekb
Offline
Зарегистрирован: 08.05.2016

Уважаемы nik182.

Пожалйста подскажите ваш емейл. 

nik182
Offline
Зарегистрирован: 04.05.2015

Дальнейшая работа подразумевает подключение сниффера i2c шины к существующему устройству и получения кодов, передаваемых AD7148. Без знания этих кодов очень трудно двигаться дальше. Другой путь - посылать разные коды и смотреть как отреагирует устройство. Но это очень стрёмный путь. Можно вогнать в какой нибудь инженерный режим и сбить все настройки. Я вам дал полностью рабочий код. В него нужно добавить присвоение Button чисел 1,2,3,4.... в зависимости от количества коман и для каждой команды прописать коды в массив AD_reg. Я сделать большего не могу, т.к. без наличия железа или конкретных кодов всё остальное просто бессмысленно. Подключите ардуину к шине i2c. Нажимайте кнопки и смотрите, какие числа бегут по шине. http://cxem.net/comp/comp122.php Например вот схема сниффера. В гугле их много.

darkjorik
Offline
Зарегистрирован: 08.11.2014

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

Logik
Offline
Зарегистрирован: 05.08.2014

nik182 пишет:
Дальнейшая работа подразумевает подключение сниффера i2c шины к существующему устройству и получения кодов, передаваемых AD7148.

Нафига сниферить если в доке есть глава I2C-COMPATIBLE SERIAL INTERFACE.

Почитать, реализовать. Только не по ТС задача эта.

nik182
Offline
Зарегистрирован: 04.05.2015

Потому что при нажатии на кнопку АЦП оцифровывает матрицу и посылает результат оцифровки. В мануале ничего нет про матрицуи и результат оцифровки.

ProstoAlex
Offline
Зарегистрирован: 21.01.2015

я буду делать тоже самое с котлом.

задча - нажимать на кнопки +/-, они сенсорные.

Разобрав пульт котла увидел, что от платки кнопок на основную плату идет шлейф с количеством проводников на 3 больше чем чилос кнопок.

Дальше просто отследил дорожки, и увидел, гда на процессор идут сигналы с сенсорных кнопок.

Перед процессором - резисторы.

И замыкая эти дорожки на землю (резистором 100к) получаю нажатия.

Все просто.

Logik
Offline
Зарегистрирован: 05.08.2014

nik182 пишет:
Потому что при нажатии на кнопку АЦП оцифровывает матрицу и посылает результат оцифровки. В мануале ничего нет про матрицуи и результат оцифровки.

Действительно, ничего нет такого.  И в этой теме нет. А зачем Вы  это выдумали?

Vitaly_Ekb
Offline
Зарегистрирован: 08.05.2016

При замыкании контакта сенсорной конопки на землю работает не стабильно, то работает, то не работает, прежде чем писать пробовал и сейчас перепроверил. А вот через 100кОм вроде стабильно срабатывает. 

Думаю надо проверить сначала точность срабатывания кнопки, если точность будет близко к 100% остановлюсь на нем. если нет буду копать в сторону более сложной схемы. 

Там на плате есть пищалка, и при нажатии на клавишу пищалка издает звук. Думаю надо на ардуинке собрать схему проверить точности срабатывания нажатия кнопки. Что бы ардуина замыкала кнопку и проверяла сработку пищалки. Подскажите где посмотреть пример кода для проверки срабатывания пищалки. На пищалку приходит сигнал длительностью ~17,5 м.сек с частотой ~ 4 кГц.

ProstoAlex
Offline
Зарегистрирован: 21.01.2015

возможно, контроллер, отрабатывающий нажатия, проверяет напряжения (на КЗ?), отсекает дребезг и проч.

nik182
Offline
Зарегистрирован: 04.05.2015

Logik пишет:

Действительно, ничего нет такого.  И в этой теме нет. А зачем Вы  это выдумали?

Уточните, что я выдумал, потому как от ТС:

Vitaly_Ekb пишет:

Есть панель управления вентиляцией на ATmega32A. К мк  по i2c подключена  микруха AD7148 по схеме см. ниже. Эта микруха отвечает за нажатие сенсорных клавиш на панели управления.

Подскажите, как можно нажимать (эмулировать нажатие) на сенсорные кнопки с помощью ардуины?

Эмулировать нажатие можно только посылая такие же  коды АЦП  как из мс AD7148. 

Vitaly_Ekb
Offline
Зарегистрирован: 08.05.2016

Уважаемый  nik182

Я правильно понимаю что вместо  I2C сниффера подойдет логический анализатор типа такого

что бы посмотреть что AD7148 шлет по шине I2C?

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

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

Как видно анализатор тоже точно всё вывел, ( на разницу в одном байте не обращать внимания -это ацп))  Хоть и не так красочно как осциллоскоп)

Logik
Offline
Зарегистрирован: 05.08.2014

nik182 пишет:

Logik пишет:

Действительно, ничего нет такого.  И в этой теме нет. А зачем Вы  это выдумали?

Уточните, что я выдумал, потому как от ТС:

Vitaly_Ekb пишет:

Есть панель управления вентиляцией на ATmega32A. К мк  по i2c подключена  микруха AD7148 по схеме см. ниже. Эта микруха отвечает за нажатие сенсорных клавиш на панели управления.
 

Подскажите, как можно нажимать (эмулировать нажатие) на сенсорные кнопки с помощью ардуины?

И опять, ни АЦП ни матрицы нет. В мануале тоже нет. Но вы пишите

Logik пишет:

nik182 пишет:
Потому что при нажатии на кнопку АЦП оцифровывает матрицу и посылает результат оцифровки. В мануале ничего нет про матрицуи и результат оцифровки.

Действительно, ничего нет такого.  И в этой теме нет. А зачем Вы  это выдумали?

Вот я и спрашиваю зачем вы придумываете сущности не по теме. 
nik182 пишет:

Эмулировать нажатие можно только посылая такие же  коды АЦП  как из мс AD7148. 

Если уж решили подменять значения из регистров AD7148 то надо почитать доку, что там за значения должны быть на каких адресах. А там емкости нажимающего подключенные к контактам, их значения разные для разных нажимающих, состояния рук и т.д. и вычитывать их точные значения безсмыслено, достаточно подавать большие числа из допустимого диапазона значений регистра при нажатии и маленькие при отсутствии в соответствии с форматом из даташита. Даже если с первого раза не угадается - за несколько попыток уточнится.

Vitaly_Ekb
Offline
Зарегистрирован: 08.05.2016

Подключил Ардуину к пульту с сенсорными конопками по схеме ниже. 

В ардуине скетч


int ledPin=13;
int btp=9;

unsigned long previousMillis = 0; 

byte stage = 0;


void setup() {
  Serial.begin(9600);
  pinMode(ledPin,OUTPUT);
  
}
void loop() {

 if (digitalRead(btp)==HIGH && stage == 0)
{
previousMillis = millis();
stage = 1;

Serial.println("Start counting ");
}


if (millis() - previousMillis>=5 && stage == 1)
{
digitalWrite(ledPin,HIGH);
stage = 2;
Serial.println("is on ");
}

if (millis() -previousMillis>=100 && stage == 2)
{
digitalWrite(ledPin,LOW);
stage = 3;
Serial.println("is off ");
}

if (millis() -previousMillis>=1000 && stage == 3)
{

stage = 0;
Serial.println("Ready to start ");
}

// delay(2000); 
}

Если сначала подключаю панель (подаю на нее питание) а потом подключаю контакт от дуньки на контакт сенсорной клавиши, то все работает. 

Если же сначала подключаю контакт от дуньки на контакт сенсорной клавиши а потом подключаю панель (подаю на нее питание), то ничего не работает.

Видать в момент включения AD7148 колибруется и замыкания контакта на землю через 100кОм уже не работает.   

Подскажите пожалуйста , куда копать. 

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Vitaly_Ekb, нафига тут оптрон?  Подключите напрямую. Только коммутировать придёться нестандартно, -командой pinMode, input -отключено, output -включено.

Vitaly_Ekb
Offline
Зарегистрирован: 08.05.2016

Большое спасибо.  В прошлые разы был не внимателен при проверке, и уточняю: Сенсорная кнопка срабатывает не когда замыкаешь ее на землю через 100кОм а когда при замкнутом через 100кОм на минус или на плюс разрываешь контакт. Причем если контакт снова не замкнешь панель будет считать, что кнопка замкнута (долгое нажатие). 

int ledPin=13;
int ledPin2=12; //Контакт сенсорной конпки
int btp=9;  //Кнопка
unsigned long previousMillis = 0; 
byte stage = 0;

void setup() {
pinMode(ledPin2,OUTPUT);
Serial.begin(9600);
pinMode(ledPin,OUTPUT);
}

void loop() {

 if (digitalRead(btp)==HIGH && stage == 0)  //Начинается отчет
{
previousMillis = millis();
stage = 1;
Serial.println("Start counting ");
}


if (millis() - previousMillis>=5 && stage == 1)   // Включается
{
digitalWrite(ledPin,HIGH);
pinMode(ledPin2,INPUT); 
stage = 2;
Serial.println("is on ");
}


if (millis() -previousMillis>=1000 && stage == 2)     // Выключается
{
pinMode(ledPin2,OUTPUT); 
digitalWrite(ledPin,LOW);
stage = 3;
Serial.println("is off ");
}


if (millis() -previousMillis>=2000 && stage == 3)      // Готов к следющему нажатю
{
stage = 0;
Serial.println("Ready to start ");
}


}

Схему собрал без оптрона. Код работает при условии если контакт мк подключается к контакту сенсорной кнопки пульта(панель) после включения панели или питание на мк подается с задержкой после подачи питания на пульт(панель).   

Я планирую собрать таймер задержки включения на 555, вернее на русском аналоге КР1006ВИ1. Чтобы питание подавалось с задержкой.

Подскажите пожалуйста может есть какой-нибудь более изящный способ?

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Vitaly_Ekb, что вы вцепились за эти 100кОм ? Не факт что сопротивление там нужно вообще, а если и нужно, то не факт что именно 100к. Может конденсатор нужен? Изучите даташит, выясните на что реагирует датчик.

Logik
Offline
Зарегистрирован: 05.08.2014

dimax пишет:

Vitaly_Ekb, нафига тут оптрон?  Подключите напрямую. Только коммутировать придёться нестандартно, -командой pinMode, input -отключено, output -включено.

Я когда на этом форуме вижу оптрон, мне плохо становится. От диссонанса чувств. Просто трындец. Я уже раз советовал селсин ставить, и шо вы думаете, он пошел его ставить )))

Logik
Offline
Зарегистрирован: 05.08.2014

Vitaly_Ekb пишет:

Большое спасибо.  В прошлые разы был не внимателен при проверке, и уточняю: Сенсорная кнопка срабатывает не когда замыкаешь ее на землю через 100кОм а когда при замкнутом через 100кОм на минус или на плюс разрываешь контакт. Причем если контакт снова не замкнешь панель будет считать, что кнопка замкнута (долгое нажатие). 

Это не невнимательность. Это непонимание принципа. Схема емкостная, и определяет не столько сопротивление, сколько емкость. Припаяли проводок или резистор- добавили емкость, держите провод  - еще емкость добавилась. А она может еще быть заряжена и разряжена.

Vitaly_Ekb
Offline
Зарегистрирован: 08.05.2016

Уважаемы ГУРУ!!! Хотел бы уточнить, мои знания в программировании ардуины ушли чуть дальше чем моргания светодиодами и термобарометра для дома. В электронике: про оптрон и схему его включения узнал только на этой недели, на этом же форуме нашел.

Уважаемый Logik    Про "селсин" !!! даже прокомментировать не нахожусь что. .  -Вы явно меня с кем-то путаете.  

dimax пишет:

Vitaly_Ekb, что вы вцепились за эти 100кОм ? Не факт что сопротивление там нужно вообще….

Я попробовал несколько сопротивлений и диаппазон, при которых кнопка срабатывает получился где-то от 15кОм до где то 150кОм.

 

dimax пишет:

…. Может конденсатор нужен? ….

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

 

dimax пишет:

…. Изучите даташит, выясните на что реагирует датчик.

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

 

Logik пишет:

Это не невнимательность. Это непонимание принципа…..

Полностью с вами согласен, вот из за этого и прошу помочь…..

 

С одной кнопкой   и сопротивлением 20кОм вроде работает, поставил 4 кнопки, продублировал на 4 кнопки, изменил код, остальные кнопки не захотели работать по той же схеме :-(.

// 4 конопи ОК. 

int ledPin=13;

int ContactPin1=9; //Контакт сенсорной конпки
int ContactPin2=10; //Контакт сенсорной конпки
int ContactPin3=11; //Контакт сенсорной конпки
int ContactPin4=12; //Контакт сенсорной конпки

//int btp=2;  //Кнопка
unsigned long previousMillis = 0; 
byte stage = 0;
byte ContactN=0;

int btp1=2;  //Кнопка1
int btp2=3;  //Кнопка2
int btp3=4;  //Кнопка3
int btp4=5;  //Кнопка4

void setup() {

pinMode(ContactPin1,OUTPUT);
pinMode(ContactPin2,OUTPUT);
pinMode(ContactPin3,OUTPUT);
pinMode(ContactPin4,OUTPUT);

Serial.begin(9600);
pinMode(ledPin,OUTPUT);
}

void loop() {

if (digitalRead(btp1)==HIGH && stage == 0)  // Включается и Начинается отчет
{
stage = 1;
ContactN=9;
}
if (digitalRead(btp2)==HIGH && stage == 0)  // Включается и Начинается отчет
{
stage = 1;
ContactN=10;
}
if (digitalRead(btp3)==HIGH && stage == 0)  // Включается и Начинается отчет
{
stage = 1;
ContactN=11;
}if (digitalRead(btp4)==HIGH && stage == 0)  // Включается и Начинается отчет
{
stage = 1;
ContactN=12;
}



 if ( stage == 1)  // Включается и Начинается отчет
{
previousMillis = millis();
stage = 2;
digitalWrite(ledPin,HIGH);
pinMode(ContactN,INPUT); 
Serial.println(ContactN );
Serial.println("Start counting  and is on ");
}

if (millis() -previousMillis>=1000 && stage == 2)     // Выключается
{
pinMode(ContactN,OUTPUT); 
digitalWrite(ledPin,LOW);
stage = 3;
Serial.println("is off ");
}

if (millis() -previousMillis>=1500 && stage == 3)      // Готов к следющему нажатю
{
stage = 0;
ContactN=0;
Serial.println("Ready to start ");
}


}

Прошу помощи, с учетом моего очень слабого понимания вопроса….

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Vitaly_Ekb пишет:

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

Да вы в него не смотрели даже, там первой строкой -ёмкостной датчик. Нафига ему ваш резистор? Реагирует он всё равно на ёмкость.

Vitaly_Ekb
Offline
Зарегистрирован: 08.05.2016

Поверьте, есть сферы в жизни в которых я не такой профан как в этой. И понимаю что намного проще сказать , что то типа:

dimax пишет:

Да вы в него не смотрели даже, там первой строкой….

Нежели предложить какое-то решение.

 

dimax пишет:

…там первой строкой -ёмкостной датчик….

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

И после этого пришел на форум за помощью.

А прицепился я к сопротивлению, потому-что наводку дал ProstoAlex и это единственное что у меня получилось на данный момент.

 

И снова :-) «Прошу помощи, с учетом моего очень слабого понимания вопроса….»

Logik
Offline
Зарегистрирован: 05.08.2014

Попытаюсь еще раз. На пальцах как для профана. Схема работает на измерении электрической емкости. Любой предмет, хоть немного проводящий, имеет емкость. Вы, я, проводок, ардуина, контакты реле, и пр. При какбы нажатии Вы подключаете свою емкость в схему, микруха просто измеряет емкость "кнопки" и сохраняет полученое значение емкости в регистре. Фишка в том что подключаете свою емкость не обязательно гальванически, т.е. контакту к металлу но и без оного, т.е. снова через емкость )))

Из этого следует несколько грусных фактов:

1. Подключить проводок - это ни о чем, важно держали ли вы этот проводок рукам, пинцетом, где он лнжал, его размеры и т.д. т.е. все что может влиять на его емкомсть.

2.  Подключение любой схемы будет добавлять ей емкость что оказывает побочное вляние на процесс измерения. А т.к. весь разговор о малых величинах, то побочное может сильно все испортить.

3. Варианты с вмешательством внутрь устройства типа подмены микросхемы (комутации шины, фокусов с адресами устройств и пр..), они конечно возможны, но требуют высокой квалификации. Ну и гарантия понятно потеряется.

4. Вариант с резистором, с учетом п.1, по сути вмешательство в процесс измерения емкости, дело малопрогнозируемое, опять же нужна схема комутирующая его и см. п.2

nik182
Offline
Зарегистрирован: 04.05.2015

Да. Робопалец рулит. Емкость тела человека от 100 до 200 pF. Соответственно примерно столько надо ставить. Такой емкостью ничего не сожёшь. Хотя резистор это то же самое. Потому что емкостью тела человека замыкается на землю генератор 250кГц и измеряется изменение переменного напряжения.

И выкиньте из SETUP pinMode - строки 22-25 т.к. именно из за них вы при старте нагружаете AD в момент калибровки. Без них всё должно работать при нормальном соединении с момента включения. Включение - начало эмуляции нажатия должно даваться командой digitalWrite(СontactN,LOW); pinMode(ContactN,OUTPUT); , а выключение - отпускание пальца pinMode(ContactN,INPUT);.

  У вас мне кажется наоборот.

Vitaly_Ekb
Offline
Зарегистрирован: 08.05.2016
Уважаемые: dimax, nik182, Logik, ProstoAlex
Огромное вам спасибо. Благодаря вашим подсказкам все сейчас работает. 
Основные моменты:
1. Включение мк с задержкой пару секунд
2. при замкнутом через 100кОм на минус или на плюс разрываешь контакт а потом снова замыкаешь
3. Время размыкания 70ms (60 и 80 уже дают ошибки) и задержка до следующего размыкания обязательн рандомная от 600 до 900 ms. 
4. командоы pinMode, input  и output .
 
МК стоял больше суток в режиме 2 раза в минуту менял производительность притока и вытяжки + еще пару недель в обычном режиме. 
Ни одной ошибки не было. Ура!!!!
 
Ниже код, может кому пригодится, хотя думаю у гуру инфаркт будет от него )))
 
// Врде все работает!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!стоит на прогоне с 15:34 23.04.2017
// Регулировка резистором ПВ и ОВ вентеляции полностью!!!!!!!!!!!!
// из 170422_2_3_прогон.txt   - переключение меж Ручная регулировка и прогон
// 
/
//  70- в ручном режиме вроед 100процентов


// Что доделать:
// - задавать значения производительности ву
// - сохранение в еепром
// -



// для автоматического нажатия 
unsigned long previousMillisPush = 0; 
byte stagePush = 0;
byte AirIn[] = {9, 9, 7, 9, 9, 7, 11, 7, 7, 0 };   // очередность нажатия кнопопок для ввода притока
//byte AirIn[] = {9, 9, 12, 11, 7, 9, 9, 7, 11, 7, 7, 0, 0 };   // очередность нажатия кнопопок для ввода притока
byte AirEnd[] = {7, 7, 9, 9, 0 };   // очередность нажатия кнопопок для ввода притока
byte x=0; // номер элемента массива
//stage





// Влючение подгонки параметров 
unsigned long previousMillisVetn = 0; 
byte stageScr = 0;


// Потенциометр задающий производительность
#define potPot A7
int Pot=200;  // то что фильтрации через PotMid заданно с резистора
int PotMid=200;  // введ чтобы убрать перепрыгивание на +- 1
int Potprevious=200;
int PotTemp=200;
byte StopAllInput=0 ; // Если =1 то кнопки не нажимаются, идет подгонка значения призводительности вентелятора. 
byte z=0; // нужна для отладки, отслеживание первого запуска. 

        byte VentIn=20;//!!!!!!!!!!!! Это значение нужно будет хранит в ЕЕпроме и оно будет хранить текущее значение на установке!!!
                      // нужно будет сначала считать из еепром, проверить пометку, что запиь был закончена, если процедура сохранения 
					  // не была закончена то выдать сообщение об ошибке и перейти в аварийный режим ()

        byte VentOut=33;  // будет хранит в ЕЕпроме и оно будет хранить текущее значение ОВ на установке!!!
		
		byte VentOutCalc=0; // расчетное значение ОВ 
		
		long VentOut100 = 0;  // для расчета ОВ - вспомогательное 
		
		
		
		
int DiffAirIn =0; // разница между Pot и VentIn. .

int DiffAirOut =0; // разница между VentOutCalc и VentOut. 
 

//  Включение прогона
unsigned int previousMillisTestOn = 0;
byte stageTestOn = 0;





int ledPin=13;
  
  
// Работа с кнопками  

int ContactPin1=9; //Контакт сенсорной конпки
int ContactPin2=7; //Контакт сенсорной конпки
int ContactPin3=11; //Контакт сенсорной конпки
int ContactPin4=12; //Контакт сенсорной конпки

//int btp=2;  //Кнопка
unsigned long previousMillis = 0; 
byte stage = 0;   //  =1 означает задача на нажатие кнопки под номером ContactN
byte ContactN=0;

int btp1=2;  //Кнопка1
int btp2=3;  //Кнопка2
int btp3=4;  //Кнопка3
int btp4=5;  //Кнопка4





void setup() {

pinMode(potPot, INPUT);

pinMode(ContactPin1,OUTPUT);
pinMode(ContactPin2,OUTPUT);
pinMode(ContactPin3,OUTPUT);
pinMode(ContactPin4,OUTPUT);

Serial.begin(9600);
pinMode(ledPin,OUTPUT);
}

void loop() {



//  Включение прогона , переключение между ручным и прогоном

if ( stageTestOn == 0 && analogRead(potPot)>=700 ||  stageTestOn == 2 && analogRead(potPot)>=850   )  //  
{
previousMillisTestOn=millis();
// Serial.println("stageTestOn == 0 старт");
++ stageTestOn;
//stageTestOn = 1;
 //Serial.println("stageTestOn == 0 stop ");
}

if ( stageTestOn == 1 && analogRead(potPot) <=100  && millis() - previousMillisTestOn<=1000  || stageTestOn == 3 && analogRead(potPot) <=100  && millis() - previousMillisTestOn<=1000    ) //  
{
// Serial.println("stageTestOn == 1 старт");
//delay(2000);
++stageTestOn;
//stageTestOn = 2;
Serial.print("stageTestOn =  ");
Serial.println(stageTestOn);

}
if ( stageTestOn == 1   && millis() - previousMillisTestOn>=1100 ) //  
{
stageTestOn = 0;
// Serial.println("stageTestOn == 0 ");
}

if ( stageTestOn == 3   && millis() - previousMillisTestOn>=1100 ) //  
{
stageTestOn = 2;
// Serial.println("stageTestOn == 0 ");
}






//  Переключение производительности при прогоне
if ( stageTestOn == 2 && millis() - previousMillisTestOn >= 30000  && stageScr == 0 && stagePush == 0 )  //    
{
PotMid = (20+(random(0, 9)))*10;
Serial.print(" PotMid=   ");
Serial.println(PotMid);


Serial.print(" stageTestOn=   ");
Serial.println(stageTestOn);

Serial.println(" Changing the production  ");

previousMillisTestOn=millis();

}







//!!!!!!!!!!!!! Первый запуск Блок наду будет убрать. Он нужен только для отклаки. При первом цикле Potprevious делает равным Pot
if (z==0)
{
// Serial.println( " First start ");



Serial.print(" stageTestOn=   ");
Serial.println(stageTestOn);

//VentIn = (analogRead(potPot))/10;
//Serial.print( "VentIn ");//
//Serial.println( VentIn);

//Pot = VentIn*10; 
////Serial.print( "Pot ");
//Serial.println( Pot);

//Potprevious= Pot;
//Serial.print( "Potprevious ");
//Serial.println( Potprevious);


++z;
Serial.println( "First start finished ");
}







// для автоматического нажатия (входа в режим регулирования производительности)
 if ( stagePush == 1 && stage == 0  )  //  задеме кнопку для нажатия
{
// Serial.println("!!! получил эстафету от stageScr ");
stage = 1;
//x=0;
ContactN=AirIn[x];

stagePush = 2;
// Serial.println("  stagePush == 1 is finised ");
}

 
 if ( stagePush == 2 && random(150, 300)+ millis()-previousMillisPush>=400 )  //  ждем, что бы передать действие для следующего 
{                                                                           //нажатия или выхода из процеудры
++x;   // переходим к нажатию следующей кнопки
     if (AirIn[x]==0)   // если кнопка 0,то выходим из процедуры
     {
       stageScr = 2 ;
       stagePush=0;
       x=0;
	   Serial.println("  stagePush == 2 is finised. Geving the right to stageScr = 2 ");
     }    // возвращаемся к выполнению stageScr=2
else   // если кнопка 0 то передаем в начало 
{ 
stagePush = 1;
// Serial.println("окончание stagePush == 2 ");
} 
}





// для  подгонки приточноно воздуха
 if ( stagePush == 5 && stage == 0 && DiffAirIn!=0 )  //  
{
// Serial.println("taking the right from  stageScr for  stagePush == 5");
stage = 1;  // Нажимаем кнопку, котору задали в stageScr == 2

stagePush = 6;
// Serial.println(" finishing stagePush == 5 ");
}


 
 if ( stagePush == 6 && random(150, 300)+ millis()-previousMillisPush>=400 )  //  ждем, отпускаем кнопку и передем действие для следующего 
{                                                                           //нажатия или выхода из процеудры
 // Serial.println("!!! получил эстафету от stagePush == 5 для  stagePush == 6");
 
 --DiffAirIn;   // минусуем разницу в показаниях 
 
 if (ContactN==12)
 {  ++VentIn ; }
 if (ContactN==11)
 {--VentIn ;}
 
	if (DiffAirIn==0)   // если сравняли показатели,то выходим из процедуры !!!!!!!!!! если перепрыгнет на 0 чуть позже то входит 
     {                     // в бесконечный цик. На будет проверять например если DiffAirIn не уменьшается то выход из цикла
       stageScr = 3 ;
       stagePush=0;
       //x=0;
	   Serial.println(" Have finished correction InAir");
	   
     }    // возвращаемся к выполнению stageScr=3
     else   // если кнопка 0 то передаем в начало 
    { 
     stagePush = 5;
     // Serial.println("окончание stagePush == 6 перевощим на stagePush == 5  ");
    } 
}



 
// для  подгонки ОВ
 if ( stagePush == 11 && stage == 0 )  //  
{
// Serial.println("taking the right from stageScr from  stagePush == 11");
stage = 1;  // Нажимаем кнопку, котору задали в stageScr == 4

stagePush = 12;
// Serial.println("finishing stagePush == 5 ");
}


 
 if ( stagePush == 12 && random(150, 300)+ millis()-previousMillisPush>=400 )  //  ждем, отпускаем кнопку и передем действие для следующего 
{                                                                           //нажатия или выхода из процеудры
//  Serial.println("!!! получил эстафету от stagePush == 11 для  stagePush == 12");
 
 --DiffAirOut;   // минусуем разницу в показаниях 
 
 if (ContactN==12)
 {  ++VentOut ; }
 if (ContactN==11)
 {--VentOut ;}
 
	if (DiffAirOut==0)   // если сравняли показатели,то выходим из процедуры !!!!!!!!!! если перепрыгнет на 0 чуть позже то входит 
     {                     // в бесконечный цик. На будет проверять например если DiffAirIn не уменьшается то выход из цикла
       stageScr = 5 ;
       stagePush=0;
       	   Serial.println(" Have finished the correction of OutAir");
	   
     }    // возвращаемся к выполнению stageScr=3
     else   // если кнопка 0 то передаем в начало 
    { 
     stagePush = 11;
     // Serial.println("окончание stagePush == 12 перевощим на stagePush == 11  ");
    } 
}
















// для автоматического сохранения данных после изменения производительности
 if ( stagePush == 13 && stage == 0  )  //  
{
// Serial.println("!!! получил эстафету от stageScr  для stagePush == 8");
stage = 1;   //Нажимаем кнопку,
//x=0;
ContactN=AirEnd[x]; // Задали кнопку, которую надо давить

stagePush = 14;
// Serial.println("окончание stagePush == 9 ");
}

 
 if ( stagePush == 14 && random(150, 300)+ millis()-previousMillisPush>=400 )  //  ждем, что бы передать действие для следующего 
{                                                                           //нажатия или выхода из процеудры
++x;   // переходим к нажатию следующей кнопки
     if (AirEnd[x]==0)   // если кнопка 0,то выходим из процедуры
     {
       stageScr = 6 ;
       stagePush=0;
       x=0;
     }    // возвращаемся к выполнению stageScr=2
else   // если кнопка 0 то передаем в начало 
{ 
stagePush = 13;
// Serial.println("окончание stagePush == 10 ");
} 
}





//  Нажать одну кнопку, что бы начать регулировать ОВ --- старое : для автоматического сохранения данных после изменения производительности 2104 stagePush == 9 нажимает 10 -ок
 if ( stagePush == 9 && stage == 0  )  //
 
{
// Serial.println("!!! получил эстафету от stageScr  для stagePush == 9");



ContactN=7; // Задали кнопку, которую надо давить

stage = 1;   //Нажимаем кнопку,



stagePush = 10;
// Serial.println("окончание stagePush == 9 ");
}

 
 if ( stagePush == 10 && random(150, 300)+ millis()-previousMillisPush>=800 )  //  ждем, что бы передать действие для следующего 
                                                  //previousMillisPush>=800 увеличил с 400 до 800
 {                                                                           //нажатия или выхода из процеудры
// Serial.println("!!! получил эстафету от stageScr9  для stagePush == 10");
      
	  stageScr = 4 ;
       stagePush=0;
       
// Serial.println("окончание stagePush == 10 ");
} 



// Блок следит за напряжением на резюке
// и убирающий перепрыгивание значений на 1


if ( stageTestOn == 4  && stageScr == 0 && stagePush == 0  ) //  
{

//Serial.println("stageTestOn == 2 ");


PotMid = (analogRead(potPot));  //что там накрутили резистором
PotMid = map(PotMid, 0, 900, 200, 850);
PotMid = constrain(PotMid, 200,800 );
}

if (Pot-PotMid>= 10 || PotMid-Pot>=10)
{
Pot=PotMid;
}



if (Pot-Potprevious>= 20 && stageScr==0  || Potprevious-Pot>=20  && stageScr==0  )  //  Начинается или сбрасывается отчет для начала проценуры корректировки (что на резисторе,  такая и производительность)
{
PotTemp = Pot;  // для отслеживания, вдруг не перестали еще крутить
stageScr = 1;   //  Запускаем процедуру корректировки 
previousMillisVetn = millis();    // запускаем или обнуляем таймер процедуры
// Serial.println("Начинается или сбрасывается отчет начала проценуры корректировки (что на резисторе такая и производительность)  ");
//Serial.print( "Z=........ ");
//Serial.println(z);

}


if ( PotTemp != Pot && stageScr==1  )  //   сбрасывается отчет если не перестали еще крутить
{
PotTemp = Pot;   // для отслеживания, вдруг не перестали еще крутить
stageScr = 1;
previousMillisVetn = millis();
//Serial.println("if ( PotTemp != Pot && stageScr==1  )  ");

Serial.print("PotTemp = ");
Serial.println(PotTemp);
Serial.print("Pot = ");
Serial.println(Pot);

}


if (stageScr == 1 && Pot-Potprevious<= 2  && Potprevious-Pot<=2   )  //  Сброс состояния если текущие параметры в пределах +-2 от того, которые был до того, как начали круить резистор
{
stageScr = 0;
Serial.println(" Reseting the current stage as far as correcion withing +-2  ");
}

 if ( stageScr == 1 && millis() -previousMillisVetn>=3000 && StopAllInput==0 && stagePush ==0 )  // заблокировали все кнопки и начали подгонять значения
{
stageScr = 20; // это сделает stagePush когда закончит 
StopAllInput=1;  // заблокировали все кнопки

stagePush = 1;  // Передали эстафету stagePush- процедура нажатия кнопок
 
Serial.println(" blocking all buttons ");
//delay(1000);
Serial.print("Resistor =  ...... ");
Serial.println( Pot);
Serial.println("stageScr 1  Ended");
}


if (  stageScr == 2 )     //  
{
DiffAirIn=(Pot/10)-VentIn;    //     сколько раз будем нажимать кнопку + или -
Serial.print( "DiffAirIn = ");
Serial.println( DiffAirIn);
if (DiffAirIn==0  )
{
stageScr = 6;
}
}

if (  stageScr == 2)     //  
{
stageScr = 20;    //      !!! Временно, надо поставить отличное от 0 и 2

Serial.println("giving the right to stagePush- Now InAir is ON   ");

// Определяем какую кнопку будем нажимать+ или -
//DiffAirIn=(Pot/10)-VentIn;    //     сколько раз будем нажимать кнопку + или -
//Serial.print( "DiffAirIn = ");
//Serial.println( DiffAirIn);

if (DiffAirIn>0)  
{
ContactN=12;
}

if (DiffAirIn<0)
{
ContactN=11;
DiffAirIn=DiffAirIn*(-1); //- меняем на +
}
Serial.print( "after +-    DiffAirIn = ");
Serial.println( DiffAirIn);

stagePush = 5;  // Передали эстафету stagePush- процедура подгонки притока

Serial.println("stageScr 2 Ended");
//Serial.print("Значение производительности:     ");
//Serial.println( Pot);
}



if (  stageScr == 3)     //  Нажать одну кнопку, что бы начать регулировать ОВ  21.04 нажимать 10- ОК
{
stageScr = 20;
Serial.println(" Starting tageScr == 3 ");

stagePush = 9;  // Передали эстафету stagePush- процедура нажатия кнопок


Serial.println("stageScr 3 Ended");
//Serial.print("Значение производительности:     ");
//Serial.println( Pot);

}



if (  stageScr == 4)     //  
{
stageScr = 20;    //      !!! Временно, надо поставить отличное от 0 и 2

Serial.println("giving the right to stagePush- Now Out air is ON ");




// Расчет необходимого ОВ
VentOut100 = ((((long(VentIn)*100)-2000)*112)/100+3300)/100;
VentOutCalc =byte(VentOut100);


//Serial.print( "VentIn = ");
Serial.print( VentIn);
Serial.print( "---");

//Serial.print( "VentOut100 = ");
Serial.print( VentOut100);
//Serial.println();
Serial.print( "---");

//Serial.print( "VentOutCalc = ");
Serial.println( VentOutCalc);
//Serial.printlnVentOutCalc




// Определяем какую кнопку будем нажимать+ или -
DiffAirOut= VentOutCalc - VentOut ;    //     сколько раз будем нажимать кнопку + или -
Serial.print( "DiffAirOut = ");
Serial.println( DiffAirOut);

if (DiffAirOut>0)  
{
ContactN=12;
}

if (DiffAirOut<0)
{
ContactN=11;
DiffAirOut=DiffAirOut*(-1); //- меняем на +
}
Serial.print( "after +-    DiffAirOut = ");
Serial.println( DiffAirOut);


stagePush = 11;  // Передали эстафету stagePush- процедура подгонки ОВ

Serial.println("stageScr 4 Ended");
//Serial.print("Значение производительности:     ");
//Serial.println( Pot);
}


if (  stageScr == 5)     //  для автоматического сохранения данных после изменения производительности и выхода из режима регулировки
{
stageScr = 20;
//Serial.println("Начали tageScr == 5 ");
stagePush = 13;  // Передали эстафету stagePush- процедура нажатия кнопок
//Serial.println("stageScr 5 Ended");

}



if (  stageScr == 6)     // 
{

// 

delay(1000);




                       Potprevious= Pot;//!!!!!!!!!!!!!!! ДЛЯ ДЕБАГА, ПОСЛЕ ПЕРЕСМОТРЕТЬ
                       PotTemp = Pot; //!!!!!!!!!!!!!!! ДЛЯ ДЕБАГА, ПОСЛЕ ПЕРЕСМОТРЕТЬ
                       stageScr = 0;  //!!!!!!!!!!!!!!! ДЛЯ ДЕБАГА, ПОСЛЕ ПЕРЕСМОТРЕТЬ
                       stagePush = 0;
					   
					   
					   
                         StopAllInput=0;

//Serial.println("stageScr 6 Ended");
Serial.println(" Complited corretion  ");
Serial.println();
Serial.println();
//Serial.print("Значение производительности:     ");
//Serial.println( Pot);

//!!!!!!!!!!!! Задать триггер по которому будет считаться, что действие выполненно
}








if (digitalRead(btp1)==HIGH && stage == 0 && StopAllInput==0)  // Включается и Начинается отчет
{
stage = 1;
ContactN=9;
}
if (digitalRead(btp2)==HIGH && stage == 0 && StopAllInput==0 )  // Включается и Начинается отчет
{
stage = 1;
ContactN=7;
}
if (digitalRead(btp3)==HIGH && stage == 0 && StopAllInput==0)  // Включается и Начинается отчет
{
stage = 1;
ContactN=11;
}if (digitalRead(btp4)==HIGH && stage == 0 && StopAllInput==0)  // Включается и Начинается отчет
{
stage = 1;
ContactN=12;
}



 if ( stage == 1)  // Включается и Начинается отчет
{
previousMillis = millis();
stage = 2;
digitalWrite(ledPin,HIGH);
pinMode(ContactN,INPUT); 
//Serial.println(ContactN );
//Serial.println("Start counting  and is on ");
}

if (millis() -previousMillis>=70 && stage == 2)     // Выключается
{
pinMode(ContactN,OUTPUT); 
digitalWrite(ledPin,LOW);
stage = 3;
//Serial.println("is off ");
Serial.print("                   Amulating the pushing   ");
Serial.println(ContactN );
}

if (millis() -previousMillis>=800 && stage == 3)      // Готов к следющему нажатю
{
stage = 0;

previousMillisPush = millis();  // это нужно ждя stagePush.

previousMillis = millis();

//Serial.println("Ready for the next push ");
}



}


 

 

Damir Galeev
Offline
Зарегистрирован: 17.03.2021

Привет!                   

Есть ли более актуальная информация по данной теме? Возникла аналогичная задача. Можете поделиться более актуальными схемами реализации: что и как лучше подключать и код? Спасибо заранее!