Отговори на тема  [ 20 мнения ]  Отиди на страница 1, 2  Следваща
Сверяване чрез матрична клавиатура 
Автор Съобщение
Ранг: Ориентиран
Ранг: Ориентиран
Аватар

Регистриран на: Съб Авг 07, 2010 8:47 pm
Мнения: 239
Местоположение: София
Мнение Сверяване чрез матрична клавиатура
Здравейте, направил съм програмка за Ардуино ( по-точно съм събрал на едно няколко по-малки програмки). Програмата се състои в изобразване на часовник, дата, ден и температура. Сензора е ТМР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);
}


Последна промяна morpheous87 на Вто Авг 24, 2010 10:39 pm, променена общо 1 път



Вто Авг 24, 2010 9:44 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Сря Юли 11, 2007 10:16 am
Мнения: 1730
Мнение 
Не знам точно на Ц ли се пише за ардуино, съответно не му знам и библиотеките му, но определенот ей тоя пасаж е лишен от всякаква логика
Код:
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(); ??
Има и друго - ако случайно клавиша е натиснат непосредствено след ИФ-а, то условието на уайла ще пропадне.


Вто Авг 24, 2010 10:26 pm
Профил
Ранг: Ориентиран
Ранг: Ориентиран
Аватар

Регистриран на: Съб Авг 07, 2010 8:47 pm
Мнения: 239
Местоположение: София
Мнение 
Дали може да се направи без функции, а с някаква поредица от if, switch и while?


Сря Авг 25, 2010 8:33 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Сря Юли 11, 2007 10:16 am
Мнения: 1730
Мнение 
.... може, що да не може


Сря Авг 25, 2010 10:24 am
Профил
Ранг: Ориентиран
Ранг: Ориентиран
Аватар

Регистриран на: Съб Авг 07, 2010 8:47 pm
Мнения: 239
Местоположение: София
Мнение 
Промених малко насоката за опита с матричната клавиатура. Мисля, че сегашният вариант е по-лесен за мен. Но имам проблем с един 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;   
               }


Сря Авг 25, 2010 5:13 pm
Профил
Ранг: Ориентиран
Ранг: Ориентиран
Аватар

Регистриран на: Съб Авг 07, 2010 8:47 pm
Мнения: 239
Местоположение: София
Мнение 
Има ли възможност и ако да, как да се върна назад в програмата ако долният 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);
          } 


Чет Авг 26, 2010 8:51 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Сря Юли 11, 2007 10:16 am
Мнения: 1730
Мнение 
Можеш с goto, но определено това е най - неправилния начин.
Помисли малко, как да си измениш кода, та да позлваш while, break, continue вместо goto или пък го разбий на функции.


Чет Авг 26, 2010 10:48 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Чет Окт 07, 2004 1:22 pm
Мнения: 1949
Местоположение: София
Мнение 
Затваряш целия код в

Код:
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 да сочи към съответните променливи


Чет Авг 26, 2010 11:22 am
Профил
Ранг: Ориентиран
Ранг: Ориентиран
Аватар

Регистриран на: Съб Авг 07, 2010 8:47 pm
Мнения: 239
Местоположение: София
Мнение 
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:


Чет Авг 26, 2010 1:04 pm
Профил
Ранг: Ориентиран
Ранг: Ориентиран
Аватар

Регистриран на: Съб Авг 07, 2010 8:47 pm
Мнения: 239
Местоположение: София
Мнение 
Как мога да огранича да ми изписва до 1 знак след десетичната запетая следният израз:
Код:
float temperatureC = (voltage - 0.5) * 100 ;


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


Чет Авг 26, 2010 7:32 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Чет Окт 07, 2004 1:22 pm
Мнения: 1949
Местоположение: София
Мнение 
Там където принтваш 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;
}


Пет Авг 27, 2010 11:18 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Сря Юли 11, 2007 10:16 am
Мнения: 1730
Мнение 
Ей тук има пример за форматирано изписване на числа в/у лцд.
За твоето конкретно изискване
Код:
fprintf(&lcdout, "Alive %.3f sec", seconds )

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


Пет Авг 27, 2010 11:51 am
Профил
Ранг: Ориентиран
Ранг: Ориентиран
Аватар

Регистриран на: Съб Авг 07, 2010 8:47 pm
Мнения: 239
Местоположение: София
Мнение 
Aз изобразявам на дисплея по следният начин -
Код:
lcd.print(temperatureC);


Пет Авг 27, 2010 5:07 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

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


Пет Авг 27, 2010 5:38 pm
Профил
Ранг: Ориентиран
Ранг: Ориентиран
Аватар

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

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


Пет Авг 27, 2010 7:53 pm
Профил
Покажи мненията от миналия:  Сортирай по  
Отговори на тема   [ 20 мнения ]  Отиди на страница 1, 2  Следваща

Кой е на линия

Потребители разглеждащи този форум: 0 регистрирани и 4 госта


Вие не можете да пускате нови теми
Вие не можете да отговаряте на теми
Вие не можете да променяте собственото си мнение
Вие не можете да изтривате собствените си мнения
Вие не можете да прикачвате файл

Търсене:
Иди на:  
cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by ST Software for PTF.
Хостинг и Домейни