Inkrementacja zmiennej

Masz problem, z którym nie możesz sobie poradzić? Pisz śmiało!
hazi18
Młodszy majsterkowicz
Posty: 23
Rejestracja: 18 paź 2019, 20:36

Re: Inkrementacja zmiennej

Post autor: hazi18 » 23 lis 2019, 15:19

Po Twoich uwagach wygląda to następująco

Kod: Zaznacz cały

int przekaznik=7;
#include "DHT.h"
#include <TM1637Display.h>
#define DHTPIN 2     // what pin we're connected to
#define DHTTYPE DHT22   // DHT 22  (AM2302)
DHT dht(DHTPIN, DHTTYPE);
const int CLK = 4; //Set the CLK pin connection to the display
const int DIO = 3; //Set the DIO pin connection to the display
const int CLK1 = 6; //Set the CLK pin connection to the display
const int DIO1 = 5; //Set the DIO pin connection to the display
TM1637Display tm1637a(CLK, DIO);  //set up the 4-Digit Display.
TM1637Display tm1637b(CLK1, DIO1);  //set up the 4-Digit Display.

void setup(void)
{
  pinMode(przekaznik,OUTPUT);  // ustawienie pinu jako wyjście
  digitalWrite(przekaznik,LOW); // ustawienie na nim stanu niskiego
  tm1637a.setBrightness(0x0a);  //set the diplay to maximum brightness
  tm1637b.setBrightness(0x0a);  //set the diplay to maximum brightness
  Serial.begin(9600); //Begin serial communication
  dht.begin();

}

void loop(void)
{ 
  float h = dht.readHumidity();
  float t = dht.readTemperature();
  pinMode(8, OUTPUT);
    Serial.print("Humidity: "); 
    Serial.print(h);
    Serial.print(" %\t");
    Serial.print("Temperature: "); 
    Serial.print(t);
    Serial.println(" *C");

if (dht.readTemperature()>=36.5)  // wywołanie funkcji warunkowej
  {
    digitalWrite(przekaznik,HIGH);  // włączenie przekaźnika  
  }

else  // wywołanie funkcji warunkowej
  {
   digitalWrite(przekaznik,LOW);  // wyłączenie przekaźnika
  } 
      tm1637a.showNumberDec(h); //Display the Variable value;
      tm1637b.showNumberDec(t); //Display the Variable value; 
     
      digitalWrite(8, LOW);
      delay(1000);
      digitalWrite(8, HIGH);
      delay(1000);
}
Inkrementację chciałem użyć w drugim projekcie, gdzie ustalałbym temperaturę wiatraka ( o którym pisałem post wcześniej) ale posługując się jako bazę ten program. Chodzi o to że mam problem z napisaniem inkrementacji tak, aby zapamiętało moje zmiany, czyli dziś ustawiam, że wiatrak ma się włączać przy 25 stopniach i wyłączać przy 23, a jutro chcę żeby się włączył przy 23 stopniach ale wyłączył przy 21 ( myślę czy się nie da jednocześnie ustawić inkrementacji/ dekrementacji dla obu zmiennych dla temp. włączenia i wyłączenia? Czyli stała różnica 2 stopnie)
Domyślam się, że do ustawiania zmiennej nie mogę przypisać stałej temperatury jak to było dla inkubatora. Więc jeśli ustawię zmienną na początek a=25 jako temperaturę kiedy wiatrak ma się włączać to jak zrobić, aby program pamiętał, że ja zmniejszyłem ją o 2 stopnie i ciągl będzie wiatrak włączał się przy 23 stopniach? Bo opcja wyłączania wiatraka to zrobię na zasadzie a-2 (nie wiem czy dobrze myślę).

Co miesiąc do wygrania nagrody o wartości ponad 1600 zł!


Awatar użytkownika
Marhef
Złota rączka
Posty: 1188
Rejestracja: 18 lis 2011, 02:18

Re: Inkrementacja zmiennej

Post autor: Marhef » 23 lis 2019, 20:53

Przede wszystkim musisz pozbyć się delay(). Można to zrobić używając millis(), ale to trochę trudniejsze.
Idea działania jest taka:
- funkcja loop() działa tak krótko, jak się tylko da
- nie ma delay() (zamiast nich millis())
- za każdym razem w pętli sprawdzasz stan przycisku

Jeszcze kilka uwag do kodu:
1) ustawienie pinów masz w sekcji setup() (dobrze), oprócz pinu od diody
2) masz zadeklarowany pin od przekaźnika, zrób tak samo z pinem od diody
3) deklaracje zmiennych i stałych daj pod #include i #define
Reszta jest ok. No, oprócz delay(). Przerabiamy, żeby ich nie było?
Dodajemy histerezę? I obsługę przycisku?

I dobrze myślisz, ale jeśli chcesz, żeby program zapamiętał nastawioną temperaturę po zaniku zasilania, musimy jeszcze ogarnąć pamięć EEPROM
hazi18
Młodszy majsterkowicz
Posty: 23
Rejestracja: 18 paź 2019, 20:36

Re: Inkrementacja zmiennej

Post autor: hazi18 » 25 lis 2019, 18:41

Hej, dzieki wielkie za uwagi :)
coś czytałem o Delay(), ze ta funkcja nie jest niby taka dobra. Czy zastępując delay() milis'em() osiągnę ten sam efekt? Jeśli programowi ma pomóc użycie milis() w porównaniu do delay() to jak najbardziej jestem za tym aby to zmienić. Pytanko jak zadeklarować zmienna a dla przycisku, który ma zmieniać jej wartość? chciałbym aby dla temperatury było to 0.1 czyli float ale nie wiem czy użycie float jest prawidłowe w tym scenariuszu :) Co masz na myśli ogarnąć EEPROM? Trzeba będzie coś dodatkowo zrobić aby ta zmienna została zapamiętana?
Czytam o milis() i widzę, że jest o wiele więcej kombinowania niż z delay(). Ile trzeba kodu, zmiennych żeby milis() liczyło od startu Arduino i co sekundę mrugało diodą ( tak jakbym chciał żeby widać, że program działa)
Kod ze strony Forbot.pl

Kod: Zaznacz cały

#define LED1 3
int stanLED1 = LOW;

