Перейти к публикации
iT4iT.CLUB

Slava

Пользователи
  • Публикации

    6
  • Зарегистрирован

  • Посещение

Сообщения, опубликованные пользователем Slava


  1. В 14.11.2017 в 15:09, Kitsum сказал:

     

    Спасибо. вродебы пока не нашел больше багов.

    И на основе домофонна появилась идея улучшить кофе апарат в офисе)

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

    вродебы все просто должно выйти. нооо уже голова на взрыв. огромная куча вариантов - не работает(

    помогите плз. может опытным глазом тыкнете на ошибку.

     

    Скрытый текст
    
    
    // Необходимые библиотеки
    #include <avr/wdt.h>          
    #include <SPI.h>
    #include <MFRC522.h>
    #include <Bounce2.h>
    #include <Ethernet.h>
    #include <MySQL_Connection.h>
    #include <MySQL_Cursor.h>
    
    // Необходимые пины
    #define PIN_SS         9  // RFID
    #define PIN_RST        8  // RFID
    
    #define PIN_RELAY      7  // RELAY
    #define PIN_MODE       6  // MODE
    #define PIN_TONE       3  // TONE
    #define PIN_OPEN       2  // OPEN
    
    MFRC522 mfrc522(PIN_SS, PIN_RST);
    
    byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
    IPAddress server(91, 206, 201, 35);  // IP адрес MySQL сервера
    char user[] = "prescent_crm1";               // MySQL username
    char password[] = "uae6tkrc";        // MySQL password
    
    const char QUERY_S[] ="Select Sum(Sum*MoneyWay) From prescent_crm1.CoffeMoneys where User_id=(SELECT User_id FROM prescent_crm1.RFIDKeys WHERE uid = '%s' and IsActive=1 Limit 1);";
    const char QUERY_I[] = "INSERT INTO prescent_crm1.CoffeMoneys (Sum, MoneyWay, User_id) VALUES (3,-1,(SELECT User_id FROM prescent_crm1.RFIDKeys WHERE uid = '%s' and IsActive=1 Limit 1));";
    const char QUERY_IT[] = "INSERT INTO prescent_crm1.CoffeMoneys (Sum, MoneyWay, User_id) VALUES (3,-1,1);";
    char query[128];
    
    EthernetClient client;
    MySQL_Connection conn((Client *)&client);
    MySQL_Cursor cur = MySQL_Cursor(&conn);
    
    //
    String key, lastKey;
    String typeKey;
    char toQuery[12];
    unsigned long lastKeyTimer  = 0;
    
    // Переменные необходимые для режима программирования
    byte modeProgTime           = 5;     // Количество секунд удержания мастер ключа для входа\выхода в\из режим\а программирования
    bool mode                   = false; // НЕ МЕНЯТЬ!
    bool modeLock               = true; // НЕ МЕНЯТЬ!
    byte modeClean              = 0;     // НЕ МЕНЯТЬ!
    unsigned long modeTimer     = 0;     // НЕ МЕНЯТЬ!
    
    // Управление замком
    unsigned long openTimer = 0;
    
    // Защита кнопок от дребезга
    Bounce key_open  = Bounce();
    /*
      Функция звукового оповещения.
      Принимает параметры: количество звуковых сигналов, частота в герцах, продолжительность звука, пауза в миллисекундах (не обязательно)
    */
    void squeaker(byte count, unsigned int Hz, unsigned int duration, unsigned int sleep = 0) 
    {
      for(int i=0; i<count; i++) {
        tone(PIN_TONE, Hz, duration);
        if(sleep > 0) delay(sleep);
      }
    }
    /*
      Функция читает EEPROM и составляет список активных ключей
      Первый байт в памяти содержит количество ключей
      UID ключа содержит 4 байта
      Общая память 1 + количество ключей * 4
      Максимум можно записать 255 ключей
    */
    void setup() {
      // Настраиваем сторожевой таймер
      wdt_disable();
      delay(8000);
      wdt_enable(WDTO_8S);
    
      // Инициализация используемых пинов
      // Реле
      pinMode(PIN_RELAY, OUTPUT);
      digitalWrite(PIN_RELAY, HIGH);
       
      // Кнопка открытия двери
      pinMode(PIN_OPEN,INPUT_PULLUP);
      key_open.attach(PIN_OPEN);
      key_open.interval(5);   
    
      // Перемычка выбора режима работы (0 - автоматическое закрытие двери, 1 - закрытие двери по ключу)
      pinMode(PIN_MODE, INPUT);
      digitalWrite(PIN_MODE, HIGH);
    
      // Инициализация консоли
      Serial.begin(115200);
      while (!Serial);
      Serial.println(F("Start"));
    
      // Инициализация ридера
      SPI.begin();
      mfrc522.PCD_Init();
    
      IPAddress ip(192, 168, 0, 222);
      IPAddress subnet(255, 255, 255, 0);  
      IPAddress gateway(192, 168, 0, 1);
      IPAddress dns(192, 168, 0, 2);
    
    Ethernet.begin(mac, ip, dns, gateway, subnet);
      Serial.print(F("IP: "));
      Serial.println(Ethernet.localIP());
      Serial.println();
      
      // Приглашаем в гости
      Serial.println(F("iT4iT CLUB (C) 2015\nhttps://it4it.club\n"));      
    }
    
    void loop() {
      // Сбрасываем сторожевой таймер микроконтроллера
      wdt_reset();
    
      if(openTimer > millis()+10000) openTimer = 0;
      if(lastKeyTimer > millis()+10000) lastKeyTimer = 0;
    
      // Изменение режима работы закрытия
      //modeLock = !digitalRead(PIN_MODE);
    
      // Открытие двери с кнопки
      key_open.update();
    
      // Если ключ отсутствует или не читается, не выполняем дальнейший код
      if(!mfrc522.PICC_IsNewCardPresent()) {
        // Очистка таймера входа в режим программирования, в случае если ридер свободен
        if(modeTimer != 0) {
          if(++modeClean > 5) modeTimer = modeClean = 0;
        }
        // Таймер для контроля времени хранения последнего ключа в памяти
        if(lastKeyTimer != 0) {
          if((millis()-lastKeyTimer) > 100) {
            lastKey = "";
            lastKeyTimer = 0;
          }
        }
        return;
      }
      if(!mfrc522.PICC_ReadCardSerial()) return;
      // Останавливаем режим очистки
      modeClean = 0;
    
      // Читаем ключ
      for(byte i=0; i<4; i++) key += mfrc522.uid.uidByte[i];
      // Один ключ = Один запрос к MySQL серверу. Не флудим.
      if(key != lastKey) 
      {
        
      
          
          if(!conn.connect(server, 3306, user, password)) {
            squeaker(5, 1000, 200, 200);
           return;
          }
    
        key.toCharArray(toQuery, key.length()+1);
        Serial.println(F("key code -"));
        Serial.println(toQuery);
        sprintf(query, QUERY_S, toQuery);
        cur.execute(query);
    
        column_names *cols = cur.get_columns();
    
        for (int f = 0; f < cols->num_fields; f++) {
        Serial.print(cols->fields[f]->name);
        if (f < cols->num_fields-1) {
          Serial.print(',');
        }
      }
      
        row_values *row = NULL;
        Serial.println("KEY: " + key);
        row = cur.get_next_row();
        if(row != NULL)
        {
          if(row->values[0]!=NULL)
          {
          typeKey = String(row->values[0]);
          }
          else
          {
            typeKey = String("0");
          }
        }
        else
        {
          typeKey = "0";
        //}
        }
        Serial.println("FROMDB: " + typeKey);
        if((typeKey.toFloat()) > 3) 
        {
          //if(!mode) 
          {
            Serial.println(F("access allow"));
            // Доступ разрешен
            if(modeLock) 
            {
              openTimer = millis()/1000;
              digitalWrite(PIN_RELAY, LOW); 
    
              Serial.println(F("add key in MySQL"));
           // sprintf(query, QUERY_IT, toQuery);
            //cur.execute(QUERY_IT);
    
    cur.close();
        conn.close();
        
    if(!conn.connect(server, 3306, user, password)) {
            squeaker(5, 1000, 200, 200);
           return;
          }
          
            MySQL_Cursor cur_mem = MySQL_Cursor(&conn);
    
      cur_mem.execute(QUERY_IT);
      cur_mem.close();
      
            }
            else digitalWrite(PIN_RELAY, !digitalRead(PIN_RELAY));
            squeaker(2, 2200, 200, 200);
    
    
            
          }
        }
        else {
          //if(!mode) 
          {
            Serial.println(F("access dany"));
            squeaker(1, 500, 1000);
          }
        }
    
        lastKey = key;
        cur.close();
        conn.close();
      }
        lastKey = key;
      lastKeyTimer = millis();
      key = "";
    }

     

     


  2. 2 часа назад, Kitsum сказал:

     

    Что по поводу кнопки. Я буду рассуждать в контексте оригинальной программы.

    Реализация механизма открытия с кнопки очень проста и работает независимо от сети.

    
    // Открытие двери с кнопки
    key_open.update();
    if(!key_open.read() and openTimer == 0 and !mode) {
      if(modeLock or (!modeLock and digitalRead(PIN_RELAY))) {
        openTimer = millis()/1000;
        digitalWrite(PIN_RELAY, LOW);
        Serial.println(F("The door opened from the inside\n"));
        squeaker(5, 3200, 100, 300);
      }
      delay(2000);
    }

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

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

    1. В каком режиме работает закрытие замка (авто/ручной)?
    2. Используете ли Вы сторожевой таймер?
    3. Внесите следующие изменение в работу кнопки
        Показать содержимое
      
      
      // Открытие двери с кнопки
      key_open.update();
      if(!key_open.read() and openTimer == 0 and !mode) {
        Serial.println(F("Key down")); // Ожидаем увидеть этот вывод в Serial
        if(modeLock or (!modeLock and digitalRead(PIN_RELAY))) {
          openTimer = millis()/1000;
          digitalWrite(PIN_RELAY, LOW);
          Serial.println(F("The door opened from the inside\n")); // И этот тоже
          squeaker(5, 3200, 100, 300);
        }
        delay(2000);
      }
    4. Воссоздайте ситуацию и опишите полный порядок Ваших действий.
    5. Что прилетает в Serial монитор?

     

     

    1) - автоматическое закрытие серез время

    2) да. скетч в этой части не изменылся. стоит ( wdt_disable();
      delay(8000);
      wdt_enable(WDTO_8S);)

    3) внес но попрежнему без ethernet не открывает.

    4) вариант1 - подключаю езернет, подключаю юсб. - все работает отлично. 

    вариант2 - подключаю езернет, подключаю юсб (питание) - все отлично, вытаскиваю езернет - кнопка работает на карточки не реагирует.

    вариант3 - НЕ подключаю езернет, подключаю юсб (питание) - карточка не работает, КНОПКА также не работает.

    5) ничего. молчит. просто пустой

    в скетч была дописана функция открытия без ключа. но также не хочет работать( может что-т не так?)

    Скрытый текст

     

    
    // Необходимые библиотеки
    #include <avr/wdt.h>          
    #include <SPI.h>
    #include <MFRC522.h>
    #include <Bounce2.h>
    #include <Ethernet.h>
    #include <MySQL_Connection.h>
    #include <MySQL_Cursor.h>
    
    // Необходимые пины
    #define PIN_SS         9  // RFID
    #define PIN_RST        8  // RFID
    
    #define PIN_RELAY      7  // RELAY
    #define PIN_MODE       6  // MODE
    #define PIN_TONE       3  // TONE
    #define PIN_OPEN       2  // OPEN
    
    MFRC522 mfrc522(PIN_SS, PIN_RST);
    
    byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
    IPAddress server(11, 226, 221, 35);  // IP адрес MySQL сервера
    char user[] = "p111";               // MySQL username
    char password[] = "2222";        // MySQL password
    
    const char QUERY_S[] = "SELECT type FROM prescent_crm1.rfid WHERE uid = %s;";
    const char QUERY_I[] = "INSERT INTO prescent_crm1.rfid (uid) VALUES ('%s');";
    char query[128];
    
    EthernetClient client;
    MySQL_Connection conn((Client *)&client);
    MySQL_Cursor cur = MySQL_Cursor(&conn);
    
    //
    String key, lastKey;
    String typeKey;
    char toQuery[12];
    unsigned long lastKeyTimer  = 0;
    
    // Переменные необходимые для режима программирования
    byte modeProgTime           = 5;     // Количество секунд удержания мастер ключа для входа\выхода в\из режим\а программирования
    bool mode                   = false; // НЕ МЕНЯТЬ!
    bool modeLock               = false; // НЕ МЕНЯТЬ!
    byte modeClean              = 0;     // НЕ МЕНЯТЬ!
    unsigned long modeTimer     = 0;     // НЕ МЕНЯТЬ!
    
    // Управление замком
    unsigned long openTimer = 0;
    
    // Защита кнопок от дребезга
    Bounce key_open  = Bounce();
    /*
      Функция звукового оповещения.
      Принимает параметры: количество звуковых сигналов, частота в герцах, продолжительность звука, пауза в миллисекундах (не обязательно)
    */
    void squeaker(byte count, unsigned int Hz, unsigned int duration, unsigned int sleep = 0) 
    {
      for(int i=0; i<count; i++) {
        tone(PIN_TONE, Hz, duration);
        if(sleep > 0) delay(sleep);
      }
    }
    /*
      Функция читает EEPROM и составляет список активных ключей
      Первый байт в памяти содержит количество ключей
      UID ключа содержит 4 байта
      Общая память 1 + количество ключей * 4
      Максимум можно записать 255 ключей
    */
    void setup() {
      // Настраиваем сторожевой таймер
      wdt_disable();
      delay(8000);
      wdt_enable(WDTO_8S);
    
      // Инициализация используемых пинов
      // Реле
      pinMode(PIN_RELAY, OUTPUT);
      digitalWrite(PIN_RELAY, HIGH);
       
      // Кнопка открытия двери
      pinMode(PIN_OPEN,INPUT_PULLUP);
      key_open.attach(PIN_OPEN);
      key_open.interval(5);   
    
      // Перемычка выбора режима работы (0 - автоматическое закрытие двери, 1 - закрытие двери по ключу)
      pinMode(PIN_MODE, INPUT);
      digitalWrite(PIN_MODE, HIGH);
    
      // Инициализация консоли
      Serial.begin(115200);
      while (!Serial);
    
      // Инициализация ридера
      SPI.begin();
      mfrc522.PCD_Init();
    
      Ethernet.begin(mac);
      Serial.print(F("IP: "));
      Serial.println(Ethernet.localIP());
      Serial.println();
      
      // Приглашаем в гости
      Serial.println(F("iT4iT CLUB (C) 2015\nhttps://it4it.club\n"));      
    }
    
    void loop() {
      // Сбрасываем сторожевой таймер микроконтроллера
      wdt_reset();
    
      if(openTimer > millis()+10000) openTimer = 0;
      if(lastKeyTimer > millis()+10000) lastKeyTimer = 0;
    
      // Изменение режима работы закрытия
      modeLock = !digitalRead(PIN_MODE);
    
      // Открытие двери с кнопки
      key_open.update();
      if(!key_open.read() and openTimer == 0 and !mode) {
        if(modeLock or (!modeLock and digitalRead(PIN_RELAY))) {
          openTimer = millis()/1000;
          digitalWrite(PIN_RELAY, LOW);
          Serial.println(F("The door opened from the inside\n"));
          squeaker(5, 3200, 100, 300);
        }
        delay(2000);
      }
      
      // Автоматическое закрытие двери
      if(openTimer != 0) {
        if(millis()/1000 - openTimer > 5) {
          openTimer = 0;
          if(modeLock) {
            digitalWrite(PIN_RELAY, HIGH);
            Serial.println(F("* closed lock"));
          }
          else {
            if(!digitalRead(PIN_RELAY)) digitalWrite(PIN_RELAY, HIGH);
          }
        }
      }
      
      // Если ключ отсутствует или не читается, не выполняем дальнейший код
      if(!mfrc522.PICC_IsNewCardPresent()) {
        // Очистка таймера входа в режим программирования, в случае если ридер свободен
        if(modeTimer != 0) {
          if(++modeClean > 5) modeTimer = modeClean = 0;
        }
        // Таймер для контроля времени хранения последнего ключа в памяти
        if(lastKeyTimer != 0) {
          if((millis()-lastKeyTimer) > 100) {
            lastKey = "";
            lastKeyTimer = 0;
          }
        }
        return;
      }
      if(!mfrc522.PICC_ReadCardSerial()) return;
      // Останавливаем режим очистки
      modeClean = 0;
    
      // Читаем ключ
      for(byte i=0; i<4; i++) key += mfrc522.uid.uidByte[i];
      // Один ключ = Один запрос к MySQL серверу. Не флудим.
      if(key != lastKey) {
        
        if(!conn.connected())
        {
    
          //without Internet
          if(key=="7719892131" || key=="2145683647" || key=="8624152187")
          {
            if(!mode) {
              Serial.println(F("access allow"));
              // Доступ разрешен
              if(modeLock) {
                openTimer = millis()/1000;
                digitalWrite(PIN_RELAY, LOW); 
                return;
              }
              else digitalWrite(PIN_RELAY, !digitalRead(PIN_RELAY));
              squeaker(2, 2200, 200, 200);
              return;
            }
          }
          
          if(!conn.connect(server, 3306, user, password)) {
            squeaker(5, 1000, 200, 200);
            return;
          }
        }
    
        key.toCharArray(toQuery, key.length()+1);
        Serial.println(F("key code -"));
        Serial.println(toQuery);
        sprintf(query, QUERY_S, toQuery);
        cur.execute(query);
    
        column_names *cols = cur.get_columns();
        row_values *row = NULL;
        Serial.println("KEY: " + key);
        if((row = cur.get_next_row()) != NULL) typeKey = String(row->values[0]); else typeKey = "0";
        if(typeKey == F("1") or typeKey == F("2")) {
          if(!mode) {
            Serial.println(F("access allow"));
            // Доступ разрешен
            if(modeLock) {
              openTimer = millis()/1000;
              digitalWrite(PIN_RELAY, LOW); 
            }
            else digitalWrite(PIN_RELAY, !digitalRead(PIN_RELAY));
            squeaker(2, 2200, 200, 200);
          }
          else {
            if(typeKey != F("1")) {
              Serial.println(F("error: key elrady exists in eeprom"));
              squeaker(2, 500, 300);
            }
          }
        }
        else {
          if(!mode) {
            Serial.println(F("access dany"));
            squeaker(1, 500, 1000);
          }
          else {
            Serial.println(F("add key in MySQL"));
            sprintf(query, QUERY_I, toQuery);
            cur.execute(query);
            squeaker(2, 2200, 200, 200);
          }
        }
    
        lastKey = key;
        cur.close();
        conn.close();
      }
      else {
        if(typeKey == F("1")) {
          if(modeTimer == 0) modeTimer = millis()/1000;
          else {
            if(millis()/1000 - modeTimer > modeProgTime and modeTimer != 0) {
              modeTimer = openTimer = 0;
              if((mode = !mode) == true) {
                // Вход в режим программирования
                digitalWrite(PIN_RELAY, LOW);
                Serial.println(F("MASTER PROGRAMMING MODE ON"));
                squeaker(4, 1200, 200, 200);
              }
              else {
                // Выход из режима программирования
                digitalWrite(PIN_RELAY, HIGH);
                Serial.println(F("MASTER PROGRAMMING MODE OFF"));
                squeaker(4, 2200, 200, 200);
              }
              delay(2000);
            }
          }
        }
      }
      
      lastKeyTimer = millis();
      key = "";
    }

    в часности:

    Скрытый текст
    
       //without Internet
          if(key=="7719892131" || key=="2145683647" || key=="8624152187")
          {
            if(!mode) {
              Serial.println(F("access allow"));
              // Доступ разрешен
              if(modeLock) {
                openTimer = millis()/1000;
                digitalWrite(PIN_RELAY, LOW); 
                return;
              }
              else digitalWrite(PIN_RELAY, !digitalRead(PIN_RELAY));
              squeaker(2, 2200, 200, 200);
              return;
            }
          }
          
          if(!conn.connect(server, 3306, user, password)) {
            squeaker(5, 1000, 200, 200);
            return;
          }
        }

     

     

     

     

    но также не помогло(


  3. нет ну то что не будет работать с базой данных без езернета - понятно.

    но может можно как-то добавить чтобы в случае сбоя роутера можно было открыть кнопкой и хотябы парочкой карт?

    а  то выходит систама "в заперти"


  4.  

    14 минуты назад, svchekalin сказал:

    На выход кнопка работает и потом зачем интернет ?

    попробуйте отключить ethernet  и перегрузить ардуино (выключить и включить)

    пока ардуино не получит айпи адреса - ничего не будет


  5. 1 минуту назад, svchekalin сказал:

    На выход кнопка работает и потом зачем интернет ?

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

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

     

    когда подключен ethernet кабель - все ок работает. Когда отключаю - не работает даже кнопка на выход


  6. В 26.06.2017 в 12:02, Kitsum сказал:

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

    Добавьте в таблицу два поля time_start и time_end с типом int, в них мы будет хранить часы (в формате 24) начала и конца рабочего времени. Желательно выставить этим полям значения по умолчанию, скажет 7 и 18 соответственно. Далее в программе микроконтроллера необходимо реализовать дополнительный запрос.

    
    const char QUERY_ST[] = "SELECT type FROM test.rc522 WHERE uid = %s and time_start <= (select HOUR(NOW())) and time_end > (select HOUR(NOW()));";

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

    Находим

    
    sprintf(query, QUERY_S, toQuery);

    Меняем на

    
    sprintf(query, (mode? QUERY_S : QUERY_ST), toQuery);

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

    PS: на практике не проверял, но Вам должно хватить этой информации для дальнейшей реализации.

    Супер разработка. Но подскажите пожалуйста такую вещ. когда пропадает интернет. что тогда делать?

    перемычка в режиме: открыл картой, прошло время двери закрылись сами

    но как только пропадает интернет - не возможно зайти по карте и не реагирует кнопка в нутри.

    получается "Замуровали")

     

    Может можно добавить список ключей которыми можно откыть двери без интернета + чтобы кнопка работала без интернета (а то и выйти нельзя)

×
×
  • Создать...