jak spravne pouzit interrupt?

Wiring, C++, C, Java, ...
Pravidla fóra
Toto subfórum slouží k řešení obecných otázek kolem programování (konstrukce, knihovny, alokace paměti, ...)
Odpovědět
Stepino
Příspěvky: 4
Registrován: 02 led 2018, 09:35

jak spravne pouzit interrupt?

Příspěvek od Stepino » 02 led 2018, 09:59

Ahoj,
zkousim svuj novy projekt, impulzem pro zacatek s Arduinem bylo prakticke vyuziti.

Zadani:
Potrebuji pustit tlacitkem ss motorek, ktery bude otacek navijeci civku. Civka na sobe ma 4 odrazky ke snimani otacek. jako snimac mam IR cidlo. po 16 otackach, chci aby se motorek vypnul a tim skoncil program.

moje potiz je, ze mi program funguje zatim tak ze bud roztocim motor a nenacitam pulsy, nebo nacitam pulsy , ale nejlze v ten moment pusti motorek.

Sanzil jsem se docilit funkcnosti pomoci attachinterrupt, pouzil jsem pin2 pro vstup z IR cidla, ale stejne mi funce interrupt nefunguje a IR cidlo nefunguje jako preruseni a nenacitaji se mi pulzy
motorek_rozbeh_ovladani_tlacitkem02_1.ino
(3.13 KiB) Staženo 210 x
EDIT:
asi spatne vkladam program, kdyz ho mam jen jako prilohu tak zkusim takto

Kód: Vybrat vše

#include <TM1637Display.h>
#define CLK 2
#define DIO 3

TM1637Display display(CLK, DIO);

int led = 13;     //   interni dioda - blika podle signalu IR prijimace
int IR = 2; //  cteni IR preruseni,snimac pulsu 
int tlacitko = A2; //pin s tlačítkem na start programu
int motorpin = 6;    // DC motorek pripojen na pin 6
int numb=0;          //display
int pres=0;          //display
const int pocetder=4 //pocet der po obvode
const int pocetotacek = 37.5
const int pocetmetru = 10

int ledPin = 7;       // pin, ke kterému je připojena LED   ktera se rozviti po 4 impulzech (znaci jeden obeh)
int IRInterrupt = 0;   // počítadlo impulzu
int buttonState = 0;         // současný stav tlačítka
int lastButtonState = 0;     // předchozí stav tlačítka

void setup() {
  pinMode(ledPin, OUTPUT);         // ukazatel dokoncene otacky
  pinMode(tlacitko, INPUT_PULLUP); //start tlacitko
  pinMode(led, OUTPUT);    // internal LED ukazuje ze IR cidlo bylo preruseno
  pinMode(IR, INPUT_PULLUP);// IR pin jako vstup.
  display.setBrightness(9); 
  attachInterrupt(0, CteniPulzu, CHANGE);
}

void loop() {
   zmackniTlacitko();
   motorstart();
   motorstop();
              }


void CteniPulzu()     {
 {
buttonState = digitalRead(IR);
    
    // porovnejte buttonState (stav tlačítka) s předchozím stavem
    if (buttonState != lastButtonState) {
        
        if (buttonState == LOW) {
             IRInterrupt++;
           }
    }
    
    lastButtonState = buttonState;
    
    
    // zapne LED po každých čtyřech impulzech
    
    if (IRInterrupt % pocetder == 0) {
        digitalWrite(ledPin, HIGH);
        
    } else {
        digitalWrite(ledPin, LOW);
            }
//

  }


// zobrazeni poctu sepnuti IR na display
if(digitalRead(IR)==HIGH){ 
  
  digitalWrite(led, HIGH);  // turn the LED on to indicate impulse
 
  while(1){
    if(digitalRead(IR)==LOW){ 
         
    digitalWrite(led, LOW);   // turn the LED off 
    break;                    //End of the while loop,Back to the main loop  
    }}
  }
 
 
  {
   display.setBrightness(0x0f);
   display.showNumberDec(numb,false);
   if(digitalRead(IRInterrupt % interval)==1)
   {
    if(pres==0)
   {
    numb++;
    pres=1;
      }
    }
     
   else
  {
    pres=0;
    }
 
  }
}