unsigned long aktualnyCzas = 0;
unsigned long zapamietanyCzasLED1 = 0;

void setup(){
  Serial.begin(9600);
  pinMode(LED1, OUTPUT);
}

void loop(){
  //Pobierz liczbe milisekund od startu
  aktualnyCzas = millis();
  
  //Jeśli różnica wynosi ponad 1 sekundę
  if (aktualnyCzas - zapamietanyCzasLED1 >= 1000UL) {
    //Zapamietaj aktualny czas
    zapamietanyCzasLED1 = aktualnyCzas;
    //Zmieniamy stan diody na przeciwny
    stanLED1 = !stanLED1;
    //ustawiamy nowy stan na diodzie
    digitalWrite(LED1, stanLED1);
  }
}
Narazie zacząłem się bawić z kodem do wiatraka, z tym sprawdzaniem przycisku w loop coś mi nie wychodzi... przekaźnik nie włącza i nie wyłącza się wtedy kiedy powinien.

Kod: Zaznacz cały

#include "DHT.h"
#include <TM1637Display.h>
#define DHTPIN 2     // what pin we're connected to
#define DHTTYPE DHT22   // DHT 22  (AM2302)
DHT dht(DHTPIN, DHTTYPE);
const int CLK = 4; //Set the CLK pin connection to the display
const int DIO = 3; //Set the DIO pin connection to the display
TM1637Display tm1637a(CLK, DIO);  //set up the 4-Digit Display.
int przekaznik=7;
int dioda=8;
float a=30;
float b;
const int przycisk = 3;  // Definicja pinu do którego podłączony jest przycisk
void setup(void)
{
  pinMode(przekaznik,OUTPUT);  // ustawienie pinu jako wyjście
  digitalWrite(przekaznik,LOW); // ustawienie na nim stanu niskiego
  pinMode(dioda, OUTPUT);
  pinMode(przycisk, INPUT);      // Ustawienie pinu 3 jako wejście
  tm1637a.setBrightness(0x0a);  //set the diplay to maximum brightness
  Serial.begin(9600); //Begin serial communication
  dht.begin();

}

void loop(void)
{ 
  float t = dht.readTemperature();
    Serial.print("Temperature: "); 
    Serial.print(t);
    Serial.println(" *C");

    
if (dht.readTemperature()>=a)
{
  digitalWrite(przekaznik,HIGH);
}
if (dht.readTemperature()<=(a-2))
{
  digitalWrite(przekaznik,LOW);
}
    
    if (digitalRead(przycisk) == LOW)  // Sprawdzamy czy przycisk nie jest wciśnięty
     {            
      }
   else (digitalRead(przycisk) == HIGH); // W innym przypadku 
     {                                             
    a=b+0.1;
    }

      tm1637a.showNumberDec(t); //Display the Variable value;
     
      digitalWrite(dioda, LOW);
      delay(1000);
      digitalWrite(dioda, HIGH);
      delay(1000);
}
Awatar użytkownika
Marhef
Złota rączka
Posty: 1188
Rejestracja: 18 lis 2011, 02:18

Re: Inkrementacja zmiennej

Post autor: Marhef » 26 lis 2019, 10:37

Zacznę od kodu z Forbota. Z krótkim wyjaśnieniem.
Delay jest złą funkcją, ponieważ blokuje działanie programu. Znaczy, program nie reaguje na nic innego.
hazi18 pisze:
25 lis 2019, 18:41
Czy zastępując delay() milis'em() osiągnę ten sam efekt?
Tak. Ale nie możesz po prostu skasować delay i wstawić millis. Funkcja millis() zwraca czas, który minął od uruchomienia programu (w milisekundach).
hazi18 pisze:
25 lis 2019, 18:41
Czytam o milis() i widzę, że jest o wiele więcej kombinowania niż z delay(). Ile trzeba kodu, zmiennych żeby milis() liczyło od startu Arduino i co sekundę mrugało diodą ( tak jakbym chciał żeby widać, że program działa)
Nie przesadzaj, nie ma tego tak dużo. Masz jedną zmienną więcej (w przykładzie są dwie, ale druga nie jest potrzebna). Poniżej porównanie kodu z delay i millis.
Delay():

Kod: Zaznacz cały

#define LED1 3
int stanLED1 = LOW;

void setup(){
  pinMode(LED1, OUTPUT);
}

void loop(){
  delay(1000);  
  stanLED1 = !stanLED1;
  digitalWrite(LED1, stanLED1);
  }
}
Millis:

Kod: Zaznacz cały

#define LED1 3
int stanLED1 = LOW;

unsigned long zapamietanyCzasLED1 = 0;

void setup(){
  pinMode(LED1, OUTPUT);
}

void loop(){
  if (millis() - zapamietanyCzasLED1 >= 1000UL) {
    zapamietanyCzasLED1 = millis();
    stanLED1 = !stanLED1;
    digitalWrite(LED1, stanLED1);
  }
}
Masz dwie linijki kodu więcej. A korzyści olbrzymie :)
hazi18 pisze:
25 lis 2019, 18:41
Co masz na myśli ogarnąć EEPROM? Trzeba będzie coś dodatkowo zrobić aby ta zmienna została zapamiętana?
Zmienne w programie są przechowywane w pamięci RAM. Jeżeli zniknie napięcie zasilania, zostaną skasowane. Na początku programu przypisujesz wartości zmiennym. Więc ustawisz zmiennym wartości początkowe.
Pamięć EEPROM nie jest kasowana - możesz tam przechować wartości, które nie chcesz, żeby się zmieniały. Czyli na przykład wartość temperatury do załączenia/wyłączenia przekaźnika.
Potrzeba kilku dodatkowych linijek, żeby wykorzystać pamięć EEPROM. Ale zostawmy to na razie. Najpierw przycisk ;)

