Опубликовано: 14.08.2017 20:32
Автор: genaonyx
Всем привет, рано или поздно каждый Ардуинщик сталкивается с тем, что его просят сделать тот или иной проект естественно не безвозмездно. И все бы было хорошо, но находиться люди, которых хлебом не корми да дай кого-нибудь развести на деньги и просто кинуть человека, который вложил свое время и знания в его реализацию. Ситуация усугубляется если заказчик и исполнитель находятся в разных городах / странах. Тут надо иметь дело с почтой и, как правило, основное условие заказчика сначала товар потом деньги. И я всецело с ними согласен, мало кто захочет платить тому, кто может и не сделать задуманное и просто взять деньги и пропасть. И тут естественно надо себя как то защитить. Одой из таких защит является счетчик включения / выключения или счетчик запусков (Кому как удобней, так и называйте). Конечно, даже с ним вы можете пролететь на деньги, а именно на стоимость Arduino и комплектующих модулей использующихся в проекте, но зато сам проект станет неработоспособным в случае обмана ну или заставит злоумышленника передумать и все же оплатить заработанные деньги.
Принцип работы счетчика довольно прост, каждый раз, когда Arduino запускается, в обработчике setup() мы производим чтение двух переменных из энергонезависимой памяти Arduino (EEPROM). Одна из переменных используется для определения, работает ли наш счетчик или он уже был деактивирован вводом пароля. Вторая же переменная будет тем самым счетчиком, увеличивающимся каждый раз при включении Arduino, то есть мы этот счетчик прочтем, увеличим на единицу и запишем обратно в энергонезависимую память. В основной же секции loop() мы будем определять, работает ли счетчик, достиг ли он лимита и собственно, если все хорошо выполнять ваш скетч, иначе ожидать ввода пароля. В данной статье я опишу ввод пароля путем передачи его посредством серийного монитора, то есть через USB, вы же можете изменить скетч и добавить ввод пароля, например нажатием некой комбинации кнопок, если таковые есть в вашем проекте. Ну а теперь приступим.
#include "EEPROM.h" // Подключаем библиотеку EEPROM.
#define scAddress 0 // Адрес, где хранятся показания счетчика.
byte scValue = 0; // Переменная с показаниями счетчика.
void setup()
{
scValue = EEPROM.read(scAddress); // Чтение данных счетчика из EEPROM.
scValue++; // Увеличиваем счетчик на единицу.
EEPROM.write(scAddress, scValue); // Записываем данные счетчика обратно в EEPROM.
Serial.begin(9600); // Выводим в монитор порта для проверки.
Serial.println(scValue);
}
void loop()
{
//...
}
Теперь вкратце, что мы сделали.
Теперь давайте добавим ограничение на количество запусков.
#include "EEPROM.h" // Подключаем библиотеку EEPROM.
#define scAddress 1 // Адрес, где хранятся показания счетчика.
#define scCount 5 // Количество разрешенных запусков.
#define ledPin 13 // Порт Ардуино со светодиодом.
byte scValue = 0; // Переменная с показаниями счетчика.
void setup()
{
scValue = EEPROM.read(scAddress); // Чтение данных счетчика из EEPROM.
if (scValue == 255) scValue = 0; // Сбрасываем счетчик в 0.
if (scValue <= scCount)
{
scValue++; // Увеличиваем счетчик на единицу.
EEPROM.write(scAddress, scValue); // Записываем данные счетчика обратно в EEPROM.
}
pinMode(ledPin, OUTPUT); // Настраиваем порт светодиода.
digitalWrite(ledPin, LOW); // Выключаем светодиод.
}
void loop()
{
// Если количество запусков превысило необходимое нам количество раз, то прекращаем выполнение скетча.
if (scValue > scCount) return;
// Иначе выполняем скетч дальше.
digitalWrite(ledPin, HIGH); // Включаем светодиод.
}
И так, что мы добавили в наш счетчик запусков.
Вот так вот просто мы можем ограничить количество запусков.
На этом этапе мы уже можем отправлять проект заказчику но придется долго и нудно объяснять как скачать Arduino IDE ну и собственно как прошить Arduino.
Еще один недостаток это то, что вам надо будет выслать скетч, а многие этого делать не хотят. По этому давайте еще больше усложним наш скетч и добавим разблокировку по вводу пароля.
#include "EEPROM.h" // Подключаем библиотеку EEPROM.
#define scAddress1 2 // Адрес, где хранятся показания счетчика.
#define scAddress2 3 // Адрес, где хранятся статус счетчика (вкл/выкл).
#define scCount 5 // Количество разрешенных запусков.
#define ledPin 13 // Порт Ардуино со светодиодом.
char scPassword[] = "www.arduino.on.kg"; // Пароль.
String scInput = ""; // Содержит пароль, полученный от пользователя.
byte scValue = 0; // Переменная с показаниями счетчика.
byte scEnable = 0; // Переменная со статусом счетчика.
void setup()
{
scValue = EEPROM.read(scAddress1); // Чтение данных счетчика из EEPROM.
scEnable = EEPROM.read(scAddress2); // Чтение статуса счетчика из EEPROM.
if (scValue == 255) scValue = 0; // Сбрасываем счетчик в 0.
if (scEnable == 255) scEnable = 1; // Сбрасываем статус на включён.
if (scValue <= scCount && scEnable)
{
scValue++; // Увеличиваем счетчик на единицу.
EEPROM.write(scAddress1, scValue); // Записываем данные счетчика обратно в EEPROM.
}
Serial.begin(9600); // Настраиваем COM-порт.
pinMode(ledPin, OUTPUT); // Настраиваем порт светодиода.
digitalWrite(ledPin, LOW); // Выключаем светодиод.
}
void loop()
{
// Если количество запусков превысило необходимое нам количество раз, то ждем ввода пароля.
if (scValue > scCount && scEnable)
{
delay(1000); // Ждем секунду, чтобы получить весь пароль целиком.
scInput = Serial.readString(); // Считываем пароль.
if (scInput != "") // Если что-то прочли.
if (scInput == scPassword) // Сравниваем пароли.
{
scEnable = 0; // Сбрасываем запрет.
EEPROM.write(scAddress2, scEnable); // Записываем в память EEPROM ноль чтобы выключить счетчик.
Serial.println("Password successfully."); // Сообщаем, что пароль подошел.
} else Serial.println("Password incorrect."); // Сообщаем, что пароль не подошел.
return; // Запрещаем выполнение скетча далее.
}
// Иначе выполняем скетч дальше.
digitalWrite(ledPin, HIGH); // Включаем светодиод.
}
Ну и давайте продолжим в том же духе, как и ранее в статье.
Собственно на этом мы можем и закончить со статьей. Проект, содержащий данный код перестанет работать через определенное количество включений, а запустить его можно просто подключив к компу и отправив пароль при помощи монитора порта или терминала. При этом и мы защищены, насколько это возможно и скетч остался только у нас.
Люди, пожалуйста, обратите внимание на то, что адреса в приведенных мною скетчах разные. Как вы должны понимать, энергонезависимая память не стирается после перезагрузки или включения / выключения Arduino. Поэтому данные скетчи будут работать только один раз, после чего в адреса используем в скетчах надо обратно записать байт = 255. Пожалуйста, разберитесь со скетчем и его работой.
Ну и в качестве бонуса, вот вам скетч который вернет энергонезависимую память Arduino в заводское состояние.
#include "EEPROM.h"
void setup()
{
for (int i = 0; i < EEPROM.length(); i++) EEPROM.write(i, 255);
}
void loop()
{
// ...
}
Всем спасибо за внимание, оставляйте свои комментарии и если тема найдет свою аудиторию то я выпущу продолжение.
По многочисленным просьбам, поступившим мне на почту, я добавил еще один пример. На этот раз счетчик работает не до 255, а до 65535 включений.
#define scAddress1 4 // Адрес, где хранятся показания счетчика.
#define scAddress2 6 // Адрес, где хранятся статус счетчика (вкл/выкл).
#define scCount 5 // Количество разрешенных запусков.
#define ledPin 13 // Порт Ардуино со светодиодом.
char scPassword[] = "www.arduino.on.kg"; // Пароль.
String scInput = ""; // Содержит пароль, полученный от пользователя.
uint16_t scValue = 0; // Переменная с показаниями счетчика.
uint8_t scEnable = 0; // Переменная со статусом счетчика.
void setup()
{
scValue = eeprom_read_word((uint16_t*)scAddress1); // Чтение данных счетчика из EEPROM.
scEnable = eeprom_read_byte((uint8_t*)scAddress2); // Чтение статуса счетчика из EEPROM.
if (scValue == 65535) scValue = 0; // Сбрасываем счетчик в 0.
if (scEnable == 65535) scEnable = 1; // Сбрасываем статус на включён.
if (scValue <= scCount && scEnable)
{
scValue++; // Увеличиваем счетчик на единицу.
eeprom_write_word((uint16_t*)scAddress1, scValue); // Записываем данные счетчика обратно в EEPROM.
}
Serial.begin(9600); // Настраиваем COM-порт.
pinMode(ledPin, OUTPUT); // Настраиваем порт светодиода.
digitalWrite(ledPin, LOW); // Выключаем светодиод.
}
void loop()
{
// Если количество запусков превысило необходимое нам количество раз, то ждем ввода пароля.
if (scValue > scCount && scEnable)
{
delay(1000); // Ждем секунду, чтобы получить весь пароль целиком.
scInput = Serial.readString(); // Считываем пароль.
if (scInput != "") // Если что то прочли.
if (scInput == scPassword) // Сравниваем пароли.
{
scEnable = 0; // Сбрасываем запрет.
eeprom_write_byte((uint8_t*)scAddress2, scEnable); // Записываем в память EEPROM ноль чтобы выключить счетчик.
Serial.println("Password successfully."); // Сообщаем что пароль подошел.
} else Serial.println("Password incorrect."); // Сообщаем что пароль не подошел.
return; // Запрещаем выполнение скетча далее.
}
// Иначе выполняем скетч дальше.
digitalWrite(ledPin, HIGH); // Включаем светодиод.
}
Так же в данном примере я отказался от библиотеки EEPROM, что немного укоротило скетч.
Если у Вас есть опыт в работе с Arduino и собственно есть время для творчества, мы приглашаем всех желающих стать авторами статей публикуемых на нашем портале. Это могут быть как уроки, так и рассказы о ваших экспериментах с Arduino. Описание различных датчиков и модулей. Советы и наставления начинающим. Пишите и размещайте свои статьи в соответсвующей ветке форума.