Всем здравствуйте, делал автономное устройство. В котором есть датчики, энкодер, работает все на батарейках, и в дело пошла библиотека Gyverpower,. Но я столкнулся с проблемой, после сна энкодер (или ардуино), тупят и на пин Arduino идет постоянно low-сигнал (будто бы кнопка зажата). Скрипт довольно большой, но я вырезал все что не касается проблемы и выделил ключевые моменты:
P.S. заметил, что если выходить из функции (return, и заного заходить (сбрасывать весь код, то проблема остается)
Меня интересует только проблема с энкодером, остальные недоделки скрипта меня не интересуют, да, я буду благодарен вашим замечаниям, но проект готов, вполне меня устраивает, кроме этого косяка со сном =)
P.S. заметил, что если выходить из функции (return, и заного заходить (сбрасывать весь код, то проблема остается)
Инициализация:
//-------ПИНЫ---------
#define S1 10
#define S2 4
#define KEY 2
//-------ПИНЫ---------
//-------БИБЛИОТЕКИ---------
#include <EncButton2.h>
//-------БИБЛИОТЕКИ---------
EncButton2<EB_ENCBTN> enc(INPUT_PULLUP, S1, S2, KEY);
void setup() {
Serial.begin(9600);
power.hardwareEnable(PWR_ALL);
power.calibrate(8000);
power.correctMillis(true);
// power.autoCalibrate();
newTimer(Timer1);
pinMode(SEN_VCC, OUTPUT);
digitalWrite(SEN_VCC, 1);
randomSeed(analogRead(0));
}
void loop() {
// в ней нет ничего такого, что касалось бы текущей проблемы
}
Сам процесс:
#define powerOff() \
lcd.noBacklight(); \
lcd.noDisplay(); \
digitalWrite(SEN_VCC, 0); \
bitSet(powerFlags, powerSave)
#define powerOn() \
lcd.display(); \
lcd.backlight(); \
digitalWrite(SEN_VCC, 1); \
bitClear(powerFlags, powerSave)
#define DisablePins() \
detachInterrupt(1)
#define EnablePins() \
attachInterrupt(1, btnTick, FALLING)
#define powerSave 0
#define disControl 1
#define powerFlag1 2
#define powerFlag2 3
#define powerFlag3 4
#define OptiFlag 5
#define Tupdate(x) x=millis()
#define check(x, y) if(millis() - x >= y)
#define newTimer(x) uint32_t x = millis()
byte workModePow(byte globMode) {
lcd.clear();
newTimer(Timer1);
newTimer(Timer2);
newTimer(Timer3);
newTimer(OptiTimer);
uint16_t randomTime = random(10, 30);
byte randomAlert = random(0, randomAlertTime);
digitalWrite(RED, 0);
uint16_t RepeatedTimer = 10;
uint16_t WorkTimer;
uint8_t PerNow1 = 0;
uint16_t RtimeL0 = 0;
uint16_t RtimeL = 0;
uint16_t FtimeL0 = 0;
uint16_t FtimeL = 0;
switch (globMode) {
case 0:
if (Timers.Wtime < 0) {
Timers.Wtime = ReminderOnline;
RepeatedTimer = RepeatedReminderOnline;
} else if (Timers.Wtime > 50) RepeatedTimer = Timers.Wtime * 0.2;
WorkTimer = Timers.Wtime + randomAlert;
PerNow1 = Timers.Wtime / 100;
break;
case 1:
if (Timers.Rtime < 0) {
Timers.Rtime = ReminderRelax;
RepeatedTimer = RepeatedReminderRelax;
} else if (Timers.Rtime > 50) RepeatedTimer = Timers.Rtime * 0.2;
WorkTimer = Timers.Rtime + randomAlert;
PerNow1 = Timers.Rtime / 100;
break;
case 2:
Timers.STimeEE = 0;
Timers.STimeEERep = 0;
if (Timers.Ftime < 0) {
Timers.Ftime = ReminderOff;
RepeatedTimer = RepeatedReminderOff;
} else if (Timers.Ftime > 50) RepeatedTimer = Timers.Ftime * 0.2;
WorkTimer = Timers.Ftime + randomAlert;
PerNow1 = Timers.Ftime / 100;
break;
}
static byte hours[3], mins[3], secs[3];
byte arrowPosition = 0;
bool missed = false;
byte secCounter = 0;
bool flag = 1;
int8_t mode = 0;
uint16_t timeL = 0;
bool mode_check = 1;
bool mode_time = 0;
bool arrow = 0;
// bool powerSave = 0;
// bool disControl = 0;
byte powerFlags = 0;
bitSet(powerFlags, powerFlag3);
bitSet(powerFlags, OptiFlag);
Tupdate(Timer1);
Tupdate(Timer3);
while (1) {
noTone(BUZ);
byte customChar[8] = { B00000, B00000, B01110, B10101, B10101, B10001, B01110, B00000 };
switch (globMode) {
case 0:
switch (secCounter % 4) {
case 0:
customChar[4] = B10101;
customChar[5] = B10001;
break;
case 1:
customChar[4] = B10111;
customChar[5] = B10001;
break;
case 2:
customChar[4] = B10101;
customChar[5] = B10101;
break;
case 3:
customChar[4] = B11101;
customChar[5] = B10001;
break;
}
break;
case 1:
switch ((secCounter % 8) / 2) {
case 0:
customChar[4] = B10101;
customChar[5] = B10001;
break;
case 1:
customChar[4] = B10111;
customChar[5] = B10001;
break;
case 2:
customChar[4] = B10101;
customChar[5] = B10101;
break;
case 3:
customChar[4] = B11101;
customChar[5] = B10001;
break;
}
break;
case 2:
switch (secCounter % 2) {
case 0:
customChar[3] = B10001;
customChar[4] = B10101;
break;
case 1:
customChar[3] = B10001;
customChar[4] = B10001;
break;
}
break;
}
if (bitRead(powerFlags, OptiFlag) && !bitRead(powerFlags, powerSave)) {
bitClear(powerFlags, OptiFlag);
Tupdate(OptiTimer);
switch (mode) {
case 0:
mode_check = 1;
switches(globMode, 0, hours[globMode], mins[globMode], secs[globMode], customChar);
break;
case 1:
mode_check = 1;
switches(globMode, 1, hours[globMode], mins[globMode], secs[globMode], customChar);
break;
case 2:
graphs(0, &mode_check, &mode_time, &arrow, arrowPosition);
break;
case 3:
graphs(1, &mode_check, &mode_time, &arrow, arrowPosition);
break;
case 4:
graphs(2, &mode_check, &mode_time, &arrow, arrowPosition);
break;
case 5:
graphs(3, &mode_check, &mode_time, &arrow, arrowPosition);
break;
case 6:
graphs(4, &mode_check, &mode_time, &arrow, arrowPosition);
break;
}
}
Serial.print(bitRead(powerFlags, disControl));
Serial.println(bitRead(powerFlags, powerSave));
if (!missed) digitalWrite(RED, 0);
bool flag1 = 1;
if (bitRead(powerFlags, disControl)) {
uint16_t howManySleep = millis() - Timer1;
if (howManySleep < 1000) power.sleepDelay(1000 - howManySleep); // вот тут ложимся спать менее, чем на секунду
} else {
delay(10); // delay, потому что без него почему-то не успевает обработать сигнал с энкодера библиотека
if (redbtn.tick() || yellowbtn.tick()) { // это отдельные кнопки, (без энкодера), они работает нормально
switch (globMode) {
case 0:
if (redbtn.click()) return 13;
if (yellowbtn.click()) return 12;
break;
case 1:
if (redbtn.click()) return 11;
if (yellowbtn.click()) return 13;
break;
case 2:
if (redbtn.click()) return 12;
if (yellowbtn.click()) return 11;
break;
}
if (redbtn.held() && yellowbtn.held()) return 99;
redbtn.resetState();
yellowbtn.resetState();
}
delay(10);
if(enc.tick()) {
Serial.println(enc.tick()); // вот здесь выводит после сна постоянно 7 (step, т.е. кнопка всегда зажата, но это не так), на любые движения энкодером не реагирует. До сна все нормально. Иногда бывает ничего не выводит, т.е. будто бы с энкодером ничего не происходит
if (!mode_time && enc.right()) {
autoOff = 0;
mode++;
mode = mode % 7;
mode_check = 1;
}
if (!mode_time && enc.left()) {
autoOff = 0;
if (mode == 0) mode = 6;
else
mode--;
mode_check = 1;
}
if (mode == 1 && enc.click()) {
autoOff = 0;
numberDrinks++;
}
if (mode == 1 && enc.held()) {
numberDrinks = 0;
autoOff = 0;
}
if (mode >= 2 && enc.held()) {
autoOff = 0;
WTime[EEPcounter] = Timers.WTimeEE;
RTime[EEPcounter] = Timers.RTimeEE;
FTime[EEPcounter] = Timers.FTimeEE;
missedW[EEPcounter] = missedNowW;
missedF[EEPcounter] = missedNowF;
Wmore[EEPcounter] = WmoreNow;
Rmore[EEPcounter] = RmoreNow;
Fmore[EEPcounter] = FmoreNow;
drink[EEPcounterDrink] = numberDrinks;
EEPcounter++;
EEPcounter = EEPcounter % 4;
EEPcounterDrink++;
EEPcounterDrink = EEPcounterDrink % 7;
EEPROM.put(5, WTime);
EEPROM.put(13, RTime);
EEPROM.put(21, FTime);
EEPROM.put(29, missedW);
EEPROM.put(33, missedF);
EEPROM.put(37, Wmore);
EEPROM.put(45, Rmore);
EEPROM.put(53, Fmore);
EEPROM.put(61, drink);
EEPROM.put(68, EEPcounter);
EEPROM.put(69, EEPcounterDrink);
lcd.clear();
lcd.setCursor(2, 0);
lcd.print("Data saved!");
delay(1000);
}
if (!mode_time && mode >= 2 && enc.rightH()) {
autoOff = 0;
arrowPosition++;
arrowPosition = arrowPosition % 5;
mode_check = 1;
}
if (!mode_time && mode >= 2 && enc.leftH()) {
autoOff = 0;
if (arrowPosition == 0) arrowPosition = 4;
else
arrowPosition--;
mode_check = 1;
}
if (!mode_time && mode >= 2 && enc.click()) {
autoOff = 0;
mode_time = 1;
mode_check = 1;
} else if (mode_time && enc.click()) {
autoOff = 0;
mode_time = 0;
mode_check = 1;
}
if (mode_time && mode == 2 && enc.leftH()) {
autoOff = 0;
if (arrowPosition != 4) FTime[arrowPosition] = FTime[arrowPosition] - 10;
else
Timers.FTimeEE = Timers.FTimeEE - 10;
}
if (mode_time && mode == 2 && enc.rightH()) {
autoOff = 0;
if (arrowPosition != 4) FTime[arrowPosition] = FTime[arrowPosition] + 10;
else
Timers.FTimeEE = Timers.FTimeEE + 10;
}
if (mode_time && mode == 3 && enc.leftH()) {
autoOff = 0;
if (arrowPosition != 4) {
if (!arrow) WTime[arrowPosition] = WTime[arrowPosition] - 10;
else
RTime[arrowPosition] = RTime[arrowPosition] - 10;
} else {
if (!arrow) Timers.WTimeEE = Timers.WTimeEE - 10;
else
Timers.RTimeEE = Timers.RTimeEE - 10;
}
}
if (mode_time && mode == 3 && enc.rightH()) {
autoOff = 0;
if (arrowPosition != 4) {
if (!arrow) WTime[arrowPosition] = WTime[arrowPosition] + 10;
else
RTime[arrowPosition] = RTime[arrowPosition] + 10;
} else {
if (!arrow) Timers.WTimeEE = Timers.WTimeEE + 10;
else
Timers.RTimeEE = Timers.RTimeEE + 10;
}
}
if (mode_time && mode == 6 && enc.leftH()) {
autoOff = 0;
if (arrowPosition != 7) {
drink[arrowPosition] = drink[arrowPosition] - 1;
} else {
numberDrinks = numberDrinks - 1;
}
}
if (mode_time && mode == 6 && enc.rightH()) {
autoOff = 0;
if (arrowPosition != 7) {
drink[arrowPosition] = drink[arrowPosition] + 1;
} else {
numberDrinks = numberDrinks + 1;
}
}
enc.resetState();
}
}
if (missed && (millis() - Timer2 >= 1000)) {
digitalWrite(RED, flag = !flag);
Tupdate(Timer2);
}
check(Timer3, 1000) {
Timer3 = Timer3 + 1000;
secs[globMode]++;
secCounter++;
autoOff++;
if (autoOff == 255) autoOff = 120;
if (secs[globMode] >= 60) {
secs[globMode] = secs[globMode] % 60;
mins[globMode]++;
timeL++;
switch (globMode) {
case 0:
Timers.WTimeEE++;
Timers.STimeEE++;
break;
case 1:
Timers.RTimeEE++;
Timers.STimeEE++;
RtimeL++;
break;
case 2:
Timers.FTimeEE++;
FtimeL++;
break;
}
if (missed) Timers.STimeEERep++;
if (missed) WmoreNow++;
}
if (mins[globMode] >= 60) {
mins[globMode] = mins[globMode] % 60;
hours[globMode]++;
}
if (hours[globMode] >= 10) hours[globMode] = 0;
}
if(!bitRead(powerFlags, OptiFlag) && millis() - OptiTimer >= 1000) {
bitSet(powerFlags, OptiFlag);
}
if (bitRead(powerFlags, powerFlag1) && autoOff >= 60) { // здесь происходит условия, когда уже можно выключать мк, если устройство "бездействует"
bitClear(powerFlags, powerFlag1);
bitSet(powerFlags, powerFlag3);
bitSet(powerFlags, disControl);
EnablePins();
} else if (bitRead(powerFlags, powerFlag2) && autoOff >= 120) {
bitClear(powerFlags, powerFlag2);
bitSet(powerFlags, powerFlag3);
powerOff();
} else if (bitRead(powerFlags, powerFlag3) && autoOff < 60) {
bitSet(powerFlags, powerFlag1);
bitSet(powerFlags, powerFlag2);
bitClear(powerFlags, powerFlag3);
bitClear(powerFlags, disControl);
DisablePins();
powerOn();
}
}
}
void btnTick(void) {
if (!digitalRead(REDBUT) || !digitalRead(KEY)) autoOff = 0; // т.к. мк спит, я подключил прерывание, чтобы будить мк и сбрасывать счетсчик бездействия
}