// --------------
void zmackniTlacitko()   {
if(digitalRead(tlacitko) == LOW)
    

// --------------
void motorstart()  {
     // fade in from min to max in increments of 5 points:
  //zapnuti motoru na tlacitko
  for (int fadeValue = 20 ; fadeValue <= 255; fadeValue += 1) {
    // sets the value (range from 0 to 255):
    analogWrite(motorpin, fadeValue);
    // wait for 100 milliseconds to see the dimming effect
    delay(50);
  }
}
// --------------
void motorstop()  {
      

// zpomaleni a vypnuti motoru
  // fade out from max to min in increments of 5 points:
  for (int fadeValue = 255 ; fadeValue >= 0; fadeValue -= 5) {
    // sets the value (range from 0 to 255):
    analogWrite(motorpin, fadeValue);
    // wait for 30 milliseconds to see the dimming effect
    delay(30);
  }
}


Stepino
Příspěvky: 4
Registrován: 02 led 2018, 09:35

Re: jak spravne pouzit interrupt?

Příspěvek od Stepino » 02 led 2018, 11:06

jeste par kosmetickych uprav.

a jeste v interrupt smycce - vetsina veci tam je spis pro debug, abych vedel ze dochazi k citani impulzu a je mozne blikani diod podle impulzu vynechat.

Kód: Vybrat vše

#include <TM1637Display.h>
#define CLK 3
#define DIO 4

TM1637Display display(CLK, DIO);

int led = 13;     //   interni dioda - blika podle signalu IR prijimace
int IR = 2; //  cteni IR preruseni,snimac pulsu 
int tlacitko = A2; //pin s tlačítkem na start programu
int motorpin = 6;    // DC motorek pripojen na pin 6
volatile int numb=0;          //display
volatile int pres=0;          //display
const int pocetder=4 //pocet der po obvode
const int pocetotacek = 37.5
const int pocetmetru = 10

int ledPin = 7;       // pin, ke kterému je připojena LED   ktera se rozviti po 4 impulzech (znaci jeden obeh)
volatile  int IRInterrupt = 0;   // počítadlo impulzu
volatile int buttonState = 0;         // současný stav tlačítka
volatile int lastButtonState = 0;     // předchozí stav tlačítka

void setup() {
  pinMode(ledPin, OUTPUT);         // ukazatel dokoncene otacky
  pinMode(tlacitko, INPUT_PULLUP); //start tlacitko
  pinMode(led, OUTPUT);    // internal LED ukazuje ze IR cidlo bylo preruseno
  pinMode(IR, INPUT_PULLUP);// IR pin jako vstup.
  display.setBrightness(9); 
  attachInterrupt(digitalPinToInterrupt(IR), CteniPulzu, CHANGE);
}

void loop() {
   motorstart();
      
   motorstop();
              }


void CteniPulzu()     {
 {
buttonState = digitalRead(IR);
    
    // porovnejte buttonState (stav tlačítka) s předchozím stavem
    if (buttonState != lastButtonState) {
        
        if (buttonState == LOW) {
             IRInterrupt++;
           }
    }
    
    lastButtonState = buttonState;
        
    // zapne LED po každých čtyřech impulzech
    
    if (IRInterrupt % pocetder == 0) {
        digitalWrite(ledPin, HIGH);
        
    } else {
        digitalWrite(ledPin, LOW);
            }


  }


// zobrazeni poctu sepnuti IR na display
if(digitalRead(IR)==HIGH){ 
  
  digitalWrite(led, HIGH);  // turn the LED on to indicate impulse
 
  while(1){
    if(digitalRead(IR)==LOW){ 
         
    digitalWrite(led, LOW);   // turn the LED off 
    break;                    //End of the while loop,Back to the main loop  
    }}
  }
    
  {
   display.setBrightness(0x0f);
   display.showNumberDec(numb,false);
   if(digitalRead(IRInterrupt % interval)==1)
   {
    if(pres==0)
   {
    numb++;
    pres=1;
      }
    }
     
   else
  {
    pres=0;
    }
   }
}

// --------------
void motorstart()   {
if(digitalRead(tlacitko) == LOW)
    
     // fade in from min to max in increments of 5 points:
  //zapnuti motoru na tlacitko
  for (int fadeValue = 20 ; fadeValue <= 255; fadeValue += 1) {
    // sets the value (range from 0 to 255):
    analogWrite(motorpin, fadeValue);
    // wait for 50 milliseconds to see the dimming effect
    delay(50);
  }
}

// --------------
void motorstop()  {
      
// zpomaleni a vypnuti motoru
  // fade out from max to min in increments of 5 points:
  for (int fadeValue = 255 ; fadeValue >= 0; fadeValue -= 5) {
    // sets the value (range from 0 to 255):
    analogWrite(motorpin, fadeValue);
    // wait for 30 milliseconds to see the dimming effect
    delay(10);
  }
}

petan
Příspěvky: 358
Registrován: 23 črc 2017, 10:19
Kontaktovat uživatele:

Re: jak spravne pouzit interrupt?

Příspěvek od petan » 02 led 2018, 20:51

Proč tam máš nulu? Zkus použít toto (jakou používáš desku? Ne všechny piny podporují interupt):

Kód: Vybrat vše

 
attachInterrupt(2, CteniPulzu, CHANGE);

//první parametr = číslo pinu
//druhý parametr = funkce, která se spustí při odchycení přerušení
//třetí parametr = je detekována náběžná hrana, sestupná hrana, nebo změna
Více o přerušení zde: https://www.arduino.cc/reference/en/lan ... interrupt/

---

Jinak, přijde mi, že program máš celkem zmatenej.
V loopu stále startuje a zastavuješ motor... Tlačítko hlídáš během přerušení, ... Zkus přemýšlet trochu jednodušeji.

Zkus tam nahrnout toto:

Kód: Vybrat vše

#define PinPreruseni 2
#define PinMotoru 3
#define PinTlacitko 5

byte rychlostMotoru;	//rychlost motoru 0-255
bool motorAktivni;
unsigned int pocetPulzu;	//počet načtených impulzů od motoru
unsigned int nastavenyPocetPulzu = 16;	//požadovaný počet pulzů


void setup() {
	pinMode(PinMotoru, OUTPUT);	//modrá
	pinMode(PinTlacitko, OUTPUT);	//zelená

	attachInterrupt(PinPreruseni, CteniPulzu, RISING);	//přerušení pro čidlo
	attachInterrupt(PinTlacitko, PozadavekStartu, RISING);	//přerušení pro tlačítko
}

void CteniPulzu() {
	//tohle se spustí při vytvoření impulsu - přerušení
	pocetPulzu++;	//prostě jenom přičti číslo
}

void PozadavekStartu() {
	//tohle se spustí při stisku tlačítka - přerušení
	if (!motorAktivni) {
		//pokud není motor spuštěn
		pocetPulzu = 0;	//vynuluj počet impulzů
		motorAktivni = true;	//zapni motor pičo
	}
	
}

void loop() {
	if (pocetPulzu >= nastavenyPocetPulzu) {
		//motor už natočil požadovaný počet pulzů
		motorAktivni = false;	//zastav motor
	}

	if (motorAktivni) {
		//pokud má být motor aktivní, tak zrychluj
		MotorStart();
	}
	else {
		//pokud ne, tak zpomaluj
		MotorStop();
	}

	delay(50); //zpoždění aby bylo vidět zpomalování motoru (šlo vy to vařešit daleko elegantněji)
}

void MotorStart() {
	//rozjeď motor
	for (rychlostMotoru; rychlostMotoru <= 255; rychlostMotoru++) {
		analogWrite(PinMotoru, rychlostMotoru);
	}
}

void MotorStop() {
	//zastav motor
	for (rychlostMotoru; rychlostMotoru > 0; rychlostMotoru--) {
		analogWrite(PinMotoru, rychlostMotoru);
	}
}

Jedno přerušení čeká na stisk tlačítka, druhé na impulzy od snímače. Po stisku tlačítka se motor zapne (se zrychlováním; vynuluje se počet impulzů), po správném počtu pulzů od čidla zase začne zpomalovat. Nelze ho zastavit předčasně tlačítkem...

Je to jen takovej nástřel. Nezkoušel jsem to.

petan
Příspěvky: 358
Registrován: 23 črc 2017, 10:19
Kontaktovat uživatele:

Re: jak spravne pouzit interrupt?

Příspěvek od petan » 02 led 2018, 20:57

Jo a ještě jsem si všiml, že přiřazuješ do proměnné INTEGER číslo s desetinným místem!
INT je celočíselní proměnná. Bacha na to, takhle vznikají matoucí a blbě dohledatelný chyby!

Kód: Vybrat vše

const int pocetotacek = 37.5
Čísla pinů je lepší přiřazovat slovem #define. Né že by to nějak vadilo, ale nezaplácáváš si paměť arduina zbytečnou proměnnou (né že by ti to vadilo). Slovo za #define se už v překladači nahradí tím dalším parametrem, takže to funguje, jako kdyby si tam zadal přímo ten text.

Kód: Vybrat vše

#define TotoJeHustyText A2

//všude, kde se v programu objeví "TotoJeHustyText" se při překladu napíše "A2"

Stepino
Příspěvky: 4
Registrován: 02 led 2018, 09:35

Re: jak spravne pouzit interrupt?

Příspěvek od Stepino » 04 led 2018, 06:41

Ahoj, děkuji za podněty.

Hned jak přijedu domů z práce zkusím poladit.


Dám sem vědět jak jsem dopadl

Stepino
Příspěvky: 4
Registrován: 02 led 2018, 09:35

Re: jak spravne pouzit interrupt?

Příspěvek od Stepino » 04 led 2018, 10:36

pocet otacek jsem upravil na float

attachinterrupt dle arduino uno znamena 0 ze na pinu2 ocekava interrupt

#define zmenim vecer - diky za tip

chybela mi logika kontroly zda motor bezi nebo nebezi.

snazil jsem se jeste vyhnout funkci delay, ktera v dobe cekani nedela nic jineho - tudiz dle logiky neukazuje kolik nacetl impluzu

petan
Příspěvky: 358
Registrován: 23 črc 2017, 10:19
Kontaktovat uživatele:

Re: jak spravne pouzit interrupt?

Příspěvek od petan » 05 led 2018, 06:57

Stepino píše:
04 led 2018, 10:36
snazil jsem se jeste vyhnout funkci delay, ktera v dobe cekani nedela nic jineho - tudiz dle logiky neukazuje kolik nacetl impluzu
Interrupt přeruší i příkaz delay.

Odpovědět

Kdo je online

Uživatelé prohlížející si toto fórum: Žádní registrovaní uživatelé a 1 host