Skocz do zawartości

Arduino - licznik impulsów i klawiatura


Witer30

Pomocna odpowiedź

Witam,

Pisze programik który ma zadanie zliczać impulsy do wartości zadanej z klawiatury i wyświetlać dane na LCD. Klawiatura to ADKeyboard v2  i komunikuje się przez pin analogowy. Wyświetlacz LCD poprze I2C. 

O to co stworzyłem - działa i nie działa...

//Licznik impulsów
/*   Inicjacja LCD    */
#include <Wire.h>   // standardowa biblioteka Arduino
#include <LiquidCrystal_I2C.h> // dolaczenie pobranej biblioteki I2C dla LCD
LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Ustawienie adresu ukladu na 0x3F
/*   Koniec - Inicjacja LCD    */

/*Inicjacja klawiatury  */
int adc_key_val[5] ={600,650,700,800,900};
int NUM_KEYS = 5;
int adc_key_in;
int key=-1;
int oldkey=-1;
/*Koniec - Inicjacja klawiatury  */ 

word steps;
word licznik; //wskazanie aktualnie zliczanych impulsów
word wartosczadana; //ustawienie do jakiej wartości ma zliczać impulsy
word wartosczadanapom;
word pom0, pom1, pom2, pom3, pom4;
void setup()
{
  
  //część licznika
  Serial.begin(9600);
  pinMode(2, INPUT_PULLUP); // GND podłącznie do pinu 2 przez przycisk
  attachInterrupt(0, onStep, FALLING); //Przerwanie dla licznika
  
  //inicjalizacja LCD
  lcd.begin(16,2);   // Inicjalizacja LCD 2x16
  lcd.backlight(); // zalaczenie podwietlenia 
  lcd.setCursor(0,0); // Ustawienie kursora w pozycji 0,0 (pierwszy wiersz, pierwsza kolumna)
  lcd.print("Licz do:");
  lcd.setCursor(0,1); //Ustawienie kursora w pozycji 0,0 (drugi wiersz, pierwsza kolumna)
  lcd.print("Ilosc:");
  licznik=0;
  wartosczadana=1;
  wartosczadanapom=0;
  
}

void loop()
{
  //klawiatura start
   
   
   adc_key_in = analogRead(0);    // read the value from the sensor
   //digitalWrite(13,LOW);
   key = get_key(adc_key_in);  // convert into key press

   if (key != oldkey)   // if keypress is detected
   {
    delay(50);  // wait for debounce time
    adc_key_in = analogRead(0);    // read the value from the sensor
    key = get_key(adc_key_in);    // convert into key press
    if (key != oldkey)
      {
      oldkey = key;
      if (key >=0)
        {
         if (key==0)
                {
                  pom0++;
                }

         if (key==1)
                {
                  pom1++;
                  pom2=pom1*100;
                }
         if (key==4)
                {
                  pom4++;
                  pom3=pom4*10;
                }        
         if (key==2) //ustawienie licznik=0 i wartosczadanapom=0
                {
                  pom0=pom1=pom2=pom3=pom4=0;
                  licznik=0;
                  wartosczadanapom=0;
                  wartosczadana=0;
                }  
         if (key==3)
                {
                  //akceptacja wartości wartosczadana
                }         
          wartosczadanapom=pom0+pom2+pom3;
          wartosczadana=wartosczadanapom;
       //   lcd.setCursor(9,0); //Ustawienie kursora w pozycji 
      //    lcd.print("        ");
     //     lcd.print(wartosczadana);
          Serial.println(wartosczadana);
          }
          }
          }
          
           

  //koniec klawiatura
  
  //Wyświetlenie na LCD aktualnej wartośći licznika
  //lcd.clear();

  
  lcd.setCursor(9,0); //Ustawienie kursora w pozycji 6,1 (drugi wiersz, szusta kolumna)
  lcd.print(wartosczadana);
  lcd.setCursor(7,1); //Ustawienie kursora w pozycji 7,1 (drugi wiersz, szusta kolumna)
  lcd.print(licznik);
 
 //Pętla jeśli licznik równy wartości zadanej to skasuj wartość licznika, wysteruj silnik i po opóźnieniu 5s przekaźnik
  
  while (licznik==wartosczadana)
  {
    lcd.setCursor(7,1); //Ustawienie kursora w pozycji 7,1 (drugi wiersz, szusta kolumna)
    lcd.print("                    ");
    licznik=0; 
    
    }
}
// Klawiatura Convert ADC value to key number
int get_key(unsigned int input)
{
    int k;
    for (k = 0; k < NUM_KEYS; k++)
    {
      if (input < adc_key_val[k])
     {
            return k;
        }
   }
       if (k >= NUM_KEYS)k = -1;  // No valid key pressed
       return k;
}
//Koniec klawiatura
void onStep()
{
  steps=licznik;
  static unsigned long lastTime;
  unsigned long timeNow = millis();
  if (timeNow - lastTime < 50)
    return;
    
  steps++;
  Serial.println(steps);
  licznik=steps;
  lastTime = timeNow;
}

