Stránka 1 z 1

Přerušení programu

Napsal: 26 lis 2019, 16:34
od QRocky
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);
}

Re: Přerušení programu

Napsal: 26 lis 2019, 19:28
od gilhad
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



Re: Přerušení programu

Napsal: 27 lis 2019, 12:52
od kiRRow
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 ...