MurlocProger

Проект по практике - Кодовый замок

Aug 12th, 2023
21
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 27.06 KB | None | 0 0
  1. /*
  2. ВНИМАНИЕ! ПУТЬ К ПАПКЕ СО СКЕТЧЕМ НЕ ДОЛЖЕН СОДЕРЖАТЬ РУССКИХ СИМВОЛОВ
  3. ВО ИЗБЕЖАНИЕ ПРОБЛЕМ ПОЛОЖИТЕ ПАПКУ В КОРЕНЬ ДИСКА С
  4.  
  5. Внимание! При первом запуске initial_calibration должен быть равен 1 (строка №17)
  6. При подключении и открытии монитора порта будет запущен процесс калибровки.
  7. Вам нужно при помощи вольтметра измерить напряжение на пинах 5V и GND,
  8. затем отправить его в монитор В МИЛЛИВОЛЬТАХ, т.е. если на вольтметре 4.56
  9. то отправить примерно 4560. После этого изменить initial_calibration на 0
  10. и заново прошить Arduino.
  11. Если хотите пропустить процесс калибровки, то введите то же самое напряжение,
  12. что было показано вам при калибровке (real VCC). И снова прошейте код.
  13. */
  14. /*
  15. ------------------------ЛОГИКА РАБОТЫ--------------------------
  16. Дверь закрыта, нажато СНАРУЖИ - проснуться, ждать ввод пароля
  17. Дверь закрыта, нажато ВНУТРИ - открыть
  18. Дверь открыта, нажато СНАРУЖИ - закрыть
  19. Дверь открыта, нажато ВНУТРИ - закрыть
  20. Дверь открыта, нажат КОНЦЕВИК - закрыть
  21.  
  22. Просыпаться каждые несколько секунд, следить за СОБЫТИЕМ
  23. Каждые несколько минут следить за напряжением акума
  24. Если акум разряжен:
  25. - открыть дверь (опционально)
  26. - запретить дальнейшее открытие и закрытие
  27. - при нажатии на кнопки мигать красным светодиодом
  28. - перестать следить за СОБЫТИЕМ
  29.  
  30. //-----------------------ПАРОЛЬ------------------------
  31. Когда система не спит, нажать кнопку смены пароля (скрытая кнопка). Попадаем в режим смены пароля:
  32. - Вводим пароль из цифр (МАКСИМУМ 10 ЦИФР!!!)
  33. - При нажатии * пароль записывается в память и система выходит из смены пароля
  34. - При нажатии # пароль сбрасывается (можно вводить заново)
  35. - Если ничего не нажимать 10 секунд, автоматически выйдем из режима смены пароля, пароль останется старый
  36.  
  37. Когда система не спит (проснулись по кнопки или сон отключен), нажать * для входа в режим ввода пароля
  38. Если система спит и периодически просыпается проверять СОБЫТИЕ, то нажимаем * и удерживаем, пока не загорится красный светодиод
  39. Режим ввода пароля:
  40. - Обработка пароля сделана таким образом, что правильный пароль засчитывается только при наборе
  41. правильной последовательности цифр, то есть если пароль 345, то вводить можно любые числа до тех пор,
  42. пока не появится последовательность 345, т.е. 30984570345 откроет замок, так как оканчивается на 345
  43. - Если пароль введён верно, дверь откроется
  44. - Если ничего не нажимать, через 10 секунд система вернётся в обычный (дежурный) режим
  45. //-----------------------ПАРОЛЬ------------------------
  46. */
  47.  
  48. //-------------------------------НАСТРОЙКИ-----------------------------------
  49. #define lock_type 0 // 0 - сервопривод, 1 - щеколда, 2 - привод автомобильный
  50.  
  51. #define tail_button 1 // 1 - используется концевик на закрытие, 0 - не используется
  52. #define sleep_time 10000 // время на ввод пароля после просыпания (если не начать вводить - уснёт)
  53.  
  54. #define sleep_enable 1 // спящий режим с кнопкой проснуться (0 - выключить, 1 - включить)
  55. #define wake_button 0 // 1 - просыпаться только по наружной кнопке, 0 - просыпаться периодически и проверять СОБЫТИЕ
  56. boolean battery_monitor = 1; // измерение заряда акума (защита от переразряда)
  57. #define bat_low 3000 // напряжение акума в МИЛЛИВОЛЬТАХ, при котором сработает защита
  58. boolean open_bat_low = 1; // 1 - открыть дверь, если акум разряжен
  59.  
  60. #define vol_calibration 0 // калибровка вольтметра (если работа от АКБ) 1 - включить, 0 - выключить
  61.  
  62. //--------------СЕРВО--------------
  63. #define servoMin 40 // угол сервы для положения "замок открыт", подбирается экспериментально
  64. #define servoMax 170 // угол сервы для положения "замок закрыт", подбирается экспериментально
  65.  
  66. //--------------ЩЕКОЛДА--------------
  67. boolean latch_inverse = 0; // 0 - если у вас реле высокого уровня или МОСФЕТ, 1 - если у вас реле низкого уровня
  68. int latch_time = 1000; // время (в миллисекундах), которое ток будет подаваться на защёлку для открытия
  69.  
  70. //--------------ПРИВОД--------------
  71. #define gear_inv 0 // инвертировать привод (1 или 0)
  72.  
  73. //-------------------------------НАСТРОЙКИ-----------------------------------
  74.  
  75. // автоматический выбор close_button: 0 - если используем захлопывающуюся щеколду, 1 если серво или привод замка
  76. #if lock_type == 1
  77. #define close_button 0
  78. #else
  79. #define close_button 1
  80. #endif
  81.  
  82. //---АВТОМАТИЧСЕКИЕ НАСТРОЙКИ В ЗАВИСИМОСТИ ОТ ТИПА ЗАМКА-----
  83. #if lock_type == 0
  84. //-----------------СЕРВО----------------
  85. #include <Servo.h> // используем библиотеку для работы с сервоприводом
  86. #define servo_pin A3 // серво на A3
  87. Servo servo; // объявляем переменную servo типа Servo
  88. //-----------------СЕРВО----------------
  89. #elif lock_type == 1
  90. //-----------------ЩЕКОЛДА----------------
  91. #define latch_pin A3
  92. //-----------------ЩЕКОЛДА----------------
  93. #elif lock_type == 2
  94. //-----------------ПРИВОД----------------
  95. #define relay1 A2 // пин реле 1 подключен к А2
  96. #define relay2 A3 // пин реле 2 подключен к А3
  97. #define gear_delay 400 // время (в мс), которое ток подаётся на привод (время открытия/закрытия)
  98. //-----------------ПРИВОД----------------
  99. #endif
  100. //---АВТОМАТИЧСЕКИЕ НАСТРОЙКИ В ЗАВИСИМОСТИ ОТ ТИПА ЗАМКА-----
  101.  
  102. //----------------------БИБЛИОТЕКИ------------------------
  103. #include <EEPROMex.h> // библиотека для работы со внутренней памятью ардуино
  104. #include <LowPower.h> // библиотека сна
  105. #include "Keypad.h" //библиотека клавиатуры
  106. //----------------------БИБЛИОТЕКИ------------------------
  107.  
  108. //----------------------КЛАВИАТУРА------------------------
  109. unsigned long pass_timer;
  110. char key;
  111. String str_pass = "";
  112. byte pass_lenght, j;
  113. unsigned long int_pass; // 10 знаков моксимум!!
  114. char keys[4][3] = {
  115. {'1', '2', '3'},
  116. {'4', '5', '6'},
  117. {'7', '8', '9'},
  118. {'*', '0', '#'}
  119. };
  120. byte rowPins[] = {12, 11, 10, 9}; // Подключены строки (4 пина)
  121. byte colPins[] = {8, 7, 6}; // подключены столбцы (4 пина)
  122. Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, 4, 3 ); //иниициализировать клавиатуру
  123. //----------------------КЛАВИАТУРА------------------------
  124.  
  125. #define LEDgrn A0 // красный светодиод на А0
  126. #define LEDred A1 // зелёный светодиод на А1
  127. #define set_pass_btn 4 // кнопка смены пароля на 4 пин
  128. #define tail_pin 5 // кнопка концевика
  129. float my_vcc_const = 1.1; // начальное значение константы вольтметра
  130.  
  131. boolean set_pass_btn_flag; // флажок кнопки смены пароля
  132. boolean batteryOK = true; // дверь можно закрыть, если акум заряжен
  133. boolean set_access_flag; // флажок режима смены пароля/ключа
  134. volatile boolean door_state; // состояние двери (1 - открыто, 0 - закрыто)
  135. volatile unsigned long awake_timer, auto_awake_timer, last_press;
  136. volatile boolean inside_btn_flag, close_flag, sleep_flag;
  137. volatile byte sleep_count;
  138. boolean wake_event = false, wait_for_event = true, wakeUP_procedure_flag = false;
  139.  
  140. void setup() {
  141. Serial.begin(9600); // открыть порт для отладки
  142. if (vol_calibration) calibration(); // калибровка, если разрешена
  143. my_vcc_const = EEPROM.readFloat(1000);
  144.  
  145. // ПАРОЛЬ
  146. int_pass = EEPROM.readLong(0); // вспоминаем пароль из памяти
  147. str_pass = String(int_pass, DEC); // переводим в строчный тип
  148. pass_lenght = str_pass.length(); // получиаем длину пароля
  149. // ПАРОЛЬ
  150.  
  151. // подтянуть все кнопки
  152. pinMode(2, INPUT_PULLUP);
  153. pinMode(3, INPUT_PULLUP);
  154. pinMode(set_pass_btn, INPUT_PULLUP);
  155. pinMode(tail_pin, INPUT_PULLUP);
  156.  
  157. pinMode(LEDred, OUTPUT);
  158. pinMode(LEDgrn, OUTPUT);
  159. digitalWrite(LEDred, 0);
  160. digitalWrite(LEDgrn, 0);
  161.  
  162. // прерывания: 2 пин на внутреннюю кнопку
  163. attachInterrupt(0, inside_btn, FALLING);
  164. // 3 пин на внешнюю кнопку
  165. attachInterrupt(1, outside_btn, FALLING);
  166.  
  167. //---АВТОМАТИЧСЕКИЕ НАСТРОЙКИ В ЗАВИСИМОСТИ ОТ ТИПА ЗАМКА-----
  168. #if lock_type == 1 // если щеколда
  169. pinMode(latch_pin, OUTPUT);
  170. digitalWrite(latch_pin, latch_inverse);
  171. #elif lock_type == 2 // если привод (2 реле)
  172. pinMode(relay1, OUTPUT);
  173. pinMode(relay2, OUTPUT);
  174. digitalWrite(relay1, 1);
  175. digitalWrite(relay2, 1);
  176. #endif
  177. //---АВТОМАТИЧСЕКИЕ НАСТРОЙКИ В ЗАВИСИМОСТИ ОТ ТИПА ЗАМКА-----
  178. open_door();
  179. }
  180.  
  181. // набор команд для открытия двери
  182. void open_door() {
  183. if (batteryOK) { // если акум заряжен
  184. digitalWrite(LEDgrn, 1); // зелёный свет
  185. digitalWrite(LEDred, 0);
  186. last_press = millis();
  187. //--------ОТКРЫТЬ---------
  188. #if lock_type == 0
  189. servo.attach(servo_pin); // привязываем привод к порту
  190. servo.write(servoMin); // поворачиваем серву
  191. delay(500); // ждём поворот
  192. servo.detach(); // отвязываем привод
  193. #elif lock_type == 1 // если щеколда
  194. digitalWrite(latch_pin, !latch_inverse); // подать ток на защёлку
  195. delay(latch_time); // подождать
  196. digitalWrite(latch_pin, latch_inverse); // прекратить подачу тока
  197. #elif lock_type == 2 // если привод замка
  198. if (gear_inv) { // перещёлкнуть реле, подождать, все дела
  199. digitalWrite(relay1, 0);
  200. delay(gear_delay);
  201. digitalWrite(relay1, 1);
  202. } else {
  203. digitalWrite(relay2, 0);
  204. delay(gear_delay);
  205. digitalWrite(relay2, 1);
  206. }
  207. #endif
  208. //--------ОТКРЫТЬ---------
  209. if (!close_button) {
  210. door_state = 0; // считать дверь закрытой (сама захлопнется)
  211. digitalWrite(LEDred, 0); // выключить свет
  212. digitalWrite(LEDgrn, 0);
  213. }
  214. else door_state = 1; // считать дверь открытой
  215. } else { // если акум разряжен
  216. for (int i = 0; i < 3; i++) { // мигать красным светодиодом
  217. digitalWrite(LEDred, 1);
  218. delay(500);
  219. digitalWrite(LEDred, 0);
  220. delay(500);
  221. }
  222. }
  223. if (sleep_enable) sleep_mode();
  224. }
  225.  
  226. // набор команд для закрытия двери
  227. void close_door() {
  228. if (batteryOK) { // если акум заряжен
  229. digitalWrite(LEDred, 1); // зелёный свет
  230. last_press = millis();
  231. //--------ЗАКРЫТЬ---------
  232. #if lock_type == 0 // если серво
  233. servo.attach(servo_pin); // привязываем привод к порту
  234. servo.write(servoMax); // поворачиваем серву
  235. delay(500); // ждём поворот
  236. servo.detach(); // отвязываем привод
  237. #elif lock_type == 1 // если щеколда
  238. // ничего не делать, щеколда же =)
  239. #elif lock_type == 2 // если привод замка
  240. if (gear_inv) { // перещёлкнуть реле, подождать, все дела
  241. digitalWrite(relay2, 0);
  242. delay(gear_delay);
  243. digitalWrite(relay2, 1);
  244. } else {
  245. digitalWrite(relay1, 0);
  246. delay(gear_delay);
  247. digitalWrite(relay1, 1);
  248. }
  249. #endif
  250. //--------ЗАКРЫТЬ---------
  251. door_state = 0;
  252. delay(500);
  253. digitalWrite(LEDred, 0); // выключить свет
  254. digitalWrite(LEDgrn, 0);
  255. } else { // если акум разряжен
  256. for (int i = 0; i < 3; i++) { // мигать красным светодиодом
  257. digitalWrite(LEDred, 1);
  258. delay(500);
  259. digitalWrite(LEDred, 0);
  260. delay(500);
  261. }
  262. }
  263. if (sleep_enable) sleep_mode();
  264. }
  265.  
  266. void passChange() {
  267. digitalWrite(LEDred, 0); //
  268. digitalWrite(LEDgrn, 0); // зеленый свет
  269. delay(70);
  270. digitalWrite(LEDgrn, 1); // зеленый свет
  271.  
  272. str_pass = "";
  273. pass_timer = millis(); // сброс таймера ввода пароля
  274. while (1) { // бесконечный цикл
  275. key = keypad.getKey(); // обработка нажатия
  276. if (key != NO_KEY) { // если была нажата
  277. pass_timer = millis(); // сбросить таймер
  278. if (key == '*') { // если нажата *
  279. int_pass = str_pass.toInt(); // перевести в число
  280. EEPROM.writeLong(0, int_pass); // записать в память
  281. pass_lenght = str_pass.length(); // получиаем длину пароля
  282. Serial.println(str_pass);
  283. break; // выйти из цикла
  284. }
  285. else if (key == '#') { // если нажата #
  286. str_pass = ""; // начать ввод сначала
  287. }
  288. else { // если * не нажата
  289. str_pass += key; // прибавить нажатую цифру к паролю
  290. }
  291. }
  292. // если нажата кнопка смены пароля, просто выйти из режима смены пароля
  293. if (!digitalRead(set_pass_btn) && !set_pass_btn_flag) {
  294. str_pass = String(int_pass, DEC);
  295. awake_timer = millis();
  296. set_pass_btn_flag = 1;
  297. break;
  298. }
  299. if (millis() - pass_timer > 10000) { // если сработал таймер
  300. str_pass = String(int_pass, DEC); // сбросить ввод и выйти из цикла
  301. break;
  302. }
  303. }
  304. digitalWrite(LEDgrn, 0); // погасить зеленый свет
  305. }
  306.  
  307. void wakeUP_procedure() {
  308.  
  309. }
  310. void sleep_procedure() {
  311.  
  312. }
  313.  
  314. void event() {
  315. key = keypad.getKey(); // обработка нажатия
  316. if (key == '*') { // если была нажата *
  317. pass_timer = millis(); // сбросить таймер
  318. digitalWrite(LEDgrn, 0);
  319. digitalWrite(LEDred, 1);
  320. j = 0;
  321. while (1) { // бесконечный цикл ввода пароля
  322. key = keypad.getKey(); // обработка нажатия
  323. if (key != NO_KEY) { // если была нажата
  324. pass_timer = millis(); // сбросить таймер
  325. if (key == str_pass[j]) { // если новая введённая цифра совпала с цифрой пароля
  326. j++; // прибавить счётчик
  327. } else { // если нет
  328. j = 0; // начать с начала
  329. }
  330. if (j == pass_lenght) { // если были введены все правильные цифры пароля
  331. digitalWrite(LEDred, 0); // вырубить красный
  332. digitalWrite(LEDgrn, 1); // включить зелёный
  333. open_door(); // открыть дверь
  334. break; // выйти из цикла
  335. }
  336. if (key == '#') { // если нажата #
  337. digitalWrite(LEDred, 0); // вырубить красный
  338. break; // выйти из цикла
  339. }
  340. }
  341. if (millis() - pass_timer > 10000) { // если сработал таймер
  342. break; // выйти из цикла
  343. }
  344. }
  345. }
  346. }
  347.  
  348. // отработка прерывания нажатия изнутри
  349. void inside_btn() {
  350. if (millis() - last_press > 500) { // таймер повторного открытия (побеждает глюк с приводом!)
  351. auto_awake_timer = millis(); // сбросить таймер
  352. if (!door_state) // если дверь ЗАКРЫТА
  353. inside_btn_flag = 1; // флажок на открытие
  354. else // если дверь ОТКРЫТА
  355. close_flag = 1; // флажок на закрытие
  356. sleep_count = 0; // обнулить таймер вольтметра
  357. }
  358. }
  359.  
  360. // отработка прерывания нажатия снаружи
  361. void outside_btn() {
  362. if (millis() - last_press > 500) { // таймер повторного открытия (побеждает глюк с приводом!)
  363. auto_awake_timer = millis();
  364. if (door_state) { // если дверь ОТКРЫТА
  365. close_flag = 1; // флажок на закрытие
  366. } else { // если нет
  367. // проснуться и обнулить таймер
  368. digitalWrite(LEDred, 1);
  369. digitalWrite(LEDgrn, 1);
  370. wakeUP_procedure_flag = true; // выполнить 1 раз когда проснулся
  371. awake_timer = millis();
  372. sleep_flag = 1;
  373. }
  374. sleep_count = 0; // обнулить таймер вольтметра
  375. }
  376. }
  377.  
  378. void loop() {
  379.  
  380. event();
  381.  
  382. // ---- ВЫПОЛНИТЬ КАК ПРОСНЁМСЯ -----
  383. if (wakeUP_procedure_flag) {
  384. wakeUP_procedure();
  385. wakeUP_procedure_flag = false;
  386. }
  387. // ---- ВЫПОЛНИТЬ КАК ПРОСНЁМСЯ -----
  388.  
  389. if (set_access_flag) {
  390. passChange();
  391. set_access_flag = 0;
  392. }
  393.  
  394. // если дверь была открыта и нажат концевик (кнопка закрыть)
  395. if (close_flag) {
  396. close_flag = 0;
  397. close_door(); // закрыть дверь
  398. }
  399.  
  400. // если дверь закрыта и нажата кнопка открытия изнутри
  401. if (inside_btn_flag && !door_state) {
  402. inside_btn_flag = 0;
  403. open_door(); // команда для открытия двери
  404. }
  405.  
  406. // отработка нажатия кнопки смены пароля
  407. if (!digitalRead(set_pass_btn) && !set_pass_btn_flag) {
  408. awake_timer = millis();
  409. set_pass_btn_flag = 1;
  410. }
  411. if (digitalRead(set_pass_btn) && set_pass_btn_flag) {
  412. set_pass_btn_flag = 0;
  413. set_access_flag = 1;
  414. }
  415. // отработка нажатия кнопки смены пароля
  416.  
  417. // если разрешён сон и прошло больше времени, чем по таймеру
  418. if (millis() - awake_timer > sleep_time && !set_access_flag) {
  419. if (!door_state) { // если дверь закрыта, выключить светодиоды
  420. digitalWrite(LEDred, 0);
  421. digitalWrite(LEDgrn, 0);
  422. sleep_flag = 0;
  423. }
  424. if (sleep_enable) {
  425. sleep_mode();
  426. if (wake_button) awake_timer = millis();
  427. }
  428. }
  429. if (!digitalRead(tail_pin) && door_state) {
  430. close_door();
  431. }
  432. }
  433.  
  434.  
  435. // режим сна (зависит от того, измеряем мы напряжение акума или нет)
  436. void sleep_mode() {
  437. sleep_procedure();
  438. if (!batteryOK) digitalWrite(LEDgrn, 0);
  439. delay(50);
  440. if (tail_button && door_state && close_button) {
  441. LowPower.powerDown(SLEEP_500MS, ADC_OFF, BOD_OFF); // спать 500 мс. mode POWER_OFF, АЦП выкл
  442. awake_timer = millis() + sleep_time; // КОСТЫЛЬ БЛЯ
  443. if (!digitalRead(tail_pin)) {
  444. close_door();
  445. }
  446. } else {
  447. if (sleep_enable && wake_button && !battery_monitor) // если ничего не надо
  448. LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF); // спать. mode POWER_OFF, АЦП выкл
  449. if (sleep_enable && wake_button && battery_monitor) { // если просто исзеряем акб
  450. LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); // спать 8 сек. mode POWER_OFF, АЦП выкл
  451. awake_timer = millis() + sleep_time; // КОСТЫЛЬ БЛЯ
  452. battery_m();
  453. }
  454. if (sleep_enable && !wake_button) { // если ловим событие + акб измеряем
  455. LowPower.powerDown(SLEEP_4S, ADC_OFF, BOD_OFF); // спать 4 сек. mode POWER_OFF, АЦП выкл
  456. awake_timer = millis() + sleep_time; // КОСТЫЛЬ БЛЯ
  457. delay(50);
  458. Serial.println("awake");
  459. event_m();
  460. if (battery_monitor) battery_m(); // если хотим ещё акб измерять, измеряем
  461. }
  462. }
  463. }
  464. void battery_m() {
  465. sleep_count++;
  466. if (sleep_count > 75) { // если прошло ~5 минут
  467. sleep_count = 0; // сбросить счётчик
  468. if (readVcc() < bat_low) { // если акум разряжен
  469. wait_for_event = false; // перестать ждать СОБЫТИЕ
  470. battery_monitor = false; // перестать мониторить АКБ
  471. if (open_bat_low) open_door(); // открыть дверь (и уснуть)
  472. batteryOK = false; // запретить закрытие и открытие двери
  473. }
  474. }
  475. }
  476. void event_m() {
  477. if (wake_event) {
  478. // проснуться и обнулить таймер
  479. digitalWrite(LEDred, 1);
  480. digitalWrite(LEDgrn, 1);
  481. wake_event = false;
  482. wakeUP_procedure_flag = true; // выполнить 1 раз когда проснулся
  483. awake_timer = millis();
  484. sleep_count = 0; // обнулить таймер вольтметра
  485. }
  486. }
  487.  
  488. void calibration() {
  489. //--------калибровка----------
  490. my_vcc_const = 1.1; // начальаня константа калибровки
  491. Serial.print("Real VCC is: "); Serial.println(readVcc()); // общаемся с пользователем
  492. Serial.println("Write your VCC (in millivolts)");
  493. while (Serial.available() == 0); int Vcc = Serial.parseInt(); // напряжение от пользователя
  494. float real_const = (float)1.1 * Vcc / readVcc(); // расчёт константы
  495. Serial.print("New voltage constant: "); Serial.println(real_const, 3);
  496. EEPROM.writeFloat(1000, real_const); // запись в EEPROM
  497. while (1); // уйти в бесконечный цикл
  498. //------конец калибровки-------
  499. }
  500.  
  501. long readVcc() { //функция чтения внутреннего опорного напряжения, универсальная (для всех ардуин)
  502. #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  503. ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  504. #elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
  505. ADMUX = _BV(MUX5) | _BV(MUX0);
  506. #elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
  507. ADMUX = _BV(MUX3) | _BV(MUX2);
  508. #else
  509. ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  510. #endif
  511. delay(2); // Wait for Vref to settle
  512. ADCSRA |= _BV(ADSC); // Start conversion
  513. while (bit_is_set(ADCSRA, ADSC)); // measuring
  514. uint8_t low = ADCL; // must read ADCL first - it then locks ADCH
  515. uint8_t high = ADCH; // unlocks both
  516. long result = (high << 8) | low;
  517.  
  518. result = my_vcc_const * 1023 * 1000 / result; // расчёт реального VCC
  519. return result; // возвращает VCC
  520. }
Add Comment
Please, Sign In to add comment