Странное поведение программы

mulder
Offline
Зарегистрирован: 30.01.2017

Добрый день. Отладочная плата Nano 328p

Вот ломаю голову, над вопросом - что ей надо.

Написал процедуру которая должна отсеивать дребезг контактов на кнопке. Кнопка сенсорная. И она это качественно делает (встроенная в ардуину показалась очень не практичной).

И вот что я заметил. Когда подключаешь отправку данных в порт. Она работает исправно. Но когда применяешь эту процедуру без отправки в  порт статистики. Она один цикл отправляет с нулём, а второй с единицей. Получается 50/50 правильных сигналов.

bool drebezg(int massiv[],int buttonPin) {  //Удаляем мопехи выясняем действительно ли мы нажали кнопку или нет
/* эта часть сдвигает массив в право, и наполняет его новыми значениями */
  for (int i=0; i <= 8; i++){massiv[9-i] = massiv[8-i];} // сдвиг массива в право 
  massiv[0] = analogRead(buttonPin); //добавляем новое значение 

/* Эта часть суммирует значения если значения большие, значит сигнал уверенный и это не дребезг. Если маленькие, то это дребезг и ложное срабатывание */
  int znachenie = 0; 
  int rezultat;
  for (int i=0; i <= 9; i++){znachenie = znachenie + massiv[i];}
  if (znachenie > 50) {rezultat = 1;} else {rezultat = 0;}  
  //Serial.println(rezultat);  
  return rezultat;
}

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

Однако delay, и выполнение процедуры по разным тактам, успехов не принесло.

Какой-то полтергейст)

b707
Offline
Зарегистрирован: 26.05.2017

Хм, а разве можно так массив в процедуру передавать?

mulder
Offline
Зарегистрирован: 30.01.2017

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

b707
Offline
Зарегистрирован: 26.05.2017

Ну насчет "много байт " при использовании ссылки - вас обманули. А для чего вообще этот массив должен быть внешним? Почему не завести его прямо в процедуре?

mulder
Offline
Зарегистрирован: 30.01.2017

вот у меня "рояль" много много кнопок. Все дребезжат как цикады июльским вечером. И одна функция, которую можно прописать к каждой кнопке одной строкой. А не повторять один и тот же код 52 раза в основной процедуре. Это очевидно. Этот ответ поможет в решении проблемы?

mulder
Offline
Зарегистрирован: 30.01.2017

Покажите пример передачи массива удобным для вас способом.

Что можете сказать по поводу данного поведения прграммы?

b707
Offline
Зарегистрирован: 26.05.2017

mulder пишет:

вот у меня "рояль" много много кнопок. Все дребезжат как цикады июльским вечером. И одна функция, которую можно прописать к каждой кнопке одной строкой. А не повторять один и тот же код 52 раза в основной процедуре. Это очевидно. Этот ответ поможет в решении проблемы?

отлично. А теперь, внимание, вопрос - а сколько массивов вы используете для сглаживания дребезга 52х кнопок?

Приведите весь код программы, мне нужно видеть, как описан массив и как вы его передаете

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

у тя кнопка отдает аналоговое значение?  И, если да, в каком диапаносе величин примерно, когда нажата и когда не нажата?

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

Можете подготовить компактный, но полный пример, демонстрирующий  проблему?

Компактный == ничего лишнего, не надо 100500 строк про LCD, связь со спутником и отправку смс Вашей бабушке.

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

mulder
Offline
Зарегистрирован: 30.01.2017

Вот скетч.

//***Данные кнопки 1***
bool tag1 = 1;
int mas1[10]={0};
int sred_znach = 0;
int rez1 = 0;

void setup() {    
pinMode(PC5, INPUT); //Button_
Serial.begin(9600);

// Значения по умолчанию
digitalWrite(13, LOW);// выключам лампу
digitalWrite(PD2, 1); //Button_    
}

bool drebezg(int massiv[],int buttonPin) {  //Удаляем мопехи выясняем действительно ли мы нажали кнопку или нет
/* эта часть сдвигает массив в право, и наполняет его новыми значениями */
  for (int i=0; i <= 8; i++){massiv[9-i] = massiv[8-i];} // сдвиг массива в право
  // (int i=0; i <= 9; i++){Serial.print(massiv[i]); Serial.print(",");}Serial.println(" "); // отображаем что получилось 
  massiv[0] = analogRead(buttonPin); //добавляем новое значение 
  Serial.println( massiv[0]);  

/* Эта часть суммирует значения если значения большие, значит сигнал уверенный и это не дребезг. Если маленькие, то это дребезг и ложное срабатывание */
  int znachenie = 0; 
  int rezultat;
  for (int i=0; i <= 9; i++){znachenie = znachenie + massiv[i];}
  if (znachenie > 50) {rezultat = 1;} else {rezultat = 0;}  
  //Serial.println(rezultat); // с ним работает как надо, а без него как получится. 
  return rezultat;
}

bool Button(int massiv[],int buttonPin, bool tag, byte pin_out) { // Логика кнопки: Нажал - запустилась, отжал -ничего не произошло. Снова нажал - выключилась. Отжал - ничего не произошло
  int signal_knopki = drebezg(massiv,buttonPin);
  int tg = tag;
  if ((signal_knopki == 1)&&(tg == 0)) {
    digitalWrite(pin_out, !digitalRead(pin_out) ); tg = 1;  
    return tg; 
  }  
  if ((signal_knopki == 0)&&(tg == 1)) {tg = 0; return tg;}  
}

void loop() {
   tag1 = Button(mas1,PC5,tag1,13); 
}

Вот схема подключения:

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

С1 зарядившись, подаёт на A5 значение приближенное к 0. Когда подносишь палец к пластине, на палец бежит заряд, и А5 начинает получать значение выше больше 0. Так работает сенсорная кнопка.

R2 это защита от статики, чтобы пальцем не убить микроконтроллер.

b707
Offline
Зарегистрирован: 26.05.2017

mulder - а какое значение возвращает процедура Button, если не выполняется ни условие строки 35, ни условие строки 39?

 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

mulder пишет:

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

Нет, набарот, чем меньше R1, тем меньше ложных срабатываний.

 

mulder пишет:

С1 зарядившись, подаёт на A5 значение приближенное к 0. Когда подносишь палец к пластине, на палец бежит заряд, и А5 начинает получать значение выше больше 0. Так работает сенсорная кнопка.

R2 это защита от статики, чтобы пальцем не убить микроконтроллер.

С1 ничо никуда не подает, зарядившись.  0 на А5 подает резистор, опять же R1.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Попробуй, что будет отдавать кнопка? 

bool ReadButton(const uint8_t AButtonPin) {
	uint16_t result = 0;
	uint16_t value = 0;

	for (uint8_t i = 0; i < 16; i++) {
		value = analogRead(AButtonPin);
		if (value < 10) return false;
		result += value;
	}
	return (result >> 4) > 300;
}

вставь в loop куданить

Serial.println(ButtonRead(A5));

и посмотри что выводица в сериал при нажатой и ненажатой кнопке

 

mulder
Offline
Зарегистрирован: 30.01.2017

Она ничего не будет возвращать. Это исключено.

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

Вопрос в другом - попробуйте у себя. С отсылкой статистики в порт всё работает идеально.

Как только статистики нет, кто-то начинает половину сигналов воровать. Прямо как у нас в стране. Пока контроллируешь, проблем нет. Отвернулся - стали тырить и работать коекак

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

mulder пишет:

Она ничего не будет возвращать. Это исключено.

Матьтваю, функция описана как bool, значит она ОБЯЗАНА возвращать bool.  Это будет или то, что ты ей скажешь возвращать, или мусор по её усмотрению. 

mulder
Offline
Зарегистрирован: 30.01.2017

Отдаёт одни Нули.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Попробуй заменить на   return (result >> 4) > 200;

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Мне надо понять, какие вапще значения на A5 када пальцем в сенсор тыкаешь?

Скорее всего, там будет синус с периодом 20мс. 

b707
Offline
Зарегистрирован: 26.05.2017

mulder пишет:

Она ничего не будет возвращать. Это исключено.

какой бред.

Попробуйте сами смоделиовать ситуацию. Кнопка нажата и tag =0 - срабатывает условие 35, tag меняется на на 1. Далее кнопка все еще нажата, а tag =1. сл-но не выполняется ни условие 35, ни 39.  и что тогда????????

b707
Offline
Зарегистрирован: 26.05.2017

Дед, зря ты про синус стер. Синус-ни синус, а периодическое "мигание" 0-1-0-1-0...

Собственно, на это пациент и жалуется. ошибка в логике.

А что про массив скажешь - можно так передавать? - первый раз такую записаь вижу

mulder
Offline
Зарегистрирован: 30.01.2017

Функция кнопки  возвращает  только те значения, на которые рассчитана.  Исключительных ситуаций нет. она либо отдаёт 1 когда сигнал есть, либо 0 кода его нет. промежуточных и произвольных значений нет. Тем более, эта функция управляет только светодиодом. Если в друг и попадётся исключительная ситуация. То она вернёт то значение которое было вводным.

bool Button(int massiv[],int buttonPin, bool tag, byte pin_out) {
  int signal_knopki = drebezg(massiv,buttonPin);
  int tg = tag;
  if ((signal_knopki == 1)&&(tg == 0)) {
    digitalWrite(pin_out, !digitalRead(pin_out) ); tg = 1;  
    return tg; 
  }
  
  if ((signal_knopki == 0)&&(tg == 1)) {tg = 0; return tg;}
  //Serial.println(tg); 

  if (((signal_knopki == 1)&&(tg == 1))or((signal_knopki == 0)&&(tg == 0))){return tag;}// на случай исключительной ситуации
}

Вот специально влепил костыль на всякий случай. Тоже самое получилось

 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

b707 пишет:

Дед, зря ты про синус стер. Синус-ни синус, а периодическое "мигание" 0-1-0-1-0...

Собственно, на это пациент и жалуется. ошибка в логике.

А что про массив скажешь - можно так передавать? - первый раз такую записаь вижу

массивы так и передают, только обычно и размер передается, ему в довесок

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

в этой теме я - пас, поциэнт невменяем. 

mulder
Offline
Зарегистрирован: 30.01.2017

А вот стоит влепить в функцукию Serial.println("чтото там"); Как всё работает как надо. Загадка.

 Попробую указать длину массива. Может поможет.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

mulder пишет:

 Попробую указать длину массива. Может поможет.

Нет. 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

короче, я б на месте ТС купил бы пучок TTP223 за писят рублей, раз хочеца тёплой ламповой сенсорности, настроил её триггером и не парил бы никому мосх. 

mulder
Offline
Зарегистрирован: 30.01.2017

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

Про TTP223 тоже думал. Но в панелях вытяжек она не применяется. А применяется именно та, упрощённая схема. Если её победить, будет меньше мороки с переделкой.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

mulder пишет:

Плата питается от порта USB. Может пульсация какая от ноута? 

Ты не поверишь.  Пульсация не от ноута, а ОТ ПАЛЬЦА.  И, вангую, с частотой 50 Герц. 

b707
Offline
Зарегистрирован: 26.05.2017

mulder пишет:

Если вдруг и попадётся исключительная ситуация. То она вернёт то значение которое было вводным.

это очень грубая ошибка. Функция возвращает то, что вы ей указали.

Цитата:
Вот специально влепил костыль на всякий случай. Тоже самое получилось

это не "на всякий случай" - а абсолютно необходимо в этой процедуре. Если вы этого не понимаете - значит нужно изучать программирование тщательнее.

А последнюю строчку можно было записать много проще -

return tag;

без всяких условий

mulder
Offline
Зарегистрирован: 30.01.2017

Да, получается этот эффект идёт от пульсации человеческого тела. Когда подключаешь через 5 вольт, всё попадает. Но почему при отправке статистики всё работает как часы - непонятно. Будем ждать TTP223 Думаю только она может решить эти проблемы.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

mulder пишет:

эффект идёт от пульсации человеческого тела

Удивительно, правда?

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

DetSimen пишет:

Удивительно, правда?

Конечно, удивительно! Пульс человека 1 герц, а там откуда-то аж 50!

sadman41
Offline
Зарегистрирован: 19.10.2016

Человек нервный попался (или рептилоид) - вот и бьёт пульс.

Green
Offline
Зарегистрирован: 01.10.2015

50 гц никак. Максимум в минуту: 220 - возраст. У себя наблюдал 194 макс. А это всего 3 Гц.)

mulder
Offline
Зарегистрирован: 30.01.2017

На счёт рептилоида не знаю, но если бы им был, за ардуино бы не сидел.)))

Кто нибудь повторял на макетке по этому вопросу опыт? получилось повторить странный эффект?

Может мы так разработаем прибор определения рептилоидов ))))

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

Простите, какой странный эффект? Абсолютно нормальный в рамках приведённой схемы. Ничего другого и не ожидалось. Обработать правильно и получить нужный результат. Всевото делов. Если человек имел дело с радио и понимает что такое длина антенны и как меняется напряжение на входе приёмника при изменении длины антенны, то проблем с пониманием как работает сенсорная кнопка - на изменении длины антенны, не будет. Нет никакого заряда человека.

mulder
Offline
Зарегистрирован: 30.01.2017

Получилось обойти проблему. Как говорится в том анекдоте - Вытащить не вытащили, но батарейки поменяли.

struct knopka //структура
{
byte number_pin_in;
byte number_pin_out;
int znach;
unsigned long Time_;
bool status_knopki; //сигнал нажата ли кнопка или нет
bool tag; //триггер для функции (knopka) удержания кнопки
};

//***Данные кнопки 1***
knopka knopka1;

// the setup function runs once when you press reset or power the board
void setup() {
    pinMode(PC5, INPUT); //Button_

Serial.begin(9600);

// Значения по умолчанию
digitalWrite(13, LOW);// выключам лампу
digitalWrite(PD2, 0); //Button_

knopka1.number_pin_in = PC5;
knopka1.number_pin_out = 13;
knopka1.znach = 0;
knopka1.Time_ = 0;   
knopka1.status_knopki = 0; 
knopka1.tag = 0;
}

knopka drebezg(knopka Kn) {// Удаляем мопехи выясняем действительно ли мы нажали кнопку или нет
  int tg = millis() - Kn.Time_; //Разница между пройденным временем и временем прослушивания порта
 //Serial.println(analogRead(Kn.number_pin));   
  if (analogRead(Kn.number_pin_in)>10) {  Kn.znach = Kn.znach + 1;  } //Если приходящий сигнал больше значения "шума", значит пришёл сигнал - увеличиваем счётчик на 1
  if (tg >= 200) {  //Если счётчик времени дошёл до нужного значения    
    if (Kn.znach>100) {  Kn.status_knopki = 1;} else {Kn.status_knopki = 0; }  //Если за указанное время насчиталось указанное количевто сигналов
    Kn.znach=0; 
    Kn.Time_ = millis(); 
    }    
  return Kn;
}

knopka Button(knopka Kn) {// Функция кнопки
  Kn = drebezg(Kn);
  if ((Kn.status_knopki == 1)&&(Kn.tag == 0)) {    digitalWrite(Kn.number_pin_out, !digitalRead(Kn.number_pin_out) ); Kn.tag = 1; return Kn;   }
  if ((Kn.status_knopki == 0)&&(Kn.tag == 1)) {Kn.tag = 0; return Kn;}
  //Serial.println(Kn.tag); 
  return Kn;//
}

void loop() {
knopka1 = Button(knopka1);  
}

 

mulder
Offline
Зарегистрирован: 30.01.2017

И то чего же такой эффект? А именно, при отсылке в порт всё как часы, а без него синусоида цифровая)). Расскажите, тут уже куча желающих наверное.

 

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

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