Wpis z mikrobloga

Mam problem z poniższym kodem. Program dla prostej maszyny stanowej, jeden przycisk, jedna dioda. Jeżeli wciśniemy przycisk, to dioda świeci 3s, następnie 1s przerwy, świecenie 2s i koniec, wracamy do startu. Pierwsze przecenie można przerwać - jeżeli puścimy klawisz. Natomiast, jeżeli puścimy klawisz w trakcie przerwy lub drugiego świecenia, cykl musi dobiec do końca.
Program kompiluje się, odpala, natomiast dioda świeci tak jak chce, a nie tak, jak powinna.
Ktoś ma jakiś pomysł? Ew. mogę wrzucić rozrysowane grafy stanów, normalny i dla mikro.
#arduino

//KL - klwaisz; LD - dioda - tim - timer
//st1,2,3 start timera 1,2,3s,
//tabPS - pole skoku, tabPW - pole warunku,
//tabPA - pole adresu
char KL=7, LD=8, tim, pc, xw, st1, st2, st3;
char tab
PS[]={0, 12, 8, 2, 0, 9, 8, 8, 0, 0, 8, 8};
char tabPW[]={2, 1, 3, 1, 3, 1, 4, 5, 6, 0, 2, 0};
char tab
PA[]={0, 0, 10, 0, 4, 0, 1, 6, 8, 0, 1, 0};

void setup()
{
pinMode(KL, INPUT);
pinMode(LD, OUTPUT);
}
void loop()
{
//digitalWrite(LD)=(tabPS[pc]&8)?HIGH:LOW;
if(tab
PS[pc]&8)digitalWrite(LD, HIGH);
else digitalWrite(LD, LOW);
st3=(tabPS[pc]&4)?1:0;
st1=(tab
PS[pc]&2)?1:0;
st2=(tabPS[pc]&1)?1:0;
switch(tab
PW[pc])
{
case 0: xw=0; break;
case 1: xw=1; break;
case 2: xw=digitalRead(KL); break;
case 3: xw=!tim; break;
case 4: xw=!(!tim&&!digitalRead(KL)); break;
case 5: xw=!tim&&digitalRead(KL); break;
case 6: xw=!digitalRead(KL); break;
}
if(xw)++pc;
else pc=tab_PA[pc];
if(st3) tim=3000;
else if(st2) tim=2000;
else if(st1) tim=1000;
if(tim) --tim;
delay(1); // delay in between reads for stability
}
  • 9
@Wyszynkowski: Analogiczny program na zwykłej maszynie stanowej, działa jak powinien.
int KL=7, KL1, LD=8, tim, stan=1;
void setup()
{
pinMode(KL, INPUT);
pinMode(LD, OUTPUT);
}
void loop()
{
switch(stan)
{
case 1: digitalWrite(LD, LOW);
if(digitalRead(KL)&&!KL1){ tim=3000; stan=2;}
break;
case 2: digitalWrite(LD, HIGH);
if(!tim&&digitalRead(KL)){ tim=1000; stan=3;}
else if(!digitalRead(KL)) stan=1;
break;
case 3: digitalWrite(LD, LOW);
if(!tim){ tim=2000; stan=4;}
break;
case 4: digitalWrite(LD, HIGH);
if(!tim&&!digitalRead(KL)) stan=1;
else if(!tim&&digitalRead(KL)) stan=5;
break;
case 5: digitalWrite(LD, LOW);
if(!digitalRead(KL))
@Wyszynkowski: Tak sobie rzuciłem okiem na kod (taki nawyk z pracy ;-)), maszyna stanu ok, logiczna czytelna, ale też przypadek jest prosty ;-)

Z metodyki "automatykowej" jestem zielony jak szczypiorek na wiosnę dlatego mam pytanie, w każdym stanie, na początku ustawiasz wyjście (digitalWrite(...)) nawet jeżeli wiesz, że stan się nie zmienił, np. "case 1" musi się wykonać 3000 razy i za każdym razem ustawiasz "LOW". Z tego co wiem to Arduino
@kwanty: Przypadek jest prosty, bo chciałem to odpalić na prostszym przykładzie, żeby później cisnąć trudniejsze :)

Ustawianie wyjść w przejściu stanów czy na początku stanów nie będzie problemem. Pierwszy case nie wykona się 3000 razy, tyle razy wykona się Case 2 - zauważ, że 3000 inicjujemy właśnie w przejściu z 1 do 2.
Tak zostałem nauczony, tak też zawsze robiłem na czystych AVRach. Nie wiem ile szybciej działałby program, nigdy o
@Wyszynkowski:

Ustawianie wyjść w przejściu stanów czy na początku stanów nie będzie problemem. Pierwszy case nie wykona się 3000 razy, tyle razy wykona się Case 2 - zauważ, że 3000 inicjujemy właśnie w przejściu z 1 do 2.


ok, racja to się tyczy następnych stanów

Zauważ, że KL1 w przypadku wykonywania switcha jest równy wartości KL z poprzedniej pętli.


ok, teraz to widzę, program "wisi" na case 1: dopóki nie zostanie
@kwanty: Nie, przejdzie jeden cykl w 1ms i w następnym już będzie znać swoją wartość :) Tak samo jak w pierwszym programie który wrzuciłem nie inicjalizuję pc. Drugi program, ten w komentarzu działa bez zarzutu, natomiast ten pierwszy nie działa poprawnie niestety.