avstudsning

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: avstudsning

Inlägg av sodjan »

OK.
Det förklarade ju det hela bra.
En PIC kan inte mäta ström direkt, så jag antar att
det finns någon mer hårdvara på ingångarna, men det
kanske inte spelar någon roll för resten. :-)

Knappen är alltså en "larmåterställning" kombinerat med en
testfunktion. I "Del 2" så behöver man så klart se till att man
inte direkt går ur testfunktionen p.g.a en kontaktstuds, men det
har du ju fixat med en liten fördröjning.

När man sedan släpper knappen så spelar eventuella studsar inte
lika stor roll, den kommer bara att köra reset/test lite snabbt
en eller ett par extra gånger.

En sak som jag ser dock...

Kan man köra testen av givarna även då det inte finns något larm?
D.v.s har du någon avkänning av knappen i den *första* loopen där
du scannar av ingångarna ? Det kan ju finnas anledning att kunna testa
givarna även (eller speciellt) då det inte finns något larm.
Användarvisningsbild
persika
EF Sponsor
Inlägg: 1541
Blev medlem: 31 juli 2006, 22:14:37
Ort: Österlen, Skåne

Re: avstudsning

Inlägg av persika »

sodjan:
>har du någon avkänning av knappen i den *första* loopen där
>du scannar av ingångarna ?

Ja, det finns avkänning av knappen i första loopen, precis som du tänker. Jag bara utelämnade den i den sista beskrivningen, man kan se den om man lusläser koden.

Kod: Markera allt

      if ( KnappTryckt() )
         goto AnslutTest;
Jag har använt goto för att hoppa mellan de olika program delarna. Det anses ju vara ful-programmering, men i detta fall tyckte jag det var enklare, blev väldigt klumpigt annars.
Användarvisningsbild
persika
EF Sponsor
Inlägg: 1541
Blev medlem: 31 juli 2006, 22:14:37
Ort: Österlen, Skåne

Re: avstudsning

Inlägg av persika »

Varför 5ms före avläsning ?

Om man tänker sig ett program som räknar upp en variabel vid varje knapptryckning, så här:

Kod: Markera allt


//--------------Huvudprogram--------------
while (1)
  {
  while not  Knapptryckt()  // grön, vänta tills knapp trycks in
    ;

  variabel = variabel + 1;

  while Knapptryckt()  // blå, vänta tills knapp släppts
    ;
  }


//--------------Subrutin-------------------
int Knapptryckt()  
  {
  Tidms(5);            // gul
  return KnappPinne;   // röd
  }
Bifogar även en bild som visar programkörningen över tid.

Jag kan inte få det till annat än att de 5 ms har en avstudsande inverkan, om inte, förklara för mig.
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Användarvisningsbild
AndersG
EF Sponsor
Inlägg: 9120
Blev medlem: 25 februari 2008, 17:10:58
Ort: Mariehamn
Kontakt:

Re: avstudsning

Inlägg av AndersG »

I krånglar till det... Lägg en 100n konding över knappen, eller använd den synnerligen eleganta rutin jag länkade till, tidigare.
Användarvisningsbild
Icecap
Inlägg: 26650
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: avstudsning

Inlägg av Icecap »

persika: Fördröjningen har ingen betydelse då du inte läser före och efter och jämför. Det enda fördröjningen ger är ett långsammare program, inget annat.

Men om du läser först, väntar 5ms och läser igen och jämför de två avläsningar och ser till att båda måste vara aktiva innan en knapptryckning kan anses vara aktuell, då har du en avstutsning.
Användarvisningsbild
persika
EF Sponsor
Inlägg: 1541
Blev medlem: 31 juli 2006, 22:14:37
Ort: Österlen, Skåne

Re: avstudsning

Inlägg av persika »

Förstår inte.

I bilden jag gjort ser man ju i ena fallet kommer variablen att räknas upp till 3 och i andra fallet med fördröjningen till 1, alltså har studsarna tagits bort!
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: avstudsning

Inlägg av sodjan »

OK.
Men, finns det någon räknare i detta fall?
Vad har "avstudsningen" för funktion (i detta fall)?

Det är klart att man kan ha avstudsning på knappen
om man vill, men jag ser inte vad det gör för skada
om man inte har det. Det blir kanske några extra
turen mellan "steg1" och "steg2", men det kommer
knappast att märkas.

Diskuterar vi just denna specifika applikation eller
diskuterar vi avstudsning mer generellt?
Användarvisningsbild
persika
EF Sponsor
Inlägg: 1541
Blev medlem: 31 juli 2006, 22:14:37
Ort: Österlen, Skåne

Re: avstudsning

Inlägg av persika »

Det skulle jag sagt, detta senaste är generellt.
Användarvisningsbild
Icecap
Inlägg: 26650
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: avstudsning

Inlägg av Icecap »

Såklart kommer en räknare som räknar till mer än 1 om knappen är påverkat och som nollar räknaren när knappen INTE är påverkat att fungera som debounce! ingen snack om det och det är ju essensen av alla råd om debounce. Hur man sedan integrerar denna räknare, om det är en separat funktion med en timer-interrupt eller liknande beror mest på programmeringsteknik och krav på svarstider osv.

Själv använder jag som tidigare skrivit en timer till att ge "systeminterrupt" som då kan användas till olika saker. En av dessa är "alltid" avläsning och avstutsning av knappar och (om det finns och behövs) sensorer. Sedan sparas de avstutsade indikationer i variabler, då kan "huvudprogrammet" läsa dom och är det då indikerat '1' kan det räkna med att det är vad som gäller.