Dziwnie się zachowuje ten program bo jak w sekcji setup zmienną "wartosczadana" ustawię na 0 to nie działa klawiatura i nie wyświetla na LCD, ale jak 1 to już działa... 

Też nie wiem jak zrobić aby jednym przyciskiem akceptować wartość zadaną do której ma zliczać licznik.

Dodam że mam wrażenie że zlicza mi podwójnie - mam na razie przycisk podpięty do GDN i pinu 2 (przerwanie dla arduino uno)...

Z góry dzięki za pomoc i wskazówki jak mogę usprawnić ten programik bo to dopiero początek.

Dodam że jak licznik osiągnie wartość zadaną to ma wysterować silnik i przekaźnik z opóźnieniem np 5s, skasować licznik i liczyć od nowa mimo że sterowanie silnikiem i przekaźnikiem nadal może trwać. 

Link do komentarza
Share on other sites

Masz kilka takich błędów jak używanie niezainicjalizowanych zmiennych

if (key==4) { pom4++; pom3=pom4*10; }

gdzie pom4 nie jest zainicjalizowana wcześniej.

Przy tego typu konstrukcjach z if warto jest stosować kaskadę if() - else if(); lub instrukcję switch

if(key == 0){
  // jakiś kod
}else if(key == 1){
  // jakiś kod
}else if(key == 2){} // itd

/// Lub

switch(key){ 
  case 0:
    // jakiś kod
    break;
  case 1:
    // jakiś kod
   	break;
  .
  .
  .
  default:
    // obsługa wyjątku
 	break;
}

 

Link do komentarza
Share on other sites

Przycisk 3 miał mi akceptować ustawioną wartość zadaną do której ma liczyć licznik... 

Jeszcze nie doszedłem do tego jak ustawiać wartość zadaną i dopiero po akceptacji żeby była brana jako wartość zadana...

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

20 godzin temu, atMegaTona napisał:

Masz kilka takich błędów jak używanie niezainicjalizowanych zmiennych

if (key==4) { pom4++; pom3=pom4*10; }

gdzie pom4 nie jest zainicjalizowana wcześniej.

Przy tego typu konstrukcjach z if warto jest stosować kaskadę if() - else if(); lub instrukcję switch


if(key == 0){
  // jakiś kod
}else if(key == 1){
  // jakiś kod
}else if(key == 2){} // itd

/// Lub

switch(key){ 
  case 0:
    // jakiś kod
    break;
  case 1:
    // jakiś kod
   	break;
  .
  .
  .
  default:
    // obsługa wyjątku
 	break;
}

 

Mam deklaracje zrobioną iż te zmienne są wartościami word. Fakt nie mam przypisanych wartości początkowych.

word pom0, pom1, pom2, pom3, pom4;

Generalnie to mnie zastanawia jedna rzecz, jak mam deklaracje zmiennej

wartosczadana=1;

tylko równą 0, to nie działa program. Ale jak już wartosczadana jest wieksza od 0 w deklaracji to wszystko działa do momentu resetu przyciskiem 2 to przestaje działać... 

Link do komentarza
Share on other sites

(edytowany)
30 minut temu, Witer30 napisał:

tylko równą 0, to nie działa program. Ale jak już wartosczadana jest wieksza od 0 w deklaracji to wszystko działa do momentu resetu przyciskiem 2 to przestaje działać... 

Problem tkwi w tej pętli - tak mi się wydaje... 

while (licznik==wartosczadana)
  {
    lcd.setCursor(7,1); //Ustawienie kursora w pozycji 7,1 (drugi wiersz, szusta kolumna)
    lcd.print("                    ");
    licznik=0; 
    
    }

Jak skasuje przyciskiem licznik i wartosczadana to przyjmują one wartość 0. Więc pętla wykonuje się w nieskończoność... Czy możecie coś poradzić jak uniknąć tego problemu. 

Drugie pytanie, to chciałbym uprościć ten program, czy możecie podpowiedzieć / nakierować jak to ugryźć... Bo licznik mam na przerwaniu, więc czy można by wprowadzanie danych z klawiatury również tak zrobić, lub przez funkcję i ją wywoływać jak zmieni się A0 gdzie jest ona podpięta... 

Dodam że program jeszcze będzie sterował silnikiem dc oraz przekaźnikiem z opóźnieniem 5s, gdzie licznik musi cały czas zliczać do wartosci zadanej. 

Czy dobrze kombinuje z tym w jakim kierunku chcę iść z programem... 

Edytowano przez Witer30
Link do komentarza
Share on other sites

6 minut temu, Witer30 napisał:

Czy możecie coś poradzić jak uniknąć tego problemu.

Nie robić pętli. Masz w programie jedną główną i ma wystarczyć.

  

7 minut temu, Witer30 napisał:

licznik mam na przerwaniu, więc czy można by wprowadzanie danych z klawiatury również tak zrobić


Może być trudne... jak sobie wyobrażasz wyzwolenie takiego przerwania?

  

7 minut temu, Witer30 napisał:

lub przez funkcję i ją wywoływać jak zmieni się A0 gdzie jest ona podpięta


Jak to rozumieć? Przecież masz coś takiego w programie...

Edytowano przez ethanak
Link do komentarza
Share on other sites

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.