Zostawiłeś funkcje delay(). Więc, żeby przycisk zadziałał, musisz "wstrzelić" się w program poza tymi funkcjami. Czyli musisz go przytrzymać przez przynajmniej 2 sekundy. Pokażę Ci, jak zrobić to samo, ale wykorzystując millis do mrugania LEDem.
Brakuje mi jeszcze jednego wyświetlacza. Na którym wyświetlisz ustawioną temperaturę.
hazi18 pisze:
25 lis 2019, 18:41
Pytanko jak zadeklarować zmienna a dla przycisku, który ma zmieniać jej wartość? chciałbym aby dla temperatury było to 0.1 czyli float ale nie wiem czy użycie float jest prawidłowe w tym scenariuszu
Typ float nie jest dobry. Ale na początek wystarczy ;) Jak już opanujesz zmianę temperatury i zapisywanie jej w pamięci EEPROM, to zmienimy i float.
Najpierw skomentuję kod, odnosząc się do wybranych linijek.

Kod: Zaznacz cały

float a=30;
30 nie jest wartością typu float. To wartość całkowita. Powinieneś zapisać jako

Kod: Zaznacz cały

float a = 30.0;

Kod: Zaznacz cały

float b;
Po co ta zmienna?

Kod: Zaznacz cały

pinMode(przycisk, INPUT);
Jak podłączyłeś przycisk? Bo osobiście wolę wersję, gdzie piszesz w kodzie:

Kod: Zaznacz cały

pinMode(przycisk,INPUT_PULLUP)
i podłączasz przycisk pomiędzy wejście i GND (i wtedy w kodzie sprawdzasz, czy stan przycisku jest niski - pokażę w mojej wersji kodu)

Kod: Zaznacz cały

if (dht.readTemperature()>=a)
{
  digitalWrite(przekaznik,HIGH);
}
if (dht.readTemperature()<=(a-2))
{
  digitalWrite(przekaznik,LOW);
}
Dlaczego odczytujesz kilka razy temperaturę? Przecież odczytałeś na początku pętli

Kod: Zaznacz cały

float t = dht.readTemperature();
Korzystaj z wartości w zmiennej t.

Kod: Zaznacz cały

 if (digitalRead(przycisk) == LOW)  // Sprawdzamy czy przycisk nie jest wciśnięty
     {            
      }
   else (digitalRead(przycisk) == HIGH); // W innym przypadku 
     {                                             
    a=b+0.1;
    }
Tej konstrukcji nie rozumiem. Po co sprawdzasz dwa warunki?

Kod: Zaznacz cały

else (digitalRead(przycisk) == HIGH);
Przy okazji, to nie jest poprawny zapis warunku!

Kod: Zaznacz cały

a=b+0.1;
Jaką wartość ma b?

Kod: Zaznacz cały

      digitalWrite(dioda, LOW);
      delay(1000);
      digitalWrite(dioda, HIGH);
      delay(1000);
To już wiemy, że jest źle. Zaraz to rozpiszę.

A teraz moja wersja kodu. Z komentarzami.

Kod: Zaznacz cały

#include "DHT.h"
#include <TM1637Display.h>
#define DHTPIN 2
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
const int CLK = 4;
const int DIO = 3;
TM1637Display tm1637a(CLK, DIO);
int przekaznik=7;
int dioda=8;
int przycisk = 3;
unsigned long sekunda = 0;
unsigned long czas_pomiaru_temperatury = 0;
int stanLED = 0;
float a=30.0;
void setup(void)
{
  pinMode(przekaznik,OUTPUT);
  digitalWrite(przekaznik,LOW);
  pinMode(dioda, OUTPUT);
  pinMode(przycisk, INPUT_PULLUP);
  tm1637a.setBrightness(0x0a);
  Serial.begin(9600);
  dht.begin();
}

void loop(void)
{ 
  if (millis() - czas_pomiaru_temperatury >= 5000UL)
  {
    float t = dht.readTemperature();
    czas_pomiaru_temperatury = millis();  
    Serial.print("Temperature: "); 
    Serial.print(t);
    Serial.println(" *C");
  }  
    
  if (t >= a)
  {
    digitalWrite(przekaznik,HIGH);
  }
  if (t <= (a-2.0))
  {
    digitalWrite(przekaznik,LOW);
  }
    
  if (digitalRead(przycisk) == LOW)
  {
    a = a + 0.1;
  }

  tm1637a.showNumberDec(t); //Display the Variable value;

  if (millis() - sekunda >= 1000UL)
  {
    sekunda = millis();
    stanLED = !stanLED;     
    digitalWrite(dioda, stanLED);
  }  
  delay(100);
}
Albo bez komentarza. Spróbuj sam zrozumieć
hazi18
Młodszy majsterkowicz
Posty: 23
Rejestracja: 18 paź 2019, 20:36

Re: Inkrementacja zmiennej

Post autor: hazi18 » 26 lis 2019, 18:47

Hej, kod działa ale musiałem dać "float t = dht.readTemperature();" przed wszystkie if żeby działało :)
co do float to nie wiedziałem, że wartość musi być podana z wartością dziesiętna 30.0.
Zmienna b miała być do tego aby do niej dodać te 0.1 i zapisywało do zmiennej a, ale widzę, że moje myślenie było błędne :).
Odczytanie wartości t, która była przypisana do zmiennej, fakt nie pomyślałem o tym, że tak można to zrobić.
if (digitalRead(przycisk) == LOW) // Sprawdzamy czy przycisk nie jest wciśnięty
{
}
else (digitalRead(przycisk) == HIGH); // W innym przypadku
{
a=b+0.1;
}

Tej konstrukcji nie rozumiem. Po co sprawdzasz dwa warunki?
Pisałeś wcześniej o tym, by w loop sprawdzało stan przycisku dlatego dodałem taki kod, który sprawdza czy przycisk jest wciśnięty.
Co do milis() wiem, że liczy czas od działania programu, aż zapełni się jego tablica do 50 dnia działania a potem od zera leci zegar. Tylko że ja nie potrafiłem tego wykorzystać do migania diodą co sekundę i dla mnie laika łatwiejsze jest wykorzystanie delay(). Co oznaczają wartości 5000UL i 1000UL? Według mnie 5000 to czas czytania wartości temperatury a 1000 to czas migania diody ( widzę po działaniu :))

Próbowałem z przyciskiem żeby dodawało mi po 0.1 i kliknąłem 5 razy czyli powinno dodać 0.5 a temperatura jak osiągnie 30 to przełacznik reaguje a powinno przy 30.5. Czy może to być wina źle podpiętego przełącznika? Ja testowałem taki układ z zapalaniem diody i działało. Przełożyłem kabelek sygnałowy z jednej nóżki na drugą i bez efektu.
Awatar użytkownika
Marhef
Złota rączka
Posty: 1188
Rejestracja: 18 lis 2011, 02:18