Fördelen är att jag alltid vet vilka villkor och tider som gäller för knappar och sensorer, ingen delay() behöver utföras då interrupten gör sitt jobb och sedan "försvinner", alltså kör hela programmet snabbare och finns det kritiska saker (nödstopp?) kan interruptrutinen utföra panikåtgärden direkt om det behövs.

Tar vi detta projekt som exempel kan man utöka init() till att innehålla:

Kod: Markera allt

OPTION = 0x86; // Set interrupt frekvens till 30,5Hz
TMR0 = 0; // Start på noll
INTCON = 0x90; // Tillåter Timer0 interrupt
Sedan får du lägga in följande också:

Kod: Markera allt


#define Knapp_1 0x04
typedef unsigned char BYTE;

volatile BYTE Key_Pressed;
BYTE Key_Used;

void interrupt(void)
{
#define KEY_BITS Knapp_1 /* bara en knapp just nu, kan dock expanderas i andra projekt */
static BYTE Previous, Used;
BYTE Now;
T0IF = 0; // Nolla interruptflaggan
// Now = ~PORTA & KEY_BITS; // Använd denna rad om knapptryckningen ger en nolla
Now = PORTA & KEY_BITS; // Använd denna rad om knapptryckningen ger en etta
if(Previous == Now) Key_Pressed = Now & ~Used; // Kopiera bitmönster från knapptryckningen
else if(!Now) Key_Pressed = 0; // Om ingen knapp är tryckt ska det nollas
Previous = Now; // Kom ihåg hur det var
Used = Now; // Kom ihåg om knappen är rapporterat
}
Då så, på detta sätt kommer interruptrutinen att kolla knapp-porten 30 gg/sek helt utan delay(). Är det två avläsningar efter varandra som ger identisk värde kommer detta värde att skrivas in i Key_Pressed, helt utan att du behöver göra något.

Det enda du behöver kolla i detta projekt är om Key_Pressed är noll eller icke-noll Alltså kommer din koll att se ut som:
if(Key_Pressed)
goto AnslutTest;

OBS: Denna rutin ger bara en "knapp tryckt" eller inte. Om en knapptryckning ska utlösa en grej när man trycker på den och bara en gång per tryckning kan man utöka det hela lite vid att helt enkelt att skriva en nolla till Key_Pressed när det som ska utlösas av knapptryckningen är påbörjat (eller avslutat).

Då kan man trycka in knappen och hålla den inne en halvtimme utan att det sker igen och igen.

EDIT: såg i koden att du låter den vänta 3 sek (anslutningstest) och om du utökar interruptrutinen lite kan du få detta att fungera enkelt:

Kod: Markera allt

typedef unsigned int WORD;

volatile WORD Delay_Counter;

void Delay(WORD Timer_Value)
{
Delay_Counter = Timer_Value; // Sätt värde, 30,5 steg per sekund.
while(Delay_Counter); // Vänta på att den blir noll
}

void interrupt(void)
{
#define KEY_BITS Knapp_1 /* bara en knapp just nu, kan dock expanderas i andra projekt */
static BYTE Previous, Used;
BYTE Now;
T0IF = 0; // Nolla interruptflaggan
// Now = ~PORTA & KEY_BITS; // Använd denna rad om knapptryckningen ger en nolla
Now = PORTA & KEY_BITS; // Använd denna rad om knapptryckningen ger en etta
if(Previous == Now) Key_Pressed = Now & ~Used; // Kopiera bitmönster från knapptryckningen
else if(!Now) Key_Pressed = 0; // Om ingen knapp är tryckt ska det nollas
Previous = Now; // Kom ihåg hur det var
Used = Now; // Kom ihåg om knappen är rapporterat
if(Delay_Counter) Delay_Counter--; // Räkna ner om det behövs
}
Jag använder mycket ofta detta sätt, då kan jag skapa fler timers som kan användas på fler sätt. Om jag t.ex. vill att en funktion ska ha en viss starttid kan jag - i main-loopen - sätta en flagga som betyder att programmet egentligen ska hålla på med vaddetnuär MEN om jag samtidig med att flaggan sätts laddar Delay_Counter med ett värde kan jag skriva såhär:

Kod: Markera allt

BYTE Sequence;

Main-loop:
...
if(Key_Pressed)
  {
  Sequence = 1; / Indikera att sekvensen ska köra
  Key_Pressed = 0; // Knapptryckningen är använd, nolla den
  Motor = 1; // Slå på en tänkt motor som måste få 10 sek att komma upp i varv
  Delay_Counter = 305; // Värdet för 10 sek
  }
if(Sequence && !Delay_Counter)
  {
  switch(Sequence)
    {
    case xx osv.
  ... Gör något i sekvensen - men BARA om "Delay_Counter" är noll.
  När sekvensen är klar är det bara att återställa Sequence till noll och ingen sekvens utförs
  På detta vis kan programmet göra saker i viss ordning med viss tid mellan varje sak.
    }
  }
}
Senast redigerad av Icecap 18 april 2013, 14:46:13, redigerad totalt 1 gång.
Användarvisningsbild
persika
EF Sponsor
Inlägg: 1541
Blev medlem: 31 juli 2006, 22:14:37
Ort: Österlen, Skåne

Re: avstudsning

Inlägg av persika »

Räknaren som är benämnd "variabel" är bara till för att visa om avstudsningen fungerat eller ej, så den har inget med själva avläsningen av kanppen och dess avstudsing. Det kunde lika gärna vara något annat som utfördes i huvudprogrammet, som är känsligt för hur många gånger det utförts.
Skriv svar