аварийное сохранение вроде работает. но зависит от источника питания, если при отключении будут всякие скачки напряжения туда-сюда, например если блок питания как-то медленно вынимать из розетки, то может не сработать или подглючить и намотать лишних витков. но я тестировал с кондером 1000мкф, может если увеличить будет лучше. но если отключать питание вырывая штекер прям возле ардуины - работает хорошо.
вот так надо замодить ардуйню
только проверь контакты чтоб точно те были, я мог что-нибудь неправильно нарисовать.
вот последний рабочий кот:
#include <EEPROM.h>
#include <LiquidCrystal.h>
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
#define BTN_UP 1
#define BTN_DOWN 2
#define BTN_LEFT 3
#define BTN_RIGHT 4
#define BTN_SELECT 5
#define BTN_NONE 0
#define ANALOG_PIN A0
#define PWM_PIN 10
#define DETECT_PIN 11
int read_int(int addr) {
byte raw[2];
for(byte i = 0; i < 2; i++) raw[i] = EEPROM.read(addr+i);
int &num = (int&)raw;
return num;
}
void write_int(int addr, int num) {
byte raw[2];
(int&)raw = num;
for(byte i = 0; i < 2; i++) EEPROM.write(addr+i, raw[i]);
}
int detectButton() {
int keyAnalog = analogRead(ANALOG_PIN);
if (keyAnalog < 100) {
return BTN_RIGHT;
} else if (keyAnalog < 200) {
return BTN_UP;
} else if (keyAnalog < 400) {
return BTN_DOWN;
} else if (keyAnalog < 600) {
return BTN_LEFT;
} else if (keyAnalog < 800) {
return BTN_SELECT;
} else {
return BTN_NONE;
}
}
unsigned long timer;
unsigned long button_timer;
unsigned long drop_timer;
unsigned long backmod_timer;
int button=0;
int button_old=0;
unsigned char memerr_l=0;
unsigned char memerr_v=0;
unsigned char back_mod=0;
unsigned char button_flag=0;
unsigned char select_flag=0;
volatile char lcdref_flag=0;
int vitki=0;
int vitki_mem[3];
int vitki_old=0;
char vit_nom[16];
int vitki_back=0;
int vitki_back_o=0;
volatile char dir=1;
volatile char dtc=0;
volatile char dtc_f=0;
int light=30;
int light_mem[3];
int light_old;
const int addr=0;
void interrupt0(){
analogWrite(PWM_PIN,0);
if(vitki!=vitki_old){
write_int(10+addr,vitki*(-1+2*dtc_f));
write_int(12+addr,vitki*(-1+2*dtc_f));
write_int(14+addr,vitki*(-1+2*dtc_f));
}
if(light!=light_old){
EEPROM.write(0+addr,(uint8_t)light);
EEPROM.write(1+addr,(uint8_t)light);
EEPROM.write(2+addr,(uint8_t)light);
}
delay(500);
analogWrite(PWM_PIN,5);
lcd.setCursor(0, 0);
lcd.print("nepe3arpy3u!");
while(1==1){
delay(200);
}
}
void interrupt1(){
dtc=digitalRead(DETECT_PIN);
if(vitki==0){
dir=1;
dtc_f=dtc;
}else if(dtc_f==dtc){
dir=1;
}else {dir=-1;}
vitki+=dir;
lcdref_flag=1;
if(vitki>32760){vitki=0;}
}
void setup() {
analogWrite(PWM_PIN,0);
digitalWrite(DETECT_PIN,1);
//digitalWrite(2,1);
digitalWrite(3,1);
int i=0;
if(EEPROM.read(3+addr)==123){
for(i=0;i<3;i++){
light_mem[i]=EEPROM.read(i+addr);
}
if(light_mem[0]==light_mem[1]){
light=light_mem[0]; memerr_l=0;
}else if(light_mem[0]==light_mem[2]){
light=light_mem[0]; memerr_l=1;
}else if(light_mem[1]==light_mem[2]){
light=light_mem[1]; memerr_l=2;
}else{light=30; memerr_l=3;}
}else{
EEPROM.write(0+addr,30);
EEPROM.write(1+addr,30);
EEPROM.write(2+addr,30);
EEPROM.write(3+addr,123);
if(EEPROM.read(3+addr)!=123){memerr_l=4;}
}
light_old=light;
analogWrite(PWM_PIN,light);
if(EEPROM.read(16+addr)==123){
vitki_mem[0]=read_int(10+addr);
vitki_mem[1]=read_int(12+addr);
vitki_mem[2]=read_int(14+addr);
if(vitki_mem[0]==vitki_mem[1]){
vitki=vitki_mem[0]; memerr_v=0;
}else if(vitki_mem[0]==vitki_mem[2]){
vitki=vitki_mem[0]; memerr_v=1;
}else if(vitki_mem[1]==vitki_mem[2]){
vitki=vitki_mem[1]; memerr_v=2;
}else{vitki=0; memerr_v=3;}
}else{
write_int(10+addr,0);
write_int(12+addr,0);
write_int(14+addr,0);
EEPROM.write(16+addr,123);
if(EEPROM.read(16+addr)!=123){memerr_v=4;}
}
if(vitki<0){dtc_f=0; vitki=-vitki;}
else{dtc_f=1;}
vitki_old=vitki;
vitki_back=vitki;
lcd.begin(16, 2);
lcd.clear();
lcd.noBlink();
lcd.noCursor();
lcd.print("npuBeT!");
lcd.setCursor(0, 1);
if(memerr_l||memerr_v){
sprintf(vit_nom, "owu6Ka: %d, %d",memerr_l,memerr_v);
lcd.print(vit_nom);
}else{
lcd.print("naM. HopM");
}
delay(1000);
lcd.clear();
lcd.print(" HAMOTAHO: ");
lcd.setCursor(0, 1);
sprintf(vit_nom, " %04d", vitki);
lcd.print(vit_nom);
delay(500);
EIFR = 1;
EIFR = 2;
attachInterrupt(1, interrupt1, FALLING);
attachInterrupt(0, interrupt0, FALLING);
}
void loop() {
timer=millis();
if(detectButton()>0 && !button_flag){
button_flag=1;
button_timer=timer;
} else if(detectButton()==0 && button_flag){
button_flag=0;
button=0;
button_old=0;
}
if(button_flag==1 && timer-button_timer>40){
button=detectButton();
button_flag=2;
}
if(button_old!=button){
button_old=button;
if(!back_mod){lcdref_flag=1;}
switch(button){
case BTN_SELECT:
drop_timer=timer;
if(!back_mod){
select_flag=1;
} else{
back_mod=0;
lcdref_flag=1;
select_flag=0;
uint8_t oldSREG = SREG;
cli();
vitki_back_o=vitki;
vitki=vitki_back;
vitki_back=vitki_back_o;
SREG = oldSREG;
}
break;
case BTN_UP:
if(light<10){
light+=1;
} else if(light<100){
light+=10;
} else{
light+=25;
if(light>255){
light=255;
}
}
analogWrite(PWM_PIN,light);
break;
case BTN_DOWN:
if(light==255){
light-=5;
} else if(light>100){
light-=25;
} else if(light>10){
light-=10;
} else{
light-=1;
if(light<0){
light=0;
}
}
analogWrite(PWM_PIN,light);
break;
case BTN_LEFT:
if(!back_mod && vitki_back!=vitki){
back_mod=1;
backmod_timer=timer;
lcdref_flag=0;
lcd.setCursor(0, 1);
sprintf(vit_nom, " %04d", vitki_back);
lcd.print(vit_nom);
lcd.print(" ? ");
}else{back_mod=0;lcdref_flag=1;}
break;
case BTN_RIGHT:
if(back_mod){back_mod=0;lcdref_flag=1;}
break;
default:
break;
}
}
if(back_mod && timer-backmod_timer>10000){
back_mod=0;
lcdref_flag=1;
}
if(button==BTN_SELECT && timer-drop_timer>2000){
uint8_t oldSREG = SREG;
cli();
vitki_back=vitki;
vitki=0;
SREG = oldSREG;
if(vitki_old!=0){
write_int(10+addr,0);
write_int(12+addr,0);
write_int(14+addr,0);
vitki_old=0;
}
lcdref_flag=1;
lcd.setCursor(0, 0);
lcd.print(" C6POC! ");
delay(500);
lcd.setCursor(0, 0);
lcd.print(" HAMOTAHO: ");
}
if(select_flag && !button && timer-drop_timer<1000){
select_flag=0;
uint8_t oldSREG = SREG;
cli();
vitki_back=vitki;
SREG = oldSREG;
if(vitki!=vitki_old){
write_int(10+addr,vitki*(-1+2*dtc_f));
write_int(12+addr,vitki*(-1+2*dtc_f));
write_int(14+addr,vitki*(-1+2*dtc_f));
vitki_old=vitki;
}
if(light!=light_old){
EEPROM.write(0+addr,(uint8_t)light);
EEPROM.write(1+addr,(uint8_t)light);
EEPROM.write(2+addr,(uint8_t)light);
light_old=light;
}
lcd.setCursor(0, 0);
lcd.print(" COXPAHEHO!");
delay(500);
lcd.setCursor(0, 0);
lcd.print(" HAMOTAHO: ");
}
if(lcdref_flag){
lcdref_flag=0;
back_mod=0;
uint8_t oldSREG = SREG;
cli();
int v = vitki;
SREG = oldSREG;
lcd.setCursor(0, 1);
sprintf(vit_nom, " %04d", v);
lcd.print(vit_nom);
lcd.print(" ");
}
delay(10);
}
... и добавил:кондер наверно можно взять и больше. и возможно 10 ом гасящий резистор можно уменьшить, но это я уже хз, мне кажется он нужен чтоб защитить от броска тока при заряде кондера.
... и добавил:возможно, стоит завести отдельные яички памяти для аварийного сохранения, чтобы в случае если сохранилось что-то не то, можно было откатиться к более раннему ручному сохранению. но сперва надо потестировать в реальных условиях - может и не будет ниче глючить.
... и добавил:а еще думаю все таки сделать программнуюю защиту от дребезга для датчика с прерыванием. это и при плохом отключении должно помочь от глючных витков