Přerušení programu

Nedaří se vám s projektem a nenašli jste vhodné místo, kde se zeptat? Napište sem.
Pravidla fóra
Tohle subfórum je určeno pro konzultaci ucelených nápadů, popřípadě řešení komplexnějších projektů, které opravdu není možné rozdělit na menší části.
Většinu problémů jde rozdělit na menší a ptát se na ně v konkrétních subfórech.
Odpovědět
QRocky
Příspěvky: 36
Registrován: 28 zář 2017, 16:30
Reputation: 0

Přerušení programu

Příspěvek od QRocky » 26 lis 2019, 16:34

Ahojte,

peru se s zatím nedostatečnou znalostí funkce přerušení. Mám program níže, který odečítá hodnoty ze dvou DHT senzorů a anemometru.

Ze smyčky loop volám funkce Vlhkosti a TeplotyDHT, které zobrazí naměřené hodnoty na displeji a na sériové lince. Potíž mi nastává s přerušením, kde se počítají pulzy z anemometru. Praxe je taková, že při každém pohybu se mi program přeruší a na displeji je takřka permanentně zobrazena jen hodnota z anemometru…

Chtěl bych funkci loop mít nějak takto:
Vlhkosti (VlhkostUvnitr, VlhkostVenku);
TeplotyDHT (TeplotaUvnitr, TeplotaVenku);
Hodnota anemometr;

Chci, aby se program přerušil jen pro počítání pulzů, ale na displeji aby se ty pulzy či rychlost zobrazily jen tehdy, když na ně přijde řada… Prosím o radu.

Tady celý program:


#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

Adafruit_SSD1306 display(-1);


#include "DHT.h"


// Promenna s poctem pulzu
volatile long pulzy = 0;

#define DHT1PIN 9 // DHT u displeje
#define DHT2PIN 7 // DHT venku

#define DHT1TYPE DHT11 // DHT 11
#define DHT2TYPE DHT22 // DHT 11

DHT dht1(DHT1PIN, DHT1TYPE);
DHT dht2(DHT2PIN, DHT2TYPE);

int zobrazeni = 2000; // prodleva pro zobrazeni


// Funkce preruseni pocita pulzy anemometru
void preruseni() {
pulzy++;
}

// Funkce casoveho preruseni nam rekne, ze je cas spocitat RPM
void preruseniCasovac() {
cli();
// Vypocitej pocet celych otocek za minutu
// Jedna otocka ma dva pulzy * 20, protoze
// tato funkce se vola kazde tri sekundy
int rpm = (pulzy * 20) / 2;
pulzy = 0;
sei();

Serial.print("Otacky: ");
Serial.print(rpm);
Serial.println(" RPM");
sei();




}

// Hlavni funkce setup se zpracuje po startu programu
void setup() {
// Nastaveni pinu anemometru a seriove linky

// initialize with the I2C addr 0x3C
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);

pinMode(2, INPUT);
Serial.begin(9600); // Puvodne z navodu anemometru 115200
// Nastartovani detekce preruseni na pinu anemometru
attachInterrupt(digitalPinToInterrupt(2), preruseni, FALLING);
// Nastaveni casovace
// Kazdych 300 000 000 us (3 sekundy) zavola funkci preruseniCasovac
Timer1.initialize(3e6);
Timer1.attachInterrupt(preruseniCasovac);




}


void loop() {
// Načtení a deklarace proměnných
int VlhkostUvnitr = DHTH1();
int VlhkostVenku = DHTH2();

int TeplotaUvnitr = DHTT1();
int TeplotaVenku = DHTT2();



// Poslání hodnot k zobrazení
Vlhkosti (VlhkostUvnitr, VlhkostVenku);
TeplotyDHT (TeplotaUvnitr, TeplotaVenku);







}

int DHTH1()
{

float h1 = dht1.readHumidity();
return h1;

}

int DHTH2()
{

float h2 = dht2.readHumidity();
return h2;

}


int DHTT1()
{
// Reading temperature or humidity takes about 250 milliseconds!
// Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
float t1 = dht1.readTemperature();
return t1;

}


int DHTT2()
{
float t2 = dht2.readTemperature();
return t2;

}



}