Re: Inkrementacja zmiennej

Post autor: Marhef » 27 lis 2019, 09:44

hazi18 pisze:
26 lis 2019, 18:47
Hej, kod działa ale musiałem dać "float t = dht.readTemperature();" przed wszystkie if żeby działało :)
A tu fakt, zapomniałem o pierwszym pomiarze. Powinieneś to wrzucić na koniec sekcji setup() (zaraz po dht.begin)
hazi18 pisze:
26 lis 2019, 18:47
co do float to nie wiedziałem, że wartość musi być podana z wartością dziesiętna 30.0.
W arduino przejdzie i tak, jak napisałeś. Gdybyś pisał w C, część kompilatorów wyrzuca ostrzeżenie, że dodajesz do siebie liczby w różnych typach danych - liczby bez części dziesiętnej są traktowane jako zmienne (albo stałe) typu int.
hazi18 pisze:
26 lis 2019, 18:47
Pisałeś wcześniej o tym, by w loop sprawdzało stan przycisku dlatego dodałem taki kod, który sprawdza czy przycisk jest wciśnięty.
Domyśliłem się, że po to. Ale sprawdzasz, czy przycisk nie jest wciśnięty, a za chwilę, czy przycisk jest wciśnięty. Wystarczyłby tylko jeden z tych warunków.
hazi18 pisze:
26 lis 2019, 18:47
Co oznaczają wartości 5000UL i 1000UL? Według mnie 5000 to czas czytania wartości temperatury a 1000 to czas migania diody ( widzę po działaniu :))
Dodając UL do liczby określam, że liczba jest typu Unsigned long. Z powodu takiego samego jak dodaję .0 do liczb typu float.
To jest do odmierzania czasu. Zrobiłem tak, żeby dioda zmieniała stan co sekundę, a pomiar temperatury co 5 sekund.
hazi18 pisze:
26 lis 2019, 18:47
Próbowałem z przyciskiem żeby dodawało mi po 0.1 i kliknąłem 5 razy czyli powinno dodać 0.5 a temperatura jak osiągnie 30 to przełacznik reaguje a powinno przy 30.5. Czy może to być wina źle podpiętego przełącznika? Ja testowałem taki układ z zapalaniem diody i działało. Przełożyłem kabelek sygnałowy z jednej nóżki na drugą i bez efektu.
Tego nie do końca rozumiem. Masz więcej wyświetlaczy? Podłącz drugi i wyświetlaj na nim wartość ustawionej temperatury (zmienną a).
Czy funkcja showNumberDec(t) wyświetla Ci dobrze wartość typu float? Jeśli tak, dodaj drugi wyświetlacz i wyświetl zmienną a poleceniem tm1637b.showNumberDec(a);
hazi18
Młodszy majsterkowicz
Posty: 23
Rejestracja: 18 paź 2019, 20:36

Re: Inkrementacja zmiennej

Post autor: hazi18 » 27 lis 2019, 18:24

Hej,
Ja właśnie nie mam aktualnie wyświetlaczy tylko na szeregowym to sprawdzam. Zaraz po nie pójde bo zdementuję z inkubatora i sprawdzę :)
Próbuję i powiem Ci, że nie działa ta inkrementacja :( na wyświetlaczu mam 30 i samoczynnie mi się inkrementuje. A jak przyciskam to przycisk gaśnie mi diodę i przełącznik. Takie pytanie z obserwacji, czy sprawdzanie przycisku nie powinno być poza loopem? bo teraz samo inkremetuje mi wartość "a" a nie powinno.

Kod: Zaznacz cały

#include "DHT.h"
#include <TM1637Display.h>
#define DHTPIN 2
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
const int CLK = 4;
const int DIO = 5;
TM1637Display tm1637a(CLK, DIO);
int przekaznik=7;
int dioda=8;
int przycisk = 3;
unsigned long sekunda = 0;
unsigned long czas_pomiaru_temperatury = 0;
int stanLED = 0;
float a=30.0;
void setup(void)
{
  pinMode(przekaznik,OUTPUT);
  digitalWrite(przekaznik,LOW);
  pinMode(dioda, OUTPUT);
  pinMode(przycisk, INPUT_PULLUP);
  tm1637a.setBrightness(0x0a);
  Serial.begin(9600);
  dht.begin();
}

void loop(void)
{ 
  float t = dht.readTemperature();
  if (millis() - czas_pomiaru_temperatury >= 1000UL)
  {
    float t = dht.readTemperature();
    czas_pomiaru_temperatury = millis();  
    Serial.print("Temperature: "); 
    Serial.print(t);
    Serial.println(" *C");
  }  
    
  if (t >= a)
  {
    digitalWrite(przekaznik,HIGH);
  }
  if (t <= (a-2.0))
  {
    digitalWrite(przekaznik,LOW);
  }
    
  if (digitalRead(przycisk) == LOW)
  {
    a = a + 0.1;
  }

  tm1637a.showNumberDec(a); //Display the Variable value;

  if (millis() - sekunda >= 1000UL)
  {
    sekunda = millis();
    stanLED = !stanLED;     
    digitalWrite(dioda, stanLED);
  }  
  delay(1000);
}
Awatar użytkownika
Marhef
Złota rączka
Posty: 1188
Rejestracja: 18 lis 2011, 02:18

Re: Inkrementacja zmiennej

Post autor: Marhef » 28 lis 2019, 10:13

Czekaj, jak podłączyłeś przycisk? Wstaw tu zdjęcie połączenia.
Widzę, że nie masz zamiaru pozbyć się delay?
I jeszcze jedno, linijkę

Kod: Zaznacz cały

float t = dht.readTemperature();
przenieś na koniec sekcji setup().
hazi18 pisze:
27 lis 2019, 18:24
Takie pytanie z obserwacji, czy sprawdzanie przycisku nie powinno być poza loopem? bo teraz samo inkremetuje mi wartość "a" a nie powinno.
NIE! Arduino działa w ten sposób, że po podaniu zasilania najpierw wykonuje się jeden raz to, co masz w setup(), a następnie w kółko wykonuje się to, co masz w loop().
To, że samo się inkrementuje świadczy o tym, że pin 3 masz cały czas zwarty do GND. Dlatego co sekundę zwiększa Ci się wartość temperatury. Co sekundę, bo zostawiłeś takiego delay'a. I to nie pozwoli Ci na dobrą obsługę przycisku. Zostaw tam co najwyżej delay(100);
hazi18 pisze:
27 lis 2019, 18:24
A jak przyciskam to przycisk gaśnie mi diodę i przełącznik.
Podłączyłeś przycisk pod reset arduino?!

Aha, w moim kodzie był pomiar temperatury co 5 sekund. W Twoim, temperatura jest mierzona co sekundę, za każdym razem dwa razy.
hazi18
Młodszy majsterkowicz
Posty: 23
Rejestracja: 18 paź 2019, 20:36

Re: Inkrementacja zmiennej

Post autor: hazi18 » 28 lis 2019, 20:01

Hej,
ten Delay był już w Twoim kodzie to go zostawiłem :) ale mogę wywalić.
Jak w kodzie kabelek jest podłączony do pinu nr 3.
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.
Ostatnio zmieniony 29 lis 2019, 17:20 przez hazi18, łącznie zmieniany 1 raz.
Awatar użytkownika
Marhef
Złota rączka
Posty: 1188
Rejestracja: 18 lis 2011, 02:18

