Микроконтролери и електроника
http://mcu-bg.com/mcu_site/

Сверяване чрез матрична клавиатура
http://mcu-bg.com/mcu_site/viewtopic.php?f=7&t=8080
Страница 1 от 2

Автор:  morpheous87 [ Вто Авг 24, 2010 9:44 pm ]
Заглавие:  Сверяване чрез матрична клавиатура

Здравейте, направил съм програмка за Ардуино ( по-точно съм събрал на едно няколко по-малки програмки). Програмата се състои в изобразване на часовник, дата, ден и температура. Сензора е ТМР36, а RTC - DS1307. Всичко върви добре, но искам да мога да сверявам нещата след като пусна програмата посредством матрична 3х4 клавиатура. Срещам сериозни проблеми с написването на кода за сверяването обаче... Идеята ми е когато се натисне # на клавиатурата да се влезе в режим за сверяване, да се изредят една по една всички променливи и да заработи после програмата в нормалният й режим. За целта съм направил две функции - waitForKey() (която чака да се натисне бутон в рамките на 10сек. , ), и setClock() (която трябва да облужва натиснатите бутони, да разбира, кой бутон за кое се отнася и т.н)
Код:
#include "Wire.h"
#include <Keypad.h>
#define DS1307_I2C_ADDRESS 0x68
#include <LiquidCrystal.h> // we need this library for the LCD commands
LiquidCrystal lcd(12, 11, 10, 5, 4, 3, 2);
int countPressed;
/* Ot tuk e za keypad*/
const byte ROWS = 4; //four rows
const byte COLS = 3; //three columns
char keys[ROWS][COLS] = {
  {'1','2','3'},
  {'4','5','6'},
  {'7','8','9'},
  {'#','0','#'}
};
byte rowPins[ROWS] = { 9, 8, 7, 6}; //connect to the row pinouts of the keypad
byte colPins[COLS] = { 13, 1, 0}; //connect to the column pinouts of the keypad

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
/* do tuk e za keypad*/
// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
return ( (val/10*16) + (val%10) );
}
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
return ( (val/16*10) + (val%16) );
}
// 1) Sets the date and time on the ds1307
// 2) Starts the clock
// 3) Sets hour mode to 24 hour clock
// Assumes you're passing in valid numbers
void setDateDs1307(byte second, // 0-59
byte minute, // 0-59
byte hour, // 1-23
byte dayOfWeek, // 1-7
byte dayOfMonth, // 1-28/29/30/31
byte month, // 1-12
byte year) // 0-99
{
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.send(0);
Wire.send(decToBcd(second)); // 0 to bit 7 starts the clock
Wire.send(decToBcd(minute));
Wire.send(decToBcd(hour));
Wire.send(decToBcd(dayOfWeek));
Wire.send(decToBcd(dayOfMonth));
Wire.send(decToBcd(month));
Wire.send(decToBcd(year));
Wire.send(0x10); // sends 0x10 (hex) 00010000 (binary) to control register - turns on square wave
Wire.endTransmission();
}
// Gets the date and time from the ds1307
void getDateDs1307(byte *second,
byte *minute,
byte *hour,
byte *dayOfWeek,
byte *dayOfMonth,
byte *month,
byte *year)
{
// Reset the register pointer
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.send(0);
Wire.endTransmission();
Wire.requestFrom(DS1307_I2C_ADDRESS, 7);
// A few of these need masks because certain bits are control bits
*second = bcdToDec(Wire.receive() & 0x7f);
*minute = bcdToDec(Wire.receive());
*hour = bcdToDec(Wire.receive() & 0x3f); // Need to change this if 12 hour am/pm
*dayOfWeek = bcdToDec(Wire.receive());
*dayOfMonth = bcdToDec(Wire.receive());
*month = bcdToDec(Wire.receive());
*year = bcdToDec(Wire.receive());
}
void setup()
{
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
Wire.begin();
// Change these values to what you want to set your clock to.
// You probably only want to set your clock once and then remove
// the setDateDs1307 call.
second = 0;
minute = 23;
hour = 23;
dayOfWeek = 4;
dayOfMonth = 19;
month = 5;
year = 10;
// setDateDs1307(second, minute, hour, dayOfWeek, dayOfMonth, month, year);
lcd.begin(16, 2); // tells Arduino the LCD dimensions
lcd.setCursor(0,0);
lcd.print("   Miroslav's   "); // print text and move cursor to start of next line
lcd.setCursor(0,1);
lcd.print("Diplomna Rabota ");
delay(5000);
lcd.clear(); // clear LCD screen
}
int waitForKey() {
  char key = keypad.getKey();
if (key != NO_KEY){
     if (key == '#') {
     
           int key = NO_KEY;
           unsigned long _start_time = millis();
           int countPressed = 0;
while(((key = keypad.getKey()) == NO_KEY) && ((millis()-_start_time) < 10000))
   {
   // Do nothing
          if(key==PRESSED) {
            countPressed++;
            setClock();
            return key;
          }
         
   }
   return key;
}
} return countPressed;
}

  int setClock() {
   
    char key = keypad.getKey();
   switch(countPressed) {
     int first_hour;
     int first_minute;
     int second_hour;
     int second_minute;
    case 1:  lcd.print ("Hours:");
           
             first_hour = key;
            return first_hour;
   
    case 2: lcd.print ("Hours:");
            lcd.print (first_hour);
             second_hour = key;
            return second_hour;
           
    case 3: lcd.print ("Minutes:");
            first_minute = key;
            return first_minute;
           
    case 4: lcd.print ("Minutes");
            lcd.print (first_minute) ;
             second_minute = key;
             return second_minute;
               
        }
           
  }
   
