-
Публикации
424 -
Зарегистрирован
-
Посещение
-
Дней в лидерах
234
Сообщения, опубликованные пользователем Kitsum
-
-
@svchekalin Могу на вскидку предложить внести изменения в скетч
1. Заменить строку запроса к SQL серверу
const char QUERY_S[] = "SELECT type FROM adatum.rc522 WHERE uid = %s;";
на
const char QUERY_S[] = "SELECT type, description FROM adatum.rc522 WHERE uid = %s;";
2. Найти и заменить кусок кода
if((row = cur.get_next_row()) != NULL) typeKey = String(row->values[0]); else typeKey = "0"; if(typeKey == F("1") or typeKey == F("2")) {
на
if((row = cur.get_next_row()) != NULL) typeKey = String(row->values[0]); else typeKey = "0"; Serial.println(String(row->values[1])); if(typeKey == F("1") or typeKey == F("2")) {
- 2
-
Данную тему не поднимал только ленивый. По существу все просто и очень подробно описано в первоисточнике https://github.com/esp8266/Arduino
- Скачиваем Arduino IDE с официального сайта
- Запускаем Arduino и открываем окно настроек (Файл -> Настройки)
- В поле "Дополнительные ссылки для Менеджера плат:" указываем адрес
-
http://arduino.esp8266.com/stable/package_esp8266com_index.json
- Открываем менеджер плат (Инструменты -> Список плат -> Менеджер плат) и в качестве фильтра поиска указываем "esp8266". И жмем кнопку установить.
В списке поддерживаемых плат появится ESP8266 в различных вариациях. Все необходимые файлы для поддержки работы с этим микроконтроллером и дополнительные библиотеки с примерами их работы будут закачаны в каталог %APPDATA%\Arduino15\
Скрытый текстСкрытый текстПодключение ESP8266 для загрузки скетча
В сети множество схем для подключения всех разновидностей ESP, от ESP-01 до ESP-12, но нужно понимать, что как бы они не назывались и не выглядели, собраны они на одном микроконтроллере ESP8266EX, следовательно, подключаются они все одинаково за исключением того момента, что если у ESP не выведена та или иная нога (например, ESP-01), то и искать, и подключать её не требуется. Достаточно знать, как подключить ESP-12 и Вы сможете завести и прошить любой тип ESP.
Предлагаю использовать схему подключения с автоматическим сбросом и переводом микроконтроллера в режим загрузки программы. Главное, что понадобится - USB-TTL конвертер с выведенными ногами DTR и RTS. Я использовал конвертер на базе FT232RL.
Если вы собираетесь использовать deepSleep(), то необходимо обязательно подтянуть GPIO-16 к RESET через резистор 470 Ом.
И так, что тут к чему
- RTS - Запрос на передачу (Request to Send)
- DTR - Готовность приемника данных (Data Terminal Ready)
Во время загрузки скетча транзистор T1 откроется и подтянет GPIO-0 к земле, в это время конденсатор C1 перезарядится и тем самым нога RESET кратковременно окажется подтянута к земле, что приведет к перезагрузке микроконтроллера и загрузке программы. Также благодаря конденсатору C1 мы будем перезапускать микроконтроллер каждый раз, при открытии монитора порта (как при использовании обычной Arduino UNO и т.п).
Подведем итоги
Лично мое мнение, что на базе ESP8266 стоит брать только ESP-07 или ESP-12 с переходной платой под отверстия 2,54мм, чтобы можно было установить модуль в макетную плату. Таким образом, за туже цену мы получаем микроконтроллер с максимальным количеством выведенных для нас ног и возможностью быстрого монтажа для экспериментов с разными поделками.
Скрытый текст- 1
-
Данный пост является шпаргалкой из собранных в сети различных материалов связанных с распиновкой (pinout) распространенных микроконтроллеров и плат на их основе.
Микроконтроллеры
ESP8266EX
ESP32 (R1)
Платы
ESP-01
ESP-07
Данная плата практически полностью идентична ESP-12X, разница только в наличие керамической антенны и разъема IPX для подключения внешней антенны.
ESP-12 (E/F)
NodeMCU
ESP32 Board
ESP32-WROOM-32 (DevKitC)
- 3
-
@Oksymoron К сожалению нет клавиатуры используемой в этом проекте, но уверен, что решим эту задачу и без физической реализации.
Начальный скетч мне сильно не нравится, в силу "копипаста", но будем плясать от него. Логика программы очень проста - при нажатии "*" происходит вызов функции checkPassword() в которой вызывается password.evaluate() для проверки введенного кода с клавиатуры. И тут кроется ошибка, по завершению проверки, автор должен был очистить буфер с паролем, но это не происходит. Соответственно введенный пароль остается в памяти и если он был верен, то злоумышленник может открыть замок просто нажав клавишу "*".
За сброс пароля отвечает функция password.reset() реализованная в библиотеки Password.h и нам лишь останется внести изменение в функцию checkPassword(), добавив в её конце очистку буфера.
Скрытый текст//* is to validate password короче чтобы войти //# is to reset password attempt Ну чтоб сделать сброс //внимаение ! если выдает ошибки качаем все библиотеки что указанны ниже ! #include <SPI.h> // скачайте эту библиотеку ! #include <MFRC522.h> // скачайте эту библиотеку ! #include <Password.h> // скачайте эту библиотеку ! #include <Keypad.h> // скачайте эту библиотеку ! #define SS_PIN 10 #define RST_PIN 9 MFRC522 mfrc522(SS_PIN, RST_PIN); // объект MFRC522C / reate MFRC522 instance. unsigned long uidDec, uidDecTemp; int door =8; int key = A5; int green = A1; int red = A2; Password password = Password( "DDCBC97" ); const byte ROWS = 4; // Four rows const byte COLS = 4; // columns // Define the Keymap char keys[ROWS][COLS] = { {'1','2','3','A'}, {'4','5','6','B'}, {'7','8','9','C'}, {'*','0','#','D'} }; byte rowPins[ROWS] = { 0,A0,7,6 };// Connect keypad ROW0, ROW1, ROW2 and ROW3 to these Arduino pins. byte colPins[COLS] = { 5,4,3,2, };// Connect keypad COL0, COL1 and COL2 to these Arduino pins. // Create the Keypad Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS ); void setup() { pinMode (door,OUTPUT); pinMode (key,INPUT); pinMode (green,OUTPUT); pinMode (red,OUTPUT); Serial.begin(9600); SPI.begin(); // инициализация SPI / Init SPI bus. mfrc522.PCD_Init(); // инициализация MFRC522 / Init MFRC522 card. keypad.addEventListener(keypadEvent); //add an event listener for this keypad Serial.println(""); Serial.println(""); Serial.println(" ======================== "); Serial.println(" Waiting for card... "); } void loop() { keypad.getKey(); if (digitalRead(key) == HIGH) { digitalWrite(door,HIGH); Serial.println("Open ==>"); digitalWrite(green, HIGH); delay(100); digitalWrite(red, HIGH); delay(100); digitalWrite(door,LOW); delay(100); digitalWrite(green, LOW); delay(100); digitalWrite(green, HIGH); delay(50); digitalWrite(red, HIGH); delay(50); digitalWrite(door,LOW); delay(50); digitalWrite(green, LOW); digitalWrite(green, HIGH); delay(50); digitalWrite(red, HIGH); delay(50); digitalWrite(door,LOW); delay(50); digitalWrite(green, LOW); delay(50); digitalWrite(green, HIGH); delay(50); digitalWrite(red, HIGH); delay(50); digitalWrite(green, LOW); delay(50); digitalWrite(red,LOW); digitalWrite(door,LOW); } // Поиск новой карточки / Look for new cards. if ( ! mfrc522.PICC_IsNewCardPresent()) { return; } // Выбор карточки / Select one of the cards. if ( ! mfrc522.PICC_ReadCardSerial()) { return; } uidDec = 0; // Выдача серийного номера карточки "UID". for (byte i = 0; i < mfrc522.uid.size; i++) { uidDecTemp = mfrc522.uid.uidByte[i]; uidDec = uidDec*256+uidDecTemp; } Serial.println("Card UID: "); Serial.println(uidDec); if (uidDec == 384627541) // если "UID" номер совпал. { // включим светодиод. digitalWrite(door,HIGH); // Печатаем в Serial монитор . Serial.println("Open ==>"); } // также и с другими номерами карт. else if (uidDec == 959884118) { Serial.println("Hi Sergey"); } else if (uidDec == 695670870) { Serial.println("Hi Peter"); } else // если "UID" номер карты не совпал. { Serial.println(" unknown card"); delay(10000); } Serial.println("====================================="); delay(3000); // пауза 3 секунды. digitalWrite(door,LOW); // и выключим все светодиоды. } //take care of some special events void keypadEvent(KeypadEvent eKey){ switch (keypad.getState()){ case PRESSED: Serial.print("Pressed: "); Serial.println(eKey); digitalWrite(green,HIGH); digitalWrite(red,HIGH); delay(50); digitalWrite(green,LOW); digitalWrite(red,LOW); switch (eKey){ case '*': checkPassword(); break; case '#': password.reset(); break; default: password.append(eKey); } } } void checkPassword(){ if (password.evaluate()){ Serial.println("Success"); digitalWrite(door,HIGH); // открываем дверь digitalWrite(green, HIGH); //включаем выключаем светодиоды =) моргаем короче delay(200); digitalWrite(green,LOW); delay(200); digitalWrite(green, HIGH); delay(200); digitalWrite(green,LOW); delay(200); digitalWrite(green, HIGH); delay(200); digitalWrite(green,LOW); delay(200); digitalWrite(green, HIGH); delay(200); digitalWrite(green,LOW); delay(200); digitalWrite(green, HIGH); delay(200); digitalWrite(green,LOW); delay(200); digitalWrite(green, HIGH); delay(200); digitalWrite(green,LOW); delay(200); digitalWrite(green, HIGH); delay(200); digitalWrite(green,LOW); delay(200); digitalWrite(green, HIGH); delay(200); digitalWrite(green,LOW); delay(200); digitalWrite(green, HIGH); delay(200); digitalWrite(green,LOW); delay(200); digitalWrite(green, HIGH); delay(200); digitalWrite(green,LOW); delay(200); Serial.println("Open ==>"); digitalWrite(door,LOW); }else{ Serial.println("Wrong"); digitalWrite(red, HIGH); // моргаем красным светодиодом (долго, а потомучто нефиг взламывать мой замок ! это затруднит взлом ) delay(400); digitalWrite(red,LOW); delay(400); digitalWrite(red, HIGH); delay(400); digitalWrite(red,LOW); delay(400); digitalWrite(red, HIGH); delay(400); digitalWrite(red,LOW); delay(400); digitalWrite(red, HIGH); delay(400); digitalWrite(red,LOW); delay(400); digitalWrite(red, HIGH); delay(400); digitalWrite(red,LOW); delay(400); } password.reset(); }
-
@Oksymoron на сколько я понял, после ввода пароля необходимо нажать "*" для того, чтобы замок проверил его и если пароль верный, то соответственно нас впустят, но если после этого нажать еще раз "*", то замок откроется повторно. От этого надо избавиться, я так понимаю? И что имеется в виду под сбросом ардуино, сбросить буфер с паролем или перегрузить контроллер?
-
В 18.06.2016 в 02:25, Oksymoron сказал:дай плиз ссылку на библиотеку.
Библиотека уже имеется в самой Arduino IDE, попробуйте скачать среду разработки с официального сайта https://www.arduino.cc/en/Main/Software
-
Всем доброго времени суток, сегодня поговорим о esp8266 и парсинге погоды с интернета. Это довольно интересная альтернатива метеостанции описанной в параллельной теме и думаю, что первый пост стоит посвятить базовой программе - своего рода фундаменту, на базе которого можно производить дальнейшие модификации от подключения дисплея до прикручивания MQTT протокола для системы умного дома.
О самом проекте OpenWeatherMap много написано в сети, но я познакомился с ним недавно, как и с микроконтроллером esp8266 который мы будем программировать в доработанной среде Arduino IDE. Но перед тем как начать, необходимо посетить сайт, с которого мы будем вытаскивать данные об окружающей среде.
И так, OpenWeatherMap предоставляет нам удобный и бесплатный API. На момент публикации статьи (05.2016) мы можем:
- Производить не более 60 запросов в минуту
- Не более 50000 запросов в день
- Два типа прогноза (на 5 и на 16 дней)
- Доступность сервиса 95%
- Интервал обновление данных < 2 часов
Отлично, нас все устраивает. Регистрируемся и в личном кабинете переходим в раздел API Keys. По умолчанию нам уже дадут один ключ, можно воспользоваться им, а можно создать новый и обозвать его более понятным именем. Это довольно актуально, если планируется использовать несколько устройств, да и вообще должен быть порядок везде.
Без данного ключа получить доступ к API невозможно.
Осталось определиться с интересующей нас местностью. API гласит, что есть несколько вариантов:
- По названию города и коду страны
- По уникальному идентификатору города
- По географическим координатам
- По почтовому индексу
Мне показалось удобным использовать географические координаты. При этом сервер сам найдет ближайший населенный пункт, а по сути, ближайшую метеостанцию и предоставит данные с неё.
Данные по необходимым для Вас координатам можно взять прямо с сайта, воспользовавшись любезно предоставленной картой. При выборе населенного пункта долгота и широта будут указаны в описании.
- Москва [ 37.62, 55.75 ]
- Санкт Петербург [ 30.26, 59.89 ]
- Ростов-на-Дону [ 39.71, 47.24 ]
- Севастополь [ 33.53, 44.6 ]
Список всех доступных населенных пунктов можно найти тут http://openweathermap.org/help/city_list.txt
Теперь переходим к самому интересному - скетч. В начале поста я оставил ссылку на ресурс, подробно описывающий все процедуры необходимые, чтобы завести контроллер и использовать Arduino IDE для прошивки. Но я пошел еще более простым путем и приобрел ESP-12E с обвесом под NodeMCU, это позволило прошивать контроллер без нажатия кнопок RESET и FLASH.
Получать данные от сервера можно в двух форматах, XML и JSON. Последний мне показался более предпочтительным и в связи с этим нам понадобится библиотека ArduinoJson
Программа
Скрытый текст#include <ESP8266WiFi.h> #include <ESP8266HTTPClient.h> #include <ArduinoJson.h> const char* ssid = "WiFi AP name"; const char* password = "WiFi AP password"; const String server = "api.openweathermap.org"; const String lat = "51.31"; const String lon = "37.89"; const String appid = "b1f6b0a1ea9e10feb04eb3a2de2ad2b9"; const String url = "http://" + server + "/data/2.5/weather?lat=" + lat + "&lon=" + lon + "&units=metric&appid=" + appid; unsigned long lastConnectionTime = 0; unsigned long postingInterval = 0; String httpData; struct weather_structure { unsigned int id; const char* main; const char* icon; const char* descript; float temp; float pressure; byte humidity; float speed; float deg; }; weather_structure weather; void setup() { Serial.begin(115200); Serial.print("\nConnecting to "); Serial.println(ssid); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println("\nWiFi connected\nIP address: "); Serial.println(WiFi.localIP()); Serial.println(); } void loop() { if (WiFi.status() == WL_CONNECTED) { if (millis() < lastConnectionTime) lastConnectionTime = 0; if (millis() - lastConnectionTime > postingInterval or lastConnectionTime == 0) { if (httpRequest() and parseData()) { Serial.println("\nWeather"); Serial.printf("id: %d\n", weather.id); Serial.printf("main: %s\n", weather.main); Serial.printf("description: %s\n", weather.descript); Serial.printf("icon: %s\n", weather.icon); Serial.printf("temp: %d celsius\n", round(weather.temp)); Serial.printf("humidity: %d %\n", round(weather.humidity)); Serial.printf("pressure: %d hPa or %d mmHg\n", round(weather.pressure), round(weather.pressure * 0.75)); Serial.printf("wind's speed: %d\n", round(weather.speed)); Serial.printf("wind's direction: %d\n", round(weather.deg)); Serial.println(); } } } } bool httpRequest() { HTTPClient client; bool find = false; //client.setTimeout(1000); Serial.print("Connecting "); client.begin(url); int httpCode = client.GET(); if (httpCode > 0) { Serial.printf("successfully, code: %d\n", httpCode); if (httpCode == HTTP_CODE_OK) { httpData = client.getString(); if (httpData.indexOf(F("\"main\":{\"temp\":")) > -1) { lastConnectionTime = millis(); find = true; } else Serial.println("Failed, json string is not found"); } } else Serial.printf("failed, error: %s\n", client.errorToString(httpCode).c_str()); postingInterval = find ? 600L * 1000L : 60L * 1000L; client.end(); return find; } bool parseData() { Serial.println(httpData); DynamicJsonBuffer jsonBuffer; JsonObject& root = jsonBuffer.parseObject(httpData); if (!root.success()) { Serial.println("Json parsing failed!"); return false; } weather.id = root["weather"][0]["id"]; weather.main = root["weather"][0]["main"]; weather.descript = root["weather"][0]["description"]; weather.icon = root["weather"][0]["icon"]; weather.temp = root["main"]["temp"]; weather.humidity = root["main"]["humidity"]; weather.pressure = root["main"]["pressure"]; weather.speed = root["wind"]["speed"]; weather.deg = root["wind"]["deg"]; httpData = ""; return true; }
Все, что нам нужно редактировать, это начальные переменные (ключ указан рабочий, но это все временно)
const char* ssid = "WiFi AP name"; const char* password = "WiFi AP password"; const String server = "api.openweathermap.org"; const String lat = "51.31"; const String lon = "37.89"; const String appid = "b1f6b0a1ea9e10feb04eb3a2de2ad2b9";
По умолчанию программа производит запрос информации с сервера каждые 10 минут, но если что-то пойдет не так и информация не будет получена, то интервал уменьшится до 1 минуты, а при ближайшем удачном подключении вернется обратно.
И так, на данный момент мы собираем:
- weather.id - Идентификатор погодных условий (будет полезен, см. отсылку с weather.icon)
- weather.main - Группа метеорологических параметров
- weather.descript - Описание погодных условий в группе
- weather.icon - Идентификатор иконки (подробнее ознакомиться с ними можно тут)
- weather.temp - Текущая температура в градусах Цельсия
- weather.humidity - Текущая влажность в %
- weather.pressure - Текущее давление (по умолчанию сервер отдает её в hPa, но при умножении на 0,75 мы получаем mmHg)
- weather.speed - Скорость ветра метры/сек.
- weather.deg - Направление ветра в градусах
Выглядит это следующим образом
Connecting to Lenovo S90 ...... WiFi connected IP address: 10.10.1.243 Connecting successfully, code: 200 {"coord":{"lon":37.84,"lat":51.3},"weather":[{"id":802,"main":"Clouds","description":"scattered clouds","icon":"03d"}],"base":"cmc stations","main":{"temp":18.24,"pressure":996.52,"humidity":92,"temp_min":18.24,"temp_max":18.24,"sea_level":1021.77,"grnd_level":996.52},"wind":{"speed":2.01,"deg":30.5008},"clouds":{"all":48},"dt":1464076525,"sys":{"message":0.0025,"country":"RU","sunrise":1464053115,"sunset":1464110798},"id":487928,"name":"Staryy Oskol","cod":200} Weather id: 802 main: Clouds description: scattered clouds icon: 03d temp: 18 celsius humidity: 92 % pressure: 997 hPa or 747 mmHg wind's speed: 2 wind's direction: 31
Как оказалось, ничего сложного в реализации задуманного не было, но местами пришлось повозиться. Думаю, что это будет хорошей отправной точкой для дальнейшего развития проекта.
- 1
-
@sergon63tlt Уверен, что можно.
Допустим, что мы говорим о весьма распространённом OBD2. Думаю, что вполне можно обойтись без CAN SHIELD, если воспользоваться Bluetooth адаптером на базе ELM327 и подключаться к нему с помощью CH-06 или подобного модуля. Это минимизирует затраты и избавит от лишних проводов, да и поможет избежать неприятностей если со стороны контроллера что-то замкнули или т.п
По сути, мы получаем контроллер, подключенный по UART к автомобильной сети и теперь мы сами стали частью системы. Осталось разобраться в протоколе передачи данных. Как гласит теория, бортовой компьютер знает все и вся, а сами данные держит у себя под определенными PID. Отправляем номер PID, а в ответ получаем его значение, которое преобразуем в читаемый вид путем некоторых вычислений. Основную часть можно узнать в wikipedia.
Например, отправим коды:
- 0104 - Расчетная нагрузка на двигатель от 0 до 100%
- 0105 - Температура охлаждающей жидкости двигателя от -40 до 215 градусов Цельсия
- 010A - Давление топлива от 0 до 765 кПа
- 010C - Число оборотов двигателя в минуту
- 010D - Скорость автомобиля
- 010F - Температура воздуха во впускном коллекторе от -40 до 215 градусов Цельсия
- 015E - Удельный расход топлива от 0 до 3212,75 литров в час
Это лишь малая часть информации, взятая из таблицы Mode 01. Большинство значений рассчитываются по формулам, приведенным в этой же таблице.
Кстати, имеется очень интересная библиотека ArduinoOBD и сопутствующие ей статьи:
- http://freematics.com/pages/products/arduino-obd-adapter/
- http://freematics.com/pages/products/arduino-telematics-kit-3/
- 1
-
В 04.05.2016 в 20:15, sergon63tlt сказал:Затея интересная! Жаль у меня приборы на CAN шине работаюта заводить в приборку доп провода не хочется...
Все собирается прямо в приборке и без разборки и пайки не обойтись никак. Но если жалко только ради подсветки браться за инструмент, то можно воспользоваться CAN BUS SHIELD для Arduino или вариантом подешевле в виде MCP2515 и собирать всю информацию об автомобиле.
CAN SHIELD
Скрытый текстhttp://www.seeedstudio.com/wiki/CAN-BUS_Shield
MCP2515
Библиотеки
-
@Alex13 Если мы говорим о подсветке приборной панели, то ничего сложного тут нет. Самое главное - найти в проводке или на самой панели сигнал, отвечающий за обороты двигателя. По сути, импульсы представляют из себя ШИМ, нам нужно посчитать количество импульсов в секунду, это и будут обороты двигателя. Возможно, будет какой-то множитель (2) и при 1000 об/мин будем иметь 2000 импульсов/мин, что соответствует примерно 33 импульса/сек. Отсюда можно плясать с анимацией.
В случае с RGB лентой изменять цвет можно с помощью аналогичного ШИМ сигнала от самого микроконтроллера.
-
На базе светодиодов WS2812 можно баловаться подсветкой приборной панели в зависимости от скорости автомобиля или оборотов двигателя. Аналогичным образом, можно соорудить "ангельские глазки" которые будет иметь базовый цвет белый, а при включении поворота проигрывать желтым цветом анимацию. Но это уже более кропотливая работа в плане эстетики.
Некоторые народные умельцы собирают автомобильные компьютеры, при этом показания считывают с диагностического разъема.
-
-
13 минуты назад, sergon63tlt сказал:Вот теперь " то, что доктор прописал" Если не секрет какие были изменения?
@sergon63tlt отключены лишние подтягивающие резисторы встроенные в микроконтроллер и исправил некоторые косяки которые связанные с внедрением функции lock. Хотя на домашнем компьютере версия замка @Alex13 была уже с этими исправлениями... Это еще раз доказывает, что коллективно проект развивается намного быстрее и качественнее.
- 1
-
1 час назад, sergon63tlt сказал:реле закрытия повело себя как и описано в мониторе СОМ, а вот реле открытия включилось одновременно с реле закрытия и не отключается до поднесения любого из прописанных ключей
Обновил программу из этого поста. Пробуйте залить её как есть, не внося никаких изменений. Посмотрим что будет в Serial. И подтяните пины 8 и 4 земле.
-
Да, изначально скетч писался для электромагнитного замка, но управление нагрузкой это всего лишь пару строчек кода, которые легко переписываются. Львиная доля программы - обработка RFID меток и соответствующая реакция на них.
Для того чтобы было понятно, что мы пытаемся изменить, предлагаю с начало разобраться в том, что происходит при подаче питания с пинами управления реле.
-
В самом начале программы смотрим содержимое первого байта EEPROM микроконтроллера. Там должно быть число, указывающее на количество ключей.
byte keys_count = EEPROM.read();
-
В функции Setup происходит инициализация пинов и на них выставляется высокий логический уровень, опять же все ради Китайских реле, это обесточит их.
// Реле pinMode(PIN_RELAY_1, OUTPUT); digitalWrite(PIN_RELAY_1, HIGH); pinMode(PIN_RELAY_2, OUTPUT); digitalWrite(PIN_RELAY_2, HIGH);
-
Следующий ключевой момент - принятие решения, открыть замок при отсутствие ключей в памяти и сообщить об этом в Serial или же запереть замок и встать на охрану.
if(keys_count > and keys_count < 255) { keysRead(); lock(true); } else { keys_count = ; Serial.println(F("The master key is not in memory. The first presentation to the key will be the master!\n")); lock(false); }
-
Серьезным отличием от электромагнитного замка является наличие функции void lock(bool lock); именно она манипулирует пинами и переключает реле с паузой в 0.4 сек. Заодно фиксирует последнее состояние замка, своего рода программный концевик на двери.
void lock(bool lock) { digitalWrite(lock ? PIN_RELAY_1 : PIN_RELAY_2, LOW); delay(400); digitalWrite(lock ? PIN_RELAY_1 : PIN_RELAY_2, HIGH); lockStat = lock; }
До момента, описанного в п.3 реле находились в покое и не производили никаких манипуляций с соленоидом. Функция lock, кроме возложенных на неё обязанностей, гарантирует нам, что любое реле будет в работе ровно 0.4 секунды, а затем вернется в свое обычное состояние. Следовательно, если ключ будет отсутствовать в памяти микроконтроллера то по условию в п.3 произойдет вызов lock(false); и это приведет к появлению логического нуля на 6 пине на 0.4 секунды, после вернется логическая единица. Если в EEPROM будет находиться хотя бы один ключ, то произойдет вызов lock(true); и аналогичные манипуляции произойдут с пином 7 - замок закроется.
Предлагаю проделать следующее:
- Просмотреть вывод в Serial начиная с момента подачи питания, возможно там будет подсказка.
-
Модернизировать функцию lock и выводить в Serial все, что происходит с реле
void lock(bool lock) { digitalWrite(lock ? PIN_RELAY_1 : PIN_RELAY_2, LOW); Serial.println(lock ? "RELAY CLOSE (PIN 6) ACTIVATED" : "RELAY OPEN (PIN 7) ACTIVATED"); delay(400); digitalWrite(lock ? PIN_RELAY_1 : PIN_RELAY_2, HIGH); Serial.println(lock ? "RELAY CLOSE (PIN 6) DEACTIVATED" : "RELAY OPEN (PIN 7) DEACTIVATED"); lockStat = lock; }
- Можно, но не обязательно, пару фотографий как это выглядит (собрано).
22 часа назад, sergon63tlt сказал:еще заметил одну особенность: при случайном замыкании контактов питания считывателя( +3.3в и общий) питание восстанавливаться, а вот сам считыватель теряется до полного сброса питания.
Это вполне ожидаемое поведение т.к после подачи питания, микроконтроллер MFRC522 скорее всего ожидает запись в соответствующие регистры. Уверен, что этим занимается PCD_Init().
- 1
-
В самом начале программы смотрим содержимое первого байта EEPROM микроконтроллера. Там должно быть число, указывающее на количество ключей.
-
Совершенно верно. Изначально подразумевалось использование Китайских реле в качестве управления нагрузкой, а для их работы необходим инвертированный сигнал - HIGH для закрытия и LOW для открытия реле. Естественно, что если выкинуть реле из схемы, то необходимо произвести изменения в коде, на которые указал @Alex13
-
Кнопка открытия двери и кнопка сброса памяти
// Кнопка сброса памяти pinMode(PIN_RESET,INPUT_PULLUP); key_reset.attach(PIN_RESET); key_reset.interval(5); // Кнопка открытия двери pinMode(PIN_OPEN,INPUT_PULLUP); key_open.attach(PIN_OPEN); key_open.interval(5);
Сейчас силы брошены на другой проект. Позже опять вернусь к замку.
-
Внес изменения во все листинги программы опубликованные в теме. Также внес исправление во все схемы.
- 1
-
Опишите поэтапно, что нужно выполнять и как должен действовать замок. Чем подробнее тем лучше. Какой из вариантов программы Вы использовали? Мы постараемся Вам помочь.
- 1
-
Ошибки будут всегда, все мы люди и нам свойственно ошибаться.
Ищем кусок кода в функции Setup отвечающий за инициализацию пина под кнопку сброса памяти
// Кнопка сброса памяти pinMode(PIN_RESET,INPUT_PULLUP); digitalWrite(PIN_RESET, HIGH); key_reset.attach(PIN_RESET); key_reset.interval(5);
Необходимо удалить строку
digitalWrite(PIN_RESET, HIGH);
Данная строка задействовала внутренний подтягивающий резистор микроконтроллера на 20kOm, но по моей невнимательности, на этом пине он не нужен т.к подтягивает пин к питанию а не к земле. Хотя работает и с ним т.к номинал довольно высок.
Дополнительный резистор на 4.7kOm не нужен т.к на мой взгляд не дает результата, но натолкнул на мысль об удалении вышеупомянутой строки в коде. Номиналом резистора, подтягивающего пин к питанию можно играться т.к он по сути нужен только для подстраховки, все заведется и без него. Думаю, что стоит проверить уровень напряжения, поступающего на 4-ый пин, возможно его недостаточно для формирования логической единицы, хотя эта же линия используется для формирования единицы 2-ом пине (открытие двери).
В любом случае, все это догадки, но одну ошибку в коде исправляют. Нужно больше информации для дальнейшего поиска.
-
Я пересмотрю все листинги программ, может что-то найду. Но все должно работать, по крайней мере работает на нескольких контроллерах в данный момент.
Сама очистка памяти начнется только при длительном удержании кнопки.
-
Тема является своего рода заметкой по мониторингу источников бесперебойного питания фирмы ippon. Заметкой именно потому, что шаблон был написан уже давно, а статья так и не появилась на свет и как обычно бывает, все постепенно начинает забываться, а наработанная информация растворяться в бытие. Дабы не потерять последние крошки выкидываем оставшиеся наработки. Постепенно тема будет переписана и дополнена.
Самым удобным способом мониторинга является, уже знакомый нам по теме с ИБП APC, протокол SNMP. Для подключения устройства в локальную сеть необходимо дополнить его сетевым адаптером UPS Ippon Smart Winner 1500/2000/3000.
Сама карточка поддерживает следующие протоколы:
- HTTP
- HTTPS
- IPv4
- IPv6
- NTP
- SMTP
- SNMP v1
- SNMP v2c
- SNMP v3
- SSH V1
- SSH V2
- SSL
- TCP/IP
- Telnet
На диске, идущем в комплекте, имеется весь необходимый софт и документация. Также, если немного покопаться, можно найти MIB файл со всеми поддерживаемыми OID. На всякий случай мы прикрепим к посту MIB файл на базе которого был создан текущий шаблон.
Перед тем как перейти к шаблону хочу отметить, что он содержит макрос {$SNMP_COMMUNITY} значение которого необходимо изменить на используемое вами Community.
Шаблон позволяет производить мониторинг следующих параметров:
- The measured output real complex power in VA
- Величина отрицательного напряжения аккумуляторной батареи
- Величина положительного напряжения аккумуляторной батареи
- Версия прошивки Network Management Card
- Версия прошивки микропроцессора
- Время оставшееся до истощения заряда батареи
- Время прошедшее с момента перехода на работу от батареи
- Входная мощность
- Входное напряжение
- Входной ток
- Выходная мощность
- Выходная нагрузка ИБП в процентах от номинальной мощности
- Выходное напряжение
- Выходное напряжение
- Выходной ток
- Код неисправности ИБП из таблицы Q6
- Код предупреждения ИБП из таблицы Q6
- Максимальная разрешенная выходная нагрузка
- Максимальная разрешенная рабочая температура
- Модель ИБП
- Название производителя
- Описание напитанной нагрузки (устанавливается администратором)
- Описание устройства (устанавливается администратором)
- Серийный номер
- Статус батареи
- Текущее состояние ИБП
- Температура батареи
- Температура внутри ИБП
- Уровень заряда батареи
- Частота тока на входе
- Частота тока на выходе
Данных параметров должно быть достаточно для создание базовых проверок и триггеров. Мы добавили несколько для основных тревог.
И пару базовых графиков.
Данный шаблон вполне подойдет для создания на его основе Ваших решений. Мы будем рады увидеть Ваши наработки или помочь Вам в реализации, каких либо идей по мониторингу этих источников бесперебойного питания.
- 2
-
Подключение RFID ридера RC522 к Arduino Mega 2560
С программой все практически без изменений. Используем всю туже библиотеку MFRC522.h, и только изменим в настройках два пина - RST и SS.
#include <SPI.h> #include <MFRC522.h> #define RST_PIN 5 #define SS_PIN 53 MFRC522 mfrc522(SS_PIN, RST_PIN);
-
36 минут назад, Alex13 сказал:Но ещё вопросик, можно сделать так, чтоб пин A3 активировался, только когда замок закрыт?
// Автоматическое отключение сигнализации if(alarmTimer != 0) { if(millis()/1000 - alarmTimer > 60) { alarmTimer = 0; digitalWrite(PIN_ALARM_1M, invert ? HIGH : LOW); Serial.println(F("Automatic shutdown of the first signaling channel.\n")); } } else { if(digitalRead(PIN_ALARM_FORCED) and lockStat) { alarmTimer = millis()/1000; digitalWrite(PIN_ALARM_1M, invert ? LOW : HIGH); digitalWrite(PIN_ALARM_LONG, invert ? LOW : HIGH); } }
Видеонаблюдение на основе пакета Motion
в Linux
Опубликовано: · Жалоба на ответ
Всем доброго времени суток.
Как всегда начнем с предыстории. Необходимо было реализовать видеонаблюдение за помещением, естественно с нулевым бюджетом, а как иначе. В наличие имелся сервер с Linux на борту и домашняя usb web камера. За основу был взят программный пакет Motion. В принципе ничего сложного в настройке нет, правим пару строк в конфиге и вуаля. Писать было ни о чем.
На днях обновил Ubuntu до версии 16.04.1 LTS и заодно, решено было обновить часть пакетов, в том числе Motion, и переделать систему видеонаблюдения. От usb камеры давно было решено отказаться, и ей на смену пришла дешевая IP камера (поддерживающая MJPEG поток) купленная на распродаже.
Отразим все на "бумаге"
Имеется:
Требуется:
В Ubuntu установка пакетов проста до безобразия
По завершении установки переходим в каталог с файлом конфигурации
Сразу разберемся с порядком действий т.к понимая, что сейчас будем делать, мы сможем настроить эту программу вне зависимости от её версии и версии операционной системы на которой она установлена.
Сам Motion может работать одновременно с несколькими потоками (камерами для обывателя), неважно будь то IP камеры, USB камеры или иные устройства захвата видео. Да хоть все вперемешку. Самое главное, что если мы используем IP камеры, то они должны поддерживать MJPEG поток. Никакого RTSP (Real Time Streaming Protocol) Motion не поддерживает.
Файл конфигурации motion.conf представляет из себя набор основных настроек программы и настройки для первого потока. Все последующие потоки можно конфигурировать в файлах thread1.conf, thread2.conf ... thread9.conf (по умолчанию они отсутствуют) и подключать в конце файла motion.conf
Лично я предпочитаю основные настройки и настройки по умолчанию хранить в основном файле конфигурации, а настройки самих камер вынести во внешние файлы thread, по одному файлу на каждую камеру. Таким образом, не будет никакой путаницы если например камера №2 выйдет из строя и её понадобится заменить на не типичную камеру.
Основные настройки представлены в двух секциях
Тут нас интересует только запуск программы в фоновом режиме, остальные настройки можно оставить без изменения.
Далее идет секция настройки первого потока
Закомментируем все настройки в этой секции, в этом файле они нам не нужны.
Далее большинство настроек мы оставим без изменения, а поправим только некоторые. Эти настройки будут общие для всех потоков.
Отключаем создание снимков при обнаружении движения. Можно указать один из режимов (first, best, center) и тогда мы будем получать по одному снимку на одно видео. Это может пригодиться в том случае, если вы собираетесь организовывать WEB доступ к архиву видеозаписей.
Отключаем стриминг по умолчанию
Отключаем встроенный web сервер
В самом конце основного файла конфигурации motion.conf имеется секция для подключения дополнительных потоков. По умолчанию файл motion.conf соответствовал файлу thread0.conf, но мы это доблестно исправили выше. Теперь нам необходимо включить в файл конфигурации файлы с настройками для работы с нашими камерами. Мы рассмотрим на примере конфигурации одной камеры, раскомментируем thread1.conf
Создадим файл thread1.conf
Первым делом вам необходимо узнать:
Укажем настройки для доступа к видео потоку. В моем случае камеры находятся в отдельной физической сети, и доступ к потоку по логину и паролю не требуется (только для доступа к настройкам камер).
# Сетевой адрес для захвата изображения с камеры (mjpeg поток) netcam_url http://10.10.1.101/mjpeg.cgi # Логин и пароль к видео потоку (only if required). Default: not defined ; netcam_userpass admin:password
Укажем подпись для камеры, это поможет быстро идентификации её местоположение (можно использовать символ перевода каретки)
Укажем путь до места хранения видео фрагментов (лучше создать каталог заранее)
Включаем детектор движения
У меня камера стоит под потолком, рядом со стеной с большим количеством окон. Ну и естественно окна смотрят на солнечную сторону, а это значит, что открывается прекрасный вид на быстро плывущие облака отбрасывающие тень на здание, а во время летней грозы помещение может освещаться завораживающими вспышка молний. И это все можно будет посмотреть на видео, если не добавить следующие параметры. Можно поэкспериментировать и добиться приемлемого результата для вас
Добавляем мертвую зону. Она позволит не создавать кучу мусора в папке с видео
# Количество секунд (мертвая зона) после окончания движения, в течении которых отключен детектор event_gap 10
Для наглядности можно добавить рамку вокруг движущегося объекта. Также рекомендую включить эти параметры на время, пока проходит настройка и обкатка системы
Также для настройки я использую отображение количество изменившихся пикселей. Это очень помогает отрегулировать уровень тревоги т.к камера может быть на разном ударении от наблюдаемой зоны и следовательно чем дальше, тем меньше пикселей будет занимать движущийся вдали объект
Включаем возможность стримить с сервера все происходящее на данной камере
# Настройки потока вещания (порт\качество\частота кадров\доступ только с 172.0.0.1\ограничение потока) stream_port 8081 stream_quality 70 stream_maxrate 20 stream_localhost off stream_limit 0
Можно (и нужно, если установлен stream_localhost off) требовать авторизацию при доступе к потоку с этой камеры из вне
В принципе этого уже достаточно для организации работы системы и на этом этапе можно сохранить файл. Но в моем случае требуется организовать внешнюю систему оповещения. Благо Motion умеет вызывать внешние программы и передавать им различные параметры.
Так как первая камера у меня захватывает не все помещение, а только ту его часть, где находится входная дверь, то мне куда более важно быть в курсе, когда движение началось именно в той части комнаты. И соблюдать режим тишины, когда объект движется от камеры.
При вызове внешнего скрипта ему можно передать следующие параметры
Добавим строку вызова внешнего исполняемого файла с передачей ему параметрами - номер камеры и координаты центра начала движения
Содержимое zone_alarm.sh
В данном случае происходит звуковое оповещение на самом сервере с помощью утилиты beep, по умолчанию её может и не быть
Также можно сигнализировать об обнаружении движения на удаленную станцию или на мобильное устройство. Очень актуально если камера наблюдает за помещением, в котором не бывает и не должно бывать людей. Например, склад.
Необходимо разрешить Motion работать в режиме демона, для этого правим файл /etc/default/motion
Проверяем работу
Что мы имеем на выходе
Все прекрасно работает, но остается вопрос переполнения жесткого диска. Чтобы этот счастливый момент никогда не настал, стоит автоматизировать удаление устаревших видеозаписей. В этом нам поможет планировщик CRON.
И добавим запись, которая будет выполняться ежедневно в 23:30 и искать файлы формата .avi в указанном нами каталоге и если найденный файл существует более 14 суток, то он удаляется. Естественно если камера стоит в проходном месте, то стоит уменьшить время жизни видео.
На этом настройка завершена.
PS: в файле motion.conf можно найти еще очень много интересных параметров!