Skocz do zawartości

Arduino - licznik impulsów i klawiatura


Pomocna odpowiedź

Napisano

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ć. 

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;
}

 

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...

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ć... 

(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
(edytowany)
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

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...