void loop()
{
  char key = keypad.getKey();
   if (key != NO_KEY) {
     waitForKey();
   }
   
  int sensorPin = 0; 
int reading = analogRead(sensorPin); 

// converting that reading to voltage, for 3.3v arduino use 3.3
float voltage = reading * 5.0 / 1024;

// print out the voltage

// now print out the temperature
float temperatureC = (voltage - 0.5) * 100 ;
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
lcd.clear(); // clear LCD screen
lcd.setCursor(0,0);
lcd.print(hour, DEC);
lcd.print(":");
if (minute<10)
{
lcd.print("0");
}
lcd.print(minute, DEC);
lcd.print(":");
if (second<10)
{
lcd.print("0");
}
lcd.print(second, DEC);
lcd.print(" ");
lcd.print(temperatureC);
  lcd.print("C");
lcd.setCursor(0,1);
lcd.print(" ");
switch(dayOfWeek){
case 1:
lcd.print("Sun");
break;
case 2:
lcd.print("Mon");
break;
case 3:
lcd.print("Tue");
break;
case 4:
lcd.print("Wed");
break;

case 5:
lcd.print("Thu");
break;
case 6:
lcd.print("Fri");
break;
case 7:
lcd.print("Sat");
break;
}
lcd.print(" ");
lcd.print(dayOfMonth, DEC);
lcd.print("/");
lcd.print(month, DEC);
lcd.print("/20");
lcd.print(year, DEC);
delay(1000);
}

Автор:  michev [ Вто Авг 24, 2010 10:26 pm ]
Заглавие: 

Не знам точно на Ц ли се пише за ардуино, съответно не му знам и библиотеките му, но определенот ей тоя пасаж е лишен от всякаква логика
Код:
while(((key = keypad.getKey()) == NO_KEY) && ((millis()-_start_time) < 10000))
   {
   // Do nothing
          if(key==PRESSED) {
            lcd.print("f");
            countPressed++;
            setClock();
            return key;
          }
         
   }

ИФ-а никога няма да е true...
Може би си изпуснал преди ИФ-а да сложиш key= keypad.getKey(); ??
Има и друго - ако случайно клавиша е натиснат непосредствено след ИФ-а, то условието на уайла ще пропадне.

Автор:  morpheous87 [ Сря Авг 25, 2010 8:33 am ]
Заглавие: 

Дали може да се направи без функции, а с някаква поредица от if, switch и while?

Автор:  michev [ Сря Авг 25, 2010 10:24 am ]
Заглавие: 

.... може, що да не може

Автор:  morpheous87 [ Сря Авг 25, 2010 5:13 pm ]
Заглавие: 

Промених малко насоката за опита с матричната клавиатура. Мисля, че сегашният вариант е по-лесен за мен. Но имам проблем с един switch(). Първият switch() с case '#' работи добре, но вторият не. С него целта ми е да сортирам кой бутон е натиснат и да го съхраня под int-форма за да мога след това да образувам новите стойности. Не дава грешки, но на дисплея не изобразява нищо...
Код:
void loop()
{
  char key = keypad.getKey();
 
  if (key != NO_KEY){
    switch(key) {
      case '#':
    lcd.clear();
    lcd.print("Setting Mode");
    lcd.setCursor(0,1);
    lcd.print("   Hour:");
     delay(500);
     key = NO_KEY;
           int first_hour; 
           int second_hour;   
           unsigned long _start_time = millis();
           while(((key = keypad.getKey()) == NO_KEY) && ((millis()-_start_time) < 10000))
                     { // Do nothing
                     }
             if (key != NO_KEY) {
                      key = keypad.getKey();
                 /*     switch (key){
                       
                      case '0':
                      first_hour = 0;
                      lcd.print (first_hour);
                      delay (300);
                      break;
                     
                      case '1':
                      first_hour = 1;
                      lcd.print (first_hour);
                      delay (300);
                      break;
                     
                      case '2':
                      first_hour = 2;
                      lcd.print (first_hour);
                      delay (300);
                      break;
                     
                      case '3':
                      first_hour = 3;
                      lcd.print (first_hour);
                      delay (300);
                      break;
                     
                      case '4':
                      first_hour = 4;
                      lcd.print (first_hour);
                      delay (300);
                      break;
                     
                      case '5':
                      first_hour = 5;
                      lcd.print (first_hour);
                      delay (300);
                      break;
                     
                      case '6':
                      first_hour = 6;
                      lcd.print (first_hour);
                      delay (300);
                      break;
                     
                      case '7':
                      first_hour = 7;
                      lcd.print (first_hour);
                      delay (300);
                      break;
                     
                      case '8':
                      first_hour = 8;
                      lcd.print (first_hour);
                      delay (300);
                      break;
                     
                      case '9':
                      first_hour = 9;
                      lcd.print (first_hour);
                      delay (300);
                      break;
                      }
                      */

             }
             while(((key = keypad.getKey()) == NO_KEY) && ((millis()-_start_time) < 10000))
                     { // Do nothing
                     }
               if (key != NO_KEY) {
                      key = keypad.getKey();


P.S. С този кратък код изобразява на дисплея но вместо да изобрази каквото трябва изобразява две успоредни линии - || . Защо така?
Код:
while(((key = keypad.getKey()) == NO_KEY) && ((millis()-_start_time) < 10000))
                     { // Do nothing
                     }
               if (key != NO_KEY) {
                      key = keypad.getKey();
                      second_hour = key;
                     
                      lcd.print (key);
                      delay (300); 
            //      int new_hour = (first_hour&*10) + second_hour;   
               }

Автор:  morpheous87 [ Чет Авг 26, 2010 8:51 am ]
Заглавие: 

Има ли възможност и ако да, как да се върна назад в програмата ако долният if() ( if(new_minute>=60)), е вярно условието му?

Код:
if (key != NO_KEY) {
            lcd.clear();
            lcd.print("Minutes:");

          switch (key){

            case '0':
             first_minute = 0;
             lcd.print (first_minute);
             delay (300);
             break;

             case '1':
             first_minute = 1;
             lcd.print (first_minute);
             delay (300);
             break;

             case '2':
             first_minute = 2;
             lcd.print (first_minute);
             delay (300);
             break;

             case '3':
             first_minute = 3;
             lcd.print (first_minute);
             delay (300);
             break;

             case '4':
             first_minute = 4;
             lcd.print (first_minute);
             delay (300);
             break;

             case '5':
             first_minute = 5;
             lcd.print (first_minute);
             delay (300);
             break;

             case '6':
             first_minute = 6;
             lcd.print (first_minute);
             delay (300);
             break;

             case '7':
             first_minute = 7;
             lcd.print (first_minute);
             delay (300);
             break;

             case '8':
             first_minute = 8;
             lcd.print (first_minute);
             delay (300);
             break;

             case '9':
             first_minute = 9;
             lcd.print (first_minute);
             delay (300);
             break;
             }
         }
         _start_time = millis();
         while(((key = keypad.getKey()) == NO_KEY) && ((millis()-_start_time) < 10000))
            { // Do nothing
            }
         if (key != NO_KEY) {

          switch (key){
            case '0':
             second_minute = 0;
             lcd.print (second_minute);
             delay (300);
             break;

             case '1':
             second_minute = 1;
             lcd.print (second_minute);
             delay (300);
             break;

             case '2':
             second_minute = 2;
             lcd.print (second_minute);
             delay (300);
             break;

             case '3':
             second_minute = 3;
             lcd.print (second_minute);
             delay (300);
             break;

             case '4':
             second_minute = 4;
             lcd.print (second_minute);
             delay (300);
             break;

             case '5':
             second_minute = 5;
             lcd.print (second_minute);
             delay (300);
             break;

             case '6':
             second_minute = 6;
             lcd.print (second_minute);
             delay (300);
             break;

             case '7':
             second_minute = 7;
             lcd.print (second_minute);
             delay (300);
             break;

             case '8':
             second_minute = 8;
             lcd.print (second_minute);
             delay (300);
             break;

             case '9':
             second_minute = 9;
             lcd.print (second_minute);
             delay (300);
             break;
             }
             int new_minute = (first_minute*10) + second_minute;
             if(new_minute>=60) {
        // Тук искам да се върна на най-горният if()
         lcd.clear();
           lcd.print("Wrong");
           delay(2000);
          } 

Автор:  michev [ Чет Авг 26, 2010 10:48 am ]
Заглавие: 

Можеш с goto, но определено това е най - неправилния начин.
Помисли малко, как да си измениш кода, та да позлваш while, break, continue вместо goto или пък го разбий на функции.

Автор:  Predator_MF [ Чет Авг 26, 2010 11:22 am ]
Заглавие: 

Затваряш целия код в

Код:
while (!bValid)
{
   ....
   ....
   bValid = new_minute < 60;
}


Кода е и безмислено обемен, всички case ти правят едно и също нещо, можеш доста да го опростиш, вместо всички тия case '0', case '1',
нужно е само

Код:
if (key >= '0' && key <= '9')
{
      second_minute = key - 0x30; // от ASCII към BCD
      lcd.print (second_minute);
      delay (300);
}


Можеш още доста да опростиш нещата, като направиш second_minute просто pointer към това, което ще се наглася (горна минута, долна минута, секунда и пр) и като превключваш различните режими казваш на pointer да сочи към съответните променливи

Автор:  morpheous87 [ Чет Авг 26, 2010 1:04 pm ]
Заглавие: 

Predator_MF написа:
Затваряш целия код в

Код:
while (!bValid)
{
   ....
   ....
   bValid = new_minute < 60;
}


Кода е и безмислено обемен, всички case ти правят едно и също нещо, можеш доста да го опростиш, вместо всички тия case '0', case '1',
нужно е само

Код:
if (key >= '0' && key <= '9')
{
      second_minute = key - 0x30; // от ASCII към BCD
      lcd.print (second_minute);
      delay (300);
}


Можеш още доста да опростиш нещата, като направиш second_minute просто pointer към това, което ще се наглася (горна минута, долна минута, секунда и пр) и като превключваш различните режими казваш на pointer да сочи към съответните променливи

Адски МНОГО БЛАГОДАРЯ!!! Много ми помогна, тъкмо бях в безизходица защото 168цата се напълни и не оставаше място. :partyman:

Автор:  morpheous87 [ Чет Авг 26, 2010 7:32 pm ]
Заглавие: 

Как мога да огранича да ми изписва до 1 знак след десетичната запетая следният израз:
Код:
float temperatureC = (voltage - 0.5) * 100 ;


Това не успях много да го схвана... -
Код:
while (!bValid)
{
   ....
   ....
   bValid = new_minute < 60;
}

Автор:  Predator_MF [ Пет Авг 27, 2010 11:18 am ]
Заглавие: 

Там където принтваш temperatureC, вероятно ползваш sprintf, ползвай sprintf(str, "%.01f", temperatureC). Ако не се лъжа работи и в CCS с тоя формат, върти ми се нещо от сорта на 2.1w в главата ама даже не съм инсталирал CCS, че да го ровя в документацията.

Код:

// bValid ще е флаг който казва дали настройките са въведени правилно
bool bValid = false;
// ще се цикли в тоя bValid докато потребителя не въведе правилно всички настройки
// или ти в един момент чрез timeout не решиш да го направиш true или да викнеш break
while (!bValid)
{
   // на тия редове чакаш user input, сверяваш съответните проемнливи
   ....
   ....
   // на тоя ред проверяваш дали това което е въведено е валидно, това е просто пример
   bValid = new_minute < 60;
}

Автор:  michev [ Пет Авг 27, 2010 11:51 am ]
Заглавие: 

Ей тук има пример за форматирано изписване на числа в/у лцд.
За твоето конкретно изискване
Код:
fprintf(&lcdout, "Alive %.3f sec", seconds )

го направи на
Код:
fprintf(&lcdout, "Alive %.[b]2[/b]f sec", seconds )

Автор:  morpheous87 [ Пет Авг 27, 2010 5:07 pm ]
Заглавие: 

Aз изобразявам на дисплея по следният начин -
Код:
lcd.print(temperatureC);

Автор:  michev [ Пет Авг 27, 2010 5:38 pm ]
Заглавие: 

Щом си държиш на твойто си - използвай функцията, която Predator_MF ти е дал.
Нещо от тоя сорт трябва да ти е кода
Код:
unsigned char temperature[5];
sprintf(temperature, "%.2f", temperatureC );
lcd.print(temperature);

Автор:  morpheous87 [ Пет Авг 27, 2010 7:53 pm ]
Заглавие: 

michev написа:
Щом си държиш на твойто си - използвай функцията, която Predator_MF ти е дал.
Нещо от тоя сорт трябва да ти е кода
Код:
unsigned char temperature[5];
sprintf(temperature, "%.2f", temperatureC );
lcd.print(temperature);

Пробвах , не иска по този начин...

Страница 1 от 2 Часовете са според зоната UTC + 2 часа [ DST ]
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/