void Vlhkosti (int uvnitr, int venku)
{

Serial.println("");
Serial.print("Vlhkost uvnitr: ");
Serial.print(uvnitr);
Serial.print(" %");
Serial.println("");

Serial.print("Vlhkost venku: ");
Serial.print(venku);
Serial.print(" %");

display.clearDisplay();
// Display Text
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.print("Vlhkost int: ");
display.print(uvnitr);
display.print(" %");
display.display();

display.setCursor(0,10);
display.print("Vlhkost ext: ");
display.print(venku);
display.print(" %");
display.display();

if (uvnitr > venku)
{
display.setCursor(0,20);
display.print("Int vice o: ");
display.print(uvnitr - venku);
display.print(" %");
display.display();
}

if (venku > uvnitr)
{
display.setCursor(0,20);
display.print("Ext vice o: ");
display.print(venku - uvnitr);
display.print(" %");
display.display();
}

delay(zobrazeni);
}

void TeplotyDHT (int uvnitr, int venku)
{
Serial.println("");
Serial.print("Teplota uvnitr: ");
Serial.print(uvnitr);
Serial.print(" C");
Serial.println("");

Serial.print("Teplota venku: ");
Serial.print(venku);
Serial.print(" C");

display.clearDisplay();
// Display Text
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.print("Teplota int: ");
display.print(uvnitr);
display.print(" C");
display.display();

display.setCursor(0,10);
display.print("Teplota ext: ");
display.print(venku);
display.print(" C");
display.display();

if (uvnitr > venku)
{
display.setCursor(0,20);
display.print("Int vice o: ");
display.print(uvnitr - venku);
display.print(" %");
display.display();
}

if (venku > uvnitr)
{
display.setCursor(0,20);
display.print("Ext vice o: ");
display.print(venku - uvnitr);
display.print(" %");
display.display();
}

delay(zobrazeni);
}

Uživatelský avatar
gilhad
Příspěvky: 778
Registrován: 07 bře 2018, 11:22
Reputation: 0

Re: Přerušení programu

Příspěvek od gilhad » 26 lis 2019, 19:28

1) pouzij tag code /code, aby to bylo citelne (nemravne tlacitko nad editacnim polem, 5. zleva)
2) volat Serial z preruseni NENI dobry napad (a to ani kdyz predtim povolis preruseni)
3) zkus takoveto upravy:

Kód: Vybrat vše

// Promenna s poctem pulzu
volatile long pulzy = 0;
volatile int rpm; // pridej sem, pri inicializaci programu sse promenne nastavi na nulu samy, takze =0 neni potreba

Kód: Vybrat vše

// Funkce casoveho preruseni nam rekne, ze je cas spocitat RPM
void preruseniCasovac() {
cli(); // vypocet bude rychly
// Vypocitej pocet celych otocek za minutu
// Jedna otocka ma dva pulzy * 20, protoze
// tato funkce se vola kazde tri sekundy
rpm = (pulzy * 20) / 2; // VYHOZENO int - rpm je deklarovano vyse jako volatile a chceme ho tak pouzit
pulzy = 0;
// zbytek se bude resit jinde 
sei();
// 
// Serial.print("Otacky: ");
// Serial.print(rpm);
// Serial.println(" RPM");
// sei();

}

Kód: Vybrat vše

// Poslání hodnot k zobrazení
Vlhkosti (VlhkostUvnitr, VlhkostVenku);
TeplotyDHT (TeplotaUvnitr, TeplotaVenku);

// tady je napriklad to "jinde"
// a nekde tady zobrazime otacky
Serial.print("Otacky: ");
Serial.print(rpm);
Serial.println(" RPM");
// nebo to pekne zabalis do nejake funkce dle libosti



Uživatelský avatar
kiRRow
Příspěvky: 1151
Registrován: 07 kvě 2019, 07:03
Reputation: 0
Bydliště: Opava

Re: Přerušení programu

Příspěvek od kiRRow » 27 lis 2019, 12:52

nemůžu si pomoct, ale dle mne tam máš } navíc ... mezi definicí int DHTT2() a definicí void Vlhkosti (int uvnitr, int venku) ...

ten delay je zlo, raději bych zvolil metodu časování přes millis ... uložíš si čas, kdy jsi naposledy přepsal display a ten budeš porovnávat v loopu s millis() jestli je rozdíl větší než 2000ms ... pokud ano, přepíšeš displej a znovu si uložíš čas, kdys toto provedl. Přepis displeje bych řešil tím, že bych si pamatoval kterou stránku zobrazuji (0=teplota,1=vlhkost....2=rychlost). Pak bych volal funkci vykresliStranku(cisloStranky); ...proměná se nastaví na požadovanou hodnotu před voláním ... funkce by podle vstupního parametru zavolala správnou vykreslovací funkci ...

Odpovědět

Kdo je online

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