Re: Inkrementacja zmiennej

Post autor: Marhef » 29 lis 2019, 09:46

Wywal kabelek +!!!!
Przecież robisz zwarcie zasilania!!!!!
hazi18 pisze:
28 lis 2019, 20:01
ten Delay był już w Twoim kodzie to go zostawiłem :)
Ale był tam delay(1000)?!

Jeszcze jedno nie wrzucaj zdjęć na zewnętrzny serwer, za chwilę ich tam nie będzie. W edytorze postów na dole masz zakładkę "Załączniki", tam dodawaj zdjęcia.
hazi18
Młodszy majsterkowicz
Posty: 23
Rejestracja: 18 paź 2019, 20:36

Re: Inkrementacja zmiennej

Post autor: hazi18 » 29 lis 2019, 17:24

OK faktycznie działa i dodaje jak wcisnę jednak dodaje mi co 0.5 bo 2 przyciśnięcia i już mam o 1 stopień więcej. Kurde a na rozpisce do diody było inaczej :) U Ciebie był delay(100) ale zmieniłem a potem go wywaliłem :) Pytanie czemu inkrementuje co 0.5?
Awatar użytkownika
Marhef
Złota rączka
Posty: 1188
Rejestracja: 18 lis 2011, 02:18

Re: Inkrementacja zmiennej

Post autor: Marhef » 30 lis 2019, 13:43

Bo pętla zdąży się wykonać kilka razy, zanim puścisz przycisk. Postaram się później dopisać warunek tak, żeby to się nie działo.
stiven
Złota rączka
Posty: 1593
Rejestracja: 13 maja 2014, 08:47
Lokalizacja: Zielona Góra

Re: Inkrementacja zmiennej

Post autor: stiven » 1 gru 2019, 13:21

Żeby ten if od przycisku zadziałał tylko raz po przyciśnięciu trzeba skorzystać z dodatkowej zmiennej i drugiego ifa, żeby to zapewnić. Dodatkowo trzeba skorzystać z krótkiego delaya w obu ifach, ponieważ istnieje takie zjawisko jak drganie styków w przycisku. W momencie przyciskania i puszczania przycisku styki drgają i program wykryje kilka zmian stanu, trzeba ten czas jakby "przeczekać".

Kod: Zaznacz cały

boolean blokada = 0;   //zadeklarowane poza loop() i setup()


  if (digitalRead(przycisk) == LOW && blokada == 0)
  {
    a = a + 0.1;
    blokada = 1; 
    delay(50);
  }

  else if(digitalRead(przycisk) == HIGH && blokada == 1) 
  {
    blokada = 0;
    delay(50);
  }
Zmienna typu boolean może przyjmować 2 wartości - 0 lub 1, czyli jest to 1 bit. Można by było użyć innego typu, ale skoro potrzebujemy tylko 2 wartości, a pamięć na program w arduino jest mocno ograniczona, to warto zawsze korzystać z typów mniejszych niż większych, bo w miarę rozrastania się programu tej pamięci może zabraknąć.


Kiedyś ktoś wrzucił tu na forum sposób, który nie wymaga delayów.

Kod: Zaznacz cały

byte blokada = 0;   //zadeklarowane poza loop() i setup()


  if (digitalRead(przycisk) == LOW && blokada == 0) 
  {
    blokada = 1;
    a = a + 0.1;
  }

  if (digitalRead(przycisk) == HIGH && blokada > 0) blokada++;
Typ byte, to 1 bajt, 8 bitów, zmienna tego typu przyjmuje wartości od 0 do 255 i tutaj akurat musi być taki typ wykorzystany, ze względu na zasadę na jakiej działa to rozwiązanie. Drugi if z powodu drgania styków zadziała już w trakcie wciskania przycisku, ale dzięki temu, że zmienna blokada może być inkrementowana do 255, to stworzy się taki "bufor", zanim zmienna blokada "przekręci się" i znowu będzie miała wartość 0, drugi if przestanie się wykonywać a będzie mógł ponownie pierwszy if.
Przy tym rozwiązaniu nie może być w innym miejscu kodu delay i zmienna blokada nie może być "większego" typu, bo spowoduje to przerwę w ponownym zadziałaniu przycisku.
Awatar użytkownika
Marhef
Złota rączka
Posty: 1188
Rejestracja: 18 lis 2011, 02:18

Re: Inkrementacja zmiennej

Post autor: Marhef » 1 gru 2019, 18:43

stiven pisze:
1 gru 2019, 13:21
Zmienna typu boolean może przyjmować 2 wartości - 0 lub 1, czyli jest to 1 bit. Można by było użyć innego typu, ale skoro potrzebujemy tylko 2 wartości, a pamięć na program w arduino jest mocno ograniczona, to warto zawsze korzystać z typów mniejszych niż większych, bo w miarę rozrastania się programu tej pamięci może zabraknąć.
A to nie jest tak, że zajmie i tak 1 bajt (8 bitów)? Z tego, co pamiętam, jeżeli procek jest 8-bitowy, to jest to najmniejsza możliwa ilość danych, które można zapisać (ale mogę się mylić). Niech ktoś to sprawdzi :)
stiven pisze:
1 gru 2019, 13:21
Kiedyś ktoś wrzucił tu na forum sposób, który nie wymaga delayów.
Ja to kiedyś wrzuciłem. Jako przeróbkę kodu znalezionego w internetach (na http://mirekk36.blogspot.com/)
stiven pisze:
1 gru 2019, 13:21
Typ byte, to 1 bajt, 8 bitów, zmienna tego typu przyjmuje wartości od 0 do 255 i tutaj akurat musi być taki typ wykorzystany, ze względu na zasadę na jakiej działa to rozwiązanie.
Można dać zmienną większego typu. To się przydaje, jeżeli chcesz zrobić tzw. autoinkrementację (wartość rośnie przy przytrzymaniu przycisku). W zależności od tego, co ile chcesz zmieniać wartość, dobiera się zmienną odpowiedniego typu.
Jako ciekawostkę dodam, że można np. zrobić tak, że po kilku zmianach wartości, kolejne zmiany będą wykonywać się szybciej.
Marhef pisze:
30 lis 2019, 13:43
Postaram się później dopisać warunek tak, żeby to się nie działo.
Nie zdążyłem, ale miał to być sposób podany przez stiven'a. Ten bez delay
hazi18
Młodszy majsterkowicz
Posty: 23
Rejestracja: 18 paź 2019, 20:36

Re: Inkrementacja zmiennej

Post autor: hazi18 » 1 gru 2019, 22:11

Hej,
Dzięki panowie, myślałem o tym żeby zastosować delay() po komentarzu @Marhef
Postaram się później dopisać warunek tak, żeby to się nie działo.
Jednak obawiałem się go dać bo wcześniej usuwaliśmy je z programu:)
co do działania programu, pytanko czemu jest blokada++? Co ma mi pomóc inkrementacja tej blokady bo nie rozumiem? Jak próbuję inkrementować za pomocą przycisku to nie działa...
byte blokada = 0; //zadeklarowane poza loop() i setup()
zostało zadeklarowane na początku programu przed setup.
stiven
Złota rączka
Posty: 1593
Rejestracja: 13 maja 2014, 08:47
Lokalizacja: Zielona Góra

Re: Inkrementacja zmiennej

Post autor: stiven » 1 gru 2019, 23:00

Marhef pisze:
1 gru 2019, 18:43
A to nie jest tak, że zajmie i tak 1 bajt (8 bitów)? Z tego, co pamiętam, jeżeli procek jest 8-bitowy, to jest to najmniejsza możliwa ilość danych, które można zapisać (ale mogę się mylić). Niech ktoś to sprawdzi :)
Sprawdziłem. Masz rację. Nie wiedziałem o tym.
stiven pisze:
1 gru 2019, 13:21
Typ byte, to 1 bajt, 8 bitów, zmienna tego typu przyjmuje wartości od 0 do 255 i tutaj akurat musi być taki typ wykorzystany, ze względu na zasadę na jakiej działa to rozwiązanie.
Marhef pisze:
1 gru 2019, 18:43
Można dać zmienną większego typu. To się przydaje, jeżeli chcesz zrobić tzw. autoinkrementację (wartość rośnie przy przytrzymaniu przycisku). W zależności od tego, co ile chcesz zmieniać wartość, dobiera się zmienną odpowiedniego typu.
Jako ciekawostkę dodam, że można np. zrobić tak, że po kilku zmianach wartości, kolejne zmiany będą wykonywać się szybciej.
Okej, ale sprawdziłem jak zachowa się program bez dodatkowych modyfikacji, zmieniając jedynie zmienną blokada na typ unsigned int zamiast byte (unsigned int, bo zwykły int przyjmuje też wartości ujemne, przy zwykłym int by trzeba było też zmodyfikować warunek w drugim ifie). Program reaguje na ponowne wciśnięcie przycisku dopiero po około 4 sekundach. Wynika to z tego, że cały program musi się wykonać ponad 64000 razy, a nie 255, żeby ponownie zadziałał pierwszy if i dlatego napisałem:
stiven pisze:
1 gru 2019, 13:21
Przy tym rozwiązaniu nie może być w innym miejscu kodu delay i zmienna blokada nie może być "większego" typu, bo spowoduje to przerwę w ponownym zadziałaniu przycisku.
stiven
Złota rączka
Posty: 1593
Rejestracja: 13 maja 2014, 08:47
Lokalizacja: Zielona Góra

Re: Inkrementacja zmiennej

Post autor: stiven » 2 gru 2019, 00:13

hazi18 pisze:
1 gru 2019, 22:11
co do działania programu, pytanko czemu jest blokada++? Co ma mi pomóc inkrementacja tej blokady bo nie rozumiem? Jak próbuję inkrementować za pomocą przycisku to nie działa...
byte blokada = 0; //zadeklarowane poza loop() i setup()
zostało zadeklarowane na początku programu przed setup.
Pokaż cały program, no bo coś w takim razie masz źle. blokada++ jest po to, żeby ponowne wykrycie przyciśniętego przycisku było tak jak napisałem wcześniej, po jakimś czasie, aż zmienna blokada przepełni się i przekręci na 0 (inkrementacja tej zmiennej blokada jest w czasie, kiedy przycisk nie jest wciśnięty). Kiedy zmienna blokada będzie miała znowu wartość 0, to drugi if przestanie inkrementować tą zmienną, ale wtedy pierwszy if będzie mógł zadziałać. Jest tak, że jeśli zmienna może przyjmować wartości od 0 do 255, to kiedy zmienna ma wartość 255 i dodamy do niej 1, to ona "przekręci się" jak analogowy licznik, będzie miała wartość 0 (analogicznie, jeśli do 255 dodamy 2, to będzie 1, jeśli do 255 dodamy 3, to 2, albo do 250 dodamy 10, to 4). Program działa bardzo szybko jeśli nie ma w nim delay(), mniej niż milisekunda (ale to też zależy od jego długości i operacji w nim wykonywanych), żeby zmienna blokada (przy typie byte) przeskoczyła na wartość 0, minie jedynie kilkanaście milisekund, a jest to tak krótki czas, że nie wpłynie w żaden sposób na "płynność" działania przycisku.
hazi18
Młodszy majsterkowicz
Posty: 23
Rejestracja: 18 paź 2019, 20:36

Re: Inkrementacja zmiennej

Post autor: hazi18 » 2 gru 2019, 17:58

Kod: Zaznacz cały

#include "DHT.h"
#include <TM1637Display.h>
#define DHTPIN 2
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
const int CLK = 4;
const int DIO = 5;
TM1637Display tm1637a(CLK, DIO);
int przekaznik=7;
int dioda=8;
int przycisk1 = 3;
int przycisk2 = 6;
unsigned long sekunda = 0;
unsigned long czas_pomiaru_temperatury = 0;
int stanLED = 0;
float a=30.0;
byte blokada = 0;   //zadeklarowane poza loop() i setup()
void setup(void)
{
  pinMode(przekaznik,OUTPUT);
  digitalWrite(przekaznik,LOW);
  pinMode(dioda, OUTPUT);
  pinMode(przycisk1, INPUT_PULLUP);
  pinMode(przycisk2, INPUT_PULLUP);
  tm1637a.setBrightness(0x0a);
  Serial.begin(9600);
  dht.begin();
}

void loop(void)
{   float t = dht.readTemperature();

  if (millis() - czas_pomiaru_temperatury >= 1000UL)
  {
    float t = dht.readTemperature();
    czas_pomiaru_temperatury = millis();  
    Serial.print("Temperature: "); 
    Serial.print(t);
    Serial.println(" *C");
  }  
    
  if (t >= a)
  {
    digitalWrite(przekaznik,HIGH);
  }
  if (t <= (a-2.0))
  {
    digitalWrite(przekaznik,LOW);
  }

  if (digitalRead(przycisk1) == LOW && blokada == 0) 
  {
    blokada = 1;
    a = a + 0.1;
  }

  if (digitalRead(przycisk1) == HIGH && blokada > 0) blokada++;

/*
    
  if (digitalRead(przycisk1) == LOW)
  {
    a = a + 0.1;
  }
    if (digitalRead(przycisk2) == LOW)
  {
    a = a - 0.1;
  }*/

  tm1637a.showNumberDec(a); //Display the Variable value;

  if (millis() - sekunda >= 1000UL)
  {
    sekunda = millis();
    stanLED = !stanLED;     
    digitalWrite(dioda, stanLED);
  }  
}
Tak to wygląda aktualnie. Rozumiem o co chodzi z tym przekręceniem się licznika. Więc ify te działają na takiej zasadzie, że wcisnę przycisk i wtedy uruchamiam zmienna blokada która inkrementuje mi się do momentu przekręcenia się licznika i ustawieniu się na 0, wtedy w ruch idzie drugi if i dodaje moją zadeklarowaną wartość ( w tym przypadku 0.1). Dobrze zrozumiałem działanie obu ifów?
stiven
Złota rączka
Posty: 1593
Rejestracja: 13 maja 2014, 08:47
Lokalizacja: Zielona Góra

Re: Inkrementacja zmiennej

Post autor: stiven » 2 gru 2019, 21:46

W momencie wciśnięcia przycisku zadziała raz pierwszy if, bo zmienna blokada zostaje ustawiona na 1 i nie będzie już spełniony warunek blokada == 0. Po puszczeniu przycisku działa drugi if aż do momentu przekręcania zmiennej blokada na wartość 0.
Z tymże że względu na występowanie zjawiska drgania styków przycisku, drugi if kilka razy wykona się już w momencie przyciskania przycisku i puszczania, na przykład z 10 razy, no ale będzie duży zapas do 255.
Gdyby nie drganie styków, które trzeba w jakiś sposób ominąć, to wystarczyłoby w drugim ifie napisać po prostu blokada = 0. I tak jest właśnie w pierwszym rozwiązaniu, ale tam jest użyty delay() do ominięcia momentów drgania styków, które powodują szybkie kilkukrotne zmiany stanu na wejściu Arduino, co program by interpretował jako kilkukrotne wciśnięcie przycisku.
A działa już to przyciskanie przycisku? Program wygląda dobrze.
Aha, jeszcze dopiszę, że jest tak, że delay() zatrzymuje w miejscu program na określony czas. To rozwiązanie z inkrementacją zmiennej blokada wygląda tak, że jak program trafia na drugiego ifa, dodaje 1 do zmiennej i idzie dalej, aż do końca, potem zaczyna się program od nowa i jak znowu dojdzie do ifa, zostanie dodane 1 do zmiennej blokada, itd. Takie rozwiązanie jest lepsze dla płynności działania całego programu.
Awatar użytkownika
Marhef
Złota rączka
Posty: 1188
Rejestracja: 18 lis 2011, 02:18

Re: Inkrementacja zmiennej

Post autor: Marhef » 3 gru 2019, 10:35

Hmm, ja widziałem trochę inne rozwiązanie jednak. Więc to, co pisałem wcześniej odnośnie automatycznej inkrementacji nie zadziała z waszą funkcją!!
W mojej wersji warunek wyglądałby tak:

Kod: Zaznacz cały

if (digitalRead(przycisk1) == LOW && blokada == 0) 
  {
    blokada = 1;
    a = a + 0.1;
  } else if (blokada >0) blokada++;
Dzięki temu, co 256 obiegów pętli, zmienna będzie się zwiększać.
Przepraszam za wprowadzanie w błąd.
I nie mam tego jak sprawdzić, hazi18, możesz potwierdzić, czy to zadziała?
stiven
Złota rączka
Posty: 1593
Rejestracja: 13 maja 2014, 08:47
Lokalizacja: Zielona Góra

Re: Inkrementacja zmiennej

Post autor: stiven » 3 gru 2019, 11:58

Niestety to nie działa prawidłowo. Musi być w tym drugim ifie ten warunek o puszczeniu przycisku. Bez tego dodatkowego warunku, zmienna blokada przekręca się momentalnie, w ciągu milisekund, bo jedna pętla programu trwa mikrosekundy i przez to właściwie nie ma żadnego zabezpieczenia przed wielokrotnym wykonywaniem pierwszego ifa. Samo else nic tutaj też nie zmienia, bo powoduje, że wykona się ten if, albo ten, ale warunki były takie, że w praktyce już tak było. Usunięcie warunku o puszczeniu przycisku, powoduje, że zmienna blokada jest inkrementowana do przekręcenia już w czasie przyciskania przycisku, a jej przekręcenie trwa ułamek sekundy.

Ale właściwie teraz można zmienić typ zmiennej blokada z byte na unsigned int, co daje fajny efekt, pierwszy if wykonuje się powtórnie po około 3-4 sekundach, a nie kilkadziesiąt razy w ciągu sekundy. A takie coś już będzie do przyjęcia, a nawet dobrą funkcją. Można by jeszcze zmienić kod tak, żeby dłuższe przytrzymanie przycisku szybciej inkrementowało zmienną w pierwszym ifie, czyli osiągnąć to, o czym pisałeś
Marhef pisze:
1 gru 2019, 18:43
Można dać zmienną większego typu. To się przydaje, jeżeli chcesz zrobić tzw. autoinkrementację (wartość rośnie przy przytrzymaniu przycisku). W zależności od tego, co ile chcesz zmieniać wartość, dobiera się zmienną odpowiedniego typu.
Jako ciekawostkę dodam, że można np. zrobić tak, że po kilku zmianach wartości, kolejne zmiany będą wykonywać się szybciej.
Awatar użytkownika
Marhef
Złota rączka
Posty: 1188
Rejestracja: 18 lis 2011, 02:18

Re: Inkrementacja zmiennej

Post autor: Marhef » 3 gru 2019, 14:37

Ja tak piszę z doskoku, dlatego moje wypowiedzi mogą nie być precyzyjne.
Właśnie o taki efekt mi chodziło, jak potrzebujesz zmienić wartość o np. 300 jednostek, to nie musisz przyciskać 300 razy, tylko przytrzymujesz raz.
stiven pisze:
3 gru 2019, 11:58
Można by jeszcze zmienić kod tak, żeby dłuższe przytrzymanie przycisku szybciej inkrementowało zmienną w pierwszym ifie
Można to zrobić na przykład tak:

Kod: Zaznacz cały

if (digitalRead(przycisk1) == LOW && blokada == 0) 
  {
    blokada = 1;
    a = a + 0.1;  //a to można zapisać jako a+=0.1;
    licznik++;
    if (licznik == 7) krok = 10;  // główna zmiana jest tu
    if (blokada > 246 && krok == 10) blokada = 246;  // zabezpieczenie
  } else if (blokada >0) blokada+=krok;
if (digitalRead(przycisk1) == HIGH)
  {
    krok = 1;
    licznik = 0;
  }
Wyjaśnienie: Dodałem zmienne licznik i krok (muszą być zadeklarowane wcześniej!). licznik licza, ile razy nastąpiła zmiana wartości. Jeżeli 8 razy, przyspiesza dziesięciokrotnie zwiększanie wartości (przy każdym obiegu pętli dodaje 10 do blokady). Po puszczeniu przycisku zmienne krok i licznik muszą zostać przywrócone do wartości początkowych. Linijka z komentarzem // zabezpieczenie jest po to, żeby na pewno przy przekręceniu się zmiennej w jednym kroku była wartość 0. Wpisałem 246 dla zmiennej typu byte. Przy zmianie typu należy zadbać o to, żeby zmienna blokada przyjęła wartość o 9 mniejszą od wartości maksymalnej.
stiven
Złota rączka
Posty: 1593
Rejestracja: 13 maja 2014, 08:47
Lokalizacja: Zielona Góra

Re: Inkrementacja zmiennej

Post autor: stiven » 3 gru 2019, 15:00

Marhef pisze:
3 gru 2019, 14:37
Ja tak piszę z doskoku, dlatego moje wypowiedzi mogą nie być precyzyjne.
Właśnie o taki efekt mi chodziło, jak potrzebujesz zmienić wartość o np. 300 jednostek, to nie musisz przyciskać 300 razy, tylko przytrzymujesz raz.
Ale to od razu musi być inny typ niż byte przy tym rozwiązaniu, bo bez dodawania tego przyspieszenia inkrementowania, już jest jednorazowy skok o kilkadziesiąt jednostek przy jednorazowym bardzo krótkim przyciśnięciu przycisku, więc całkiem traci się precyzyjną regulację.
hazi18
Młodszy majsterkowicz
Posty: 23
Rejestracja: 18 paź 2019, 20:36

Re: Inkrementacja zmiennej

Post autor: hazi18 » 3 gru 2019, 18:40

Panowie, sprawdzałem oba przypadki pisane przez Was i po inkrementacji tylko zinkrementowało się o 0.1 i dalej nic. Zrobiłem jak wcześniej było napisane z użycie delay() i muszę przyznać, że to działa bez zarzutu. Jest jeszcze jeden problem, brak pamięci ustawień przez EEPROM. Jak to rozwiązać?

Kod: Zaznacz cały

  if (digitalRead(przycisk1) == LOW)
  {
    a = a + 0.1;
    delay(250);
  }
    if (digitalRead(przycisk2) == LOW)
  {
    a = a - 0.1;
    delay(250);
  }
nie ma problemu inkrementacji/dekrementacji o 0.5 podczas 1 klika. Powiem tak, to działa i jestem zadowolony :) Także dziękuje za wszelkie podsunięte pomysły :)
stiven
Złota rączka
Posty: 1593
Rejestracja: 13 maja 2014, 08:47
Lokalizacja: Zielona Góra

Re: Inkrementacja zmiennej

Post autor: stiven » 3 gru 2019, 22:18

hazi18 pisze:
3 gru 2019, 18:40
Jest jeszcze jeden problem, brak pamięci ustawień przez EEPROM. Jak to rozwiązać?
Zapisujesz coś do EEPROM a później po odczycie jest coś innego?
ODPOWIEDZ

Strony partnerskie: