Помогите с кодом для дискретного входа

9ser
Offline
Зарегистрирован: 18.11.2012

Доброго времени суток.

Помогите с кусочком программы:

Цель: выводить в потр или через Enthernet sheld команду при замыкании дискретного входа

**/
int pirPin = 7; // присваеваем 7 ноге название pirPin
...
...
...
// Настройка портов на вывод
  pinMode (pirPin, INPUT);  // Настройка порта как вход
  digitalWrite(pirPin, LOW); // Установить на 7 ноге низкий уровень
...
...
...
void CheckMotion()
{
motionDetected = 0;
if(digitalRead(pirPin) == HIGH){
Serial.println("yes"); motionDetected = 1;
}else{
Serial.println("no");
motionDetected = 0;}
}

Вот кусок кода ...

В у меня получается что если на входе LOW в порт постоянно передает "no"

Когда на входе HIGH в порт постоянно передает "yes"

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

Вот в этом не получается разобратся (мало опыту по программированию)

nestandart
nestandart аватар
Offline
Зарегистрирован: 15.06.2011

Недавно написал довольно объемную статью о кнопках. Там есть то что вам нужно.

Вот http://forumdvrobot.ru/forum/3-21-1 Шестой пример кода. 

maksim
Offline
Зарегистрирован: 12.02.2012

Для этого нужно объявить переменную, которая будет хранить последнее состояние кнопки и когда текущее состояние отлично от последнего, то в этот момент и выводить данные в сериал и текущее состояние кнопки сохранить как последнее.

**/
byte pirPin = 7; // присваиваем 7 ноге название pirPin
byte motionDetected_prev = 0;
...
...
...
void CheckMotion()
{
  if(digitalRead(pirPin) |= motionDetected_prev){
    if(digitalRead(pirPin) == HIGH){
      Serial.println("yes"); 
      motionDetected = 1;
    }
    else{
      Serial.println("no");
      motionDetected = 0;
    }
    motionDetected_prev = motionDetected;
  }
}

 

Эти строки можете удалить, они бессмысленны

// Настройка портов на вывод
pinMode (pirPin, INPUT);  // Настройка порта как вход
digitalWrite(pirPin, LOW); // Установить на 7 ноге низкий уровень

если находятся в setup и используются только в начале при настройке.

9ser
Offline
Зарегистрирован: 18.11.2012

nestandart:  спачибо огромное за ссылку. Очень хорошо описано.

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

* функция проверки команд
**/
void inputcommands()
{
   if(digitalRead(startPin)==HIGH&&flag==0)
   {
   Serial.print("1");
   flag=1;
   delay(10);
   }
   if(digitalRead(startPin)==LOW&&flag==1)
   {
   Serial.println("0");
   flag=0;
   delay(10);
   }
}  

 

9ser
Offline
Зарегистрирован: 18.11.2012

подскажите как можно сделать опрос только для нескольких портов разом:

byte startPin=1;
byte endPin=5;
...
void CheckMotion(){
for (int thisPin = startPin; thisPin <=endPin; thisPin++)

 

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Опрос нужных пинов можно сделать, например, записав номера пинов в массив (особенно, если они расположены не друг за другом):

#define MAX_PINS 4
const byte pin_array[MAX_PINS] = { 1, 5, 3, 2 };
...

for( i = 0; i < MAX_PINS; ++i )
{
  byte l_pin_state = digitalRead( pin_array[ i ] );
  ...
}

Массив также можно использовать для инициализации этих пинов в setup()

UPD: исходник немного поправил, const забыл

9ser
Offline
Зарегистрирован: 18.11.2012

а как быть со старым значанием pin с которым сравниваем и выполняем действие если значание изменилось относительно предыдущего именно этого порта???

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Добавьте еще один массив, он будет хранить предыдущие значения. Сравниваете текущие значения со значениями из массива и знаете где что изменилось. После сравнения изменившиеся значения пишите в массив для сравнения в следующем цикле.
Массив для моего примера можно описать так: byte val_array[MAX_PINS] ={ 0, 0, 0, 0 };

9ser
Offline
Зарегистрирован: 18.11.2012

как-то не получается?

#define MAX_PINS 4 //максимальное количество входоа 4
const byte pin_array[MAX_PINS] = { 1, 3, 4, 5 }; //номера пинов
byte val_array[MAX_PINS] ={ 0, 0, 0, 0 }; //предыдущие значения портов
void setup() {
 Serial.begin(9600);
}
void loop(){
 for( int i = 0; i < MAX_PINS; i++) //цикл переберает значения MAX_PIN попорядку
{
  byte l_pin_state = digitalRead(pin_array[i]); //считать данные и записать в l_pin_state
  if( l_pin_state != val_array[i] ) { // сравнить l_pin_state и val_array[i]
    
    Serial.print(pin_array[i]);
    Serial.print("=");
    Serial.print(l_pin_state);
    byte val_array[i] = l_pin_state // записать текущее значение в val_array
}
}
}

 

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

16 строка, слово byte уберите и в конце точку с запятой не забудьте поставить, т.е.

val_array[i] = l_pin_state;

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

UPD: Да, еще, помните, что начальные значения в val_array у Вас нули, т.е. LOW. Как вариант, можно туда забить любое значение, не совпадающее с HIGH, LOW, тогда сработают сразу все 4 пина. А если на входах нули, то сработает при первом изменении, а при старте программы - нет.

UPD2: Да, еще в строке 15 замените print на ptintln, будет приятнее выводиться.

 

9ser
Offline
Зарегистрирован: 18.11.2012

мало что понял ещё и запутался в конец

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Для начала замените строку 16, на мой вариант, дальше проще

9ser
Offline
Зарегистрирован: 18.11.2012

Заменил и в потр сыпится 11=11=11 и т.д.

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Исходник приложите, только отформатируйте его нормально (Ctrl-T, если не ошибаюсь). Предполагаю, что Вы там не только это изменили, либо некорректно изменили, всё должно работать.

Насколько я понимаю, Вы пока при отладке меняете состояние только пин 1?

Если 15 строку замените print на println, то будет выводить построчно, а не в одну строку. Надеюсь это несложно найти в строке 15 фрагмент print и заменить его на println?

 

9ser
Offline
Зарегистрирован: 18.11.2012

Большой СПС "kisoft" за помощь

Сел, собрался, и получил:

#include <EEPROM.h>
#define MAX_PINS 4 //максимальное количество входоа 4
const byte pin_array[MAX_PINS] = { 3, 4, 5, 6 }; //номера пинов
byte val_array[MAX_PINS] ={ 0, 0, 0, 0 }; //предыдущие значения портов
void setup()
{
 Serial.begin(9600);
}
void loop()
{
 for( int i = 0; i < MAX_PINS; i++) //цикл переберает значения MAX_PIN попорядку
    {
    val_array[i] = EEPROM.read(i);
    byte l_pin_state = digitalRead(pin_array[i]); //считать данные и записать в l_pin_state
      if( l_pin_state != val_array[i] ) // сравнить l_pin_state и val_array[i]
       {
       Serial.print("Pin");
       Serial.print(pin_array[i]);
       Serial.print("=");
       Serial.println(l_pin_state);
       val_array[i] = l_pin_state; // записать текущее значение в val_array
       EEPROM.write(i, l_pin_state);
       delay(20);
       }
    }
}

Ещё сделал сохранение последнего значения порта в EEPROM вдруг напруга пропадёт

А как можно вывести вместо 1 или 0 строку формата "GET /objects/?object=D8&op=m&m=statusChanged&status=%i" для вебсервера на компе.

использую W5100 шилд

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

К сожалению не подскажу, поскольку даже близко не пользовался библиотеками Ethernet.

А строка у Вас почти готова, вместо %i нужно подставить l_pin_state. Вариантов море, отчасти зависят от возможностей бибилиотеки, которая отправляет строку.

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

#define MAX_NET_BUF_LEN 2048
char net_buff[ MAX_NET_BUF_LEN+1 ];
...

sprintf( net_buff, "Ваша строка%i", l_pin_state );
Net.send( net_buff );

Другой вариант, расположить строку в объекте типа String.

Есть и более сложные варианты.

Вот, еще тупой вариант, возможно и самый простой:

char net_buff[] = "Ваша строка "; // Здесь в конце обязательно пробел!!!
...
int16_t l_len = strlen( net_buff ) - 1;
net_buff[ l_len ] = (char)( '0' + l_pin_state );
Net.send( net_buff );

В общем, каждый выбирает себе сам, что ему ближе, а также от ситуации.

Еще, строки большой длины лучше хранить где нибудь в EEPROM или во флешке (PROGMEM), но в этом случае будет несколько сложнее добавить в эту строку состояние пина.