BCD-Code Tastenabfrage, Dezimalzahl Ausgabe

Arduino-Uno, LCD-2004, 4x4 Tastenfeld (0...F = 1...32768)
Um meinen Enkeln den BCD-Code näher zu bringen wollte ich mit 16 Tasten den BCD-Code nachemfinden und eine zugehörige Dezimalzahl auf dem LCD-Display anzeigen. Hat einer so ein Programm bereits auf Lager oder wie setzt man so ein Programm zusammen. Allein die Tastenabfrage stellt mich vor unlösbare Probleme, da in der Regel nach der 1. Taste das Programm die Eingabe blockiert und das Programm fortsetzt.
Meine Vorstellung ist 0...F auf dem Display in 4 Gruppen darzustellen, darunter L oder H (16 stellige Binärzahl), unter den 4 Binär-Gruppen folgt die Hex Zahl in 2 Zweiergruppen und ganz unten der summierten Dezimalwert aller 16 Bits. Das L oder H unter den 0...F muß sich mit der zugehörigen Taste umschalten lassen, so das jede Zahl bis 65535 anzeigbar ist.
So ist es sicherlich auch vorstellbar wie man mit 10 Fingern bereits bis 2047 zählen könnte.
Wie strukturiert man so ein Programm und wie ordne ich die einzelnen Tasten den Bimärwerten zu.
Hab zwar vor Jahrzehnten "C=+4" Basic ganz gut beherrscht doch davon ist leider nicht viel übrig. Und C++ ist für einen Rentner leider nicht mehr so einfach (mit 20 sah die Welt noch anders aus)...

das habe ich nicht verstanden

oder "customkeypad"

/* @file CustomKeypad.pde
|| @version 1.0
|| @author Alexander Brevig
|| @contact alexanderbrevig@gmail.com
||
|| @description
|| | Demonstrates changing the keypad size and key values.
|| #
*/
#include <Keypad.h>

const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns
//define the cymbols on the buttons of the keypads
char hexaKeys[ROWS][COLS] = {
  {'0','1','2','3'},
  {'4','5','6','7'},
  {'8','9','A','B'},
  {'C','D','E','F'}
};
byte rowPins[ROWS] = {3, 2, 1, 0}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {7, 6, 5, 4}; //connect to the column pinouts of the keypad

//initialize an instance of class NewKeypad
Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS); 

void setup(){
  Serial.begin(9600);
}
  
void loop(){
  char customKey = customKeypad.getKey();
  
  if (customKey){
    Serial.println(customKey);
  }
}

Im englischen Teil des Forum müssen die Beiträge und Diskussionen in englischer Sprache verfasst werden.
Deswegen wurde diese Diskussion in den deutschen Teil des Forums verschoben.
mfg ein Moderator.

welche Regel? Buch, Paragraph? Es gibt nur Ratschläge die man besser befolgen soll und Syntax das zwingend erforderlich ist. Ansonsten steht ein Programmierer auf freiem Fuß.

Der Programm liest Tasten eine nach den anderen. Jeder Taste entspricht ein Code, der wird eindeutig im Programm definiert. Meistens werden sie als irgendein Zeichen oder Buchstabe dargestellt. Ansonsten kann man sie als Bits aus dem Eingang Register gelesen werden.

auf einem Simulator könnte man sein Projekt austesten bevor man alles kaufen muss.
Z.B. hier

Auf der Seite im Tab "diagram.json" kann man Werte manipulieren und z.B. aus 1602 den 2004 machen indem man "wokwi-lcd1602" durch "wokwi-lcd2004" ersetzt.

UPD:
diagram.json

{
  "version": 1,
  "author": "Uri Shaked",
  "editor": "wokwi",
  "parts": [
    { "type": "wokwi-arduino-nano", "id": "uno", "top": 287.21, "left": 96.13, "attrs": {} },
    {
      "type": "wokwi-membrane-keypad",
      "id": "keypad",
      "top": 100,
      "left": 360,
      "attrs": {
        "keys": [ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F" ]
      }
    },
    { "type": "wokwi-lcd2004", "id": "lcd", "top": -33.39, "left": 5.96, "attrs": {} },
    {
      "type": "wokwi-resistor",
      "id": "r1",
      "top": 145.17,
      "left": 220,
      "attrs": { "value": "220" }
    }
  ],
  "connections": [
    [ "uno:GND.1", "lcd:VSS", "black", [ "v-51", "*", "h0", "v18" ] ],
    [ "uno:GND.1", "lcd:K", "black", [ "v-51", "h-66.17", "v-47.77", "h7.5" ] ],
    [ "uno:GND.1", "lcd:RW", "black", [ "v-51", "*", "h0", "v18" ] ],
    [ "uno:5V", "lcd:VDD", "red", [ "v16", "h-16" ] ],
    [ "uno:5V", "r1:2", "red", [ "v16", "h-118", "v-198.28", "h175.37" ] ],
    [ "r1:1", "lcd:A", "pink", [] ],
    [ "uno:12", "lcd:RS", "blue", [ "v-16", "*", "h0", "v20" ] ],
    [ "uno:11", "lcd:E", "purple", [ "v-20", "*", "h0", "v20" ] ],
    [ "uno:10", "lcd:D4", "green", [ "v-24", "*", "h0", "v20" ] ],
    [ "uno:9", "lcd:D5", "brown", [ "v-28", "*", "h0", "v20" ] ],
    [ "uno:8", "lcd:D6", "gold", [ "v-32", "*", "h0", "v20" ] ],
    [ "uno:7", "lcd:D7", "gray", [ "v-36", "*", "h0", "v20" ] ],
    [ "uno:A3", "keypad:C1", "brown", [ "v76", "*", "h0", "v0" ] ],
    [ "uno:A2", "keypad:C2", "gray", [ "v80", "*", "h0", "v0" ] ],
    [ "uno:A1", "keypad:C3", "orange", [ "v84", "*", "h0", "v0" ] ],
    [ "uno:A0", "keypad:C4", "pink", [ "v88", "*", "h0", "v0" ] ],
    [ "uno:5", "keypad:R1", "blue", [ "v-34", "h96", "*", "v12" ] ],
    [ "uno:4", "keypad:R2", "green", [ "v-30", "h80", "*", "v16" ] ],
    [ "uno:3", "keypad:R3", "purple", [ "v-26", "h64", "*", "v20" ] ],
    [ "uno:2", "keypad:R4", "gold", [ "v-22", "h48", "*", "v24" ] ]
  ],
  "dependencies": {}
}

Sketch dazu

#include <LiquidCrystal.h>
#include <Keypad.h>

LiquidCrystal lcd(12, 11, 10, 9, 8, 7);

const byte KEYPAD_ROWS = 4;
const byte KEYPAD_COLS = 4;
byte rowPins[KEYPAD_ROWS] = {5, 4, 3, 2};
byte colPins[KEYPAD_COLS] = {A3, A2, A1, A0};
char keys[KEYPAD_ROWS][KEYPAD_COLS] = {
  {'0', '1', '2', '3'},
  {'4', '5', '6', '7'},
  {'8', '9', 'A', 'B'},
  {'C', 'D', 'E', 'F'}
};

Keypad keypad(makeKeymap(keys), rowPins, colPins, KEYPAD_ROWS, KEYPAD_COLS);


void setup() {
    lcd.begin(20, 4);
  lcd.clear();
}

void loop() {
  static byte pos=0;

  char key = keypad.getKey();
  if (key) {
    lcd.setCursor(10*(pos%2),pos/2);
    lcd.print(key);
    lcd.print(' ');
    if(key>'9')key-=7;
    key-='0';
    for(byte i=4;i>0;i--)lcd.print((key&1<<(i-1))>0);
    if(++pos==4)pos=0;
  }
}

Was verstehst du unter BCD?

dem Endbenutzer ist sowieso nicht sichbar ob drin ein Integer oder BCD genutzt war, da es identisch auf dem Bildschirm aussieht.

Das habe ich auch nicht verstanden. Was hat BCD in all dem zu tun?
Grüße Uwe

Die Aufgabe oben lautet anders.

   F   F   F   F
1111111111111111
      FF      FF
           65535

-> hier uint16_t
@roland_0815
Der BCD-Teil ist ein eine Untermenge des Tupel.
Wenn Du auf BCD beschränkt bleiben willst, kannst Du alles ab 0xA nicht mehr darstellen.

1 Like

Ups, das nächste Problem, das "LiquidCrystal_I2C.h" harmoniert nicht so richtig mit dem "LiquidCrystal lcd(12, 11, 10, 9, 8, 7);"
wenn man es ersetzt um die I2C Schnittstelle anzusteuern kommt Mist raus.
Bisher habe ich die LCD-Ausgabe immer erfolgreich mit "lcd.setCursor(0, 0); lcd.print(0);" usw. gemacht
das Display sollte so etwa aussehen:

0123 4567 89AB CDEF
HLLH HLLL LLLL LLLL
51 00
13

Also oben die BCD-Code Ziffer wie auf der Tastatur, darunter der Dualzahl-Wert dann kommt die Hexadezimalzahl und unten die Dezimalzahl. Doch wenn ich das so betrachte ist es bestimmt besser von rechts nach links den Code aufzuschlüsseln - oder? Wie ist die Ausgabe ?

NEIN! BCD hört bei 0x9 auf.
Du hast einen HEX-Wert der von 0x0 bis 0xF geht.
Der Sinn der oberen Reihe erschliesst sich mir noch nciht - aber das ist egal.

Dann ist mir noch nicht klar, wie Du auf die Werte kommst.
Der Binärwert gibt keine 51 00 und auch keine 13 aus.
Was soll denn da stehen?

Wen du ein I2C LCD hast ( Nur 4 Drähte VCC,GND, SDA, SCL ) funktioniert das nicht mit LiquidCrystal lcd(12, 11, 10, 9, 8, 7);
Zeige mall dein Sketsch womit du die Probleme hast

#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4); //  addresse 0x3F schreiben wenn mit 0x27 nicht klappt
#include <Keypad.h>

char H[3];
char L[3];
const byte KEYPAD_ROWS = 4;
const byte KEYPAD_COLS = 4;
byte rowPins[KEYPAD_ROWS] = {5, 4, 3, 2};
byte colPins[KEYPAD_COLS] = {A3, A2, A1, A0};
char keys[KEYPAD_ROWS][KEYPAD_COLS] = {
  {'0', '1', '2', '3'},
  {'4', '5', '6', '7'},
  {'8', '9', 'A', 'B'},
  {'C', 'D', 'E', 'F'}
};

Keypad keypad(makeKeymap(keys), rowPins, colPins, KEYPAD_ROWS, KEYPAD_COLS);


void setup() {
  lcd.init();
  lcd.clear();
}

void loop() {
  static byte pos = 0;
  static uint16_t Total = 0;
  char key = keypad.getKey();
  if (key) {
    lcd.setCursor(5 * pos + 3, 1);
    lcd.print(key);

    lcd.setCursor(5 * pos, 0);
    if (key > '9')key -= 7;
    key -= '0';
    for (byte i = 4; i > 0; i--)lcd.print((key & 1 << (i - 1)) ?'1':'0'); // hier kann man H/L schreiben
    Total = Total & ~(0b1111 << 4 * (3 - pos));
    Total = Total | (key << 4 * (3 - pos));
    sprintf (H, "%02X", Total >> 8);
    sprintf (L, "%02X", Total & 0xFF);
    lcd.setCursor(7, 2);
    lcd.print(H);
    lcd.setCursor(17, 2);
    lcd.print(L);

    lcd.setCursor(12, 3);
    lcd.print("     ");
    lcd.setCursor(12, 3);
    lcd.print(Total);

    if (++pos == 4)pos = 0;
  }
}
1 Like

manchmal auch

lcd.begin();

Es gibt's um die 10 "LiquidCrystal_I2C.h"

Sicher dass das nicht 4 sein muss?

ich? ja, ich bin sicher.

Die Anzeige und die Tasteneingabe sind schon einmal da, ich danke Euch, nur mit der Logik hapert es noch einwenig. Mal sehen ob ich es noch hin bekomme. Jetzt wird mit jeder Tasteneigabe der BCD-Wert in die Hexadezimalzahl die Reihe rum eingetragen. Ich wollte jedoch L und H in der 2. Zeile ändern und zwar nur das Bit entsprechend der Wertigkeit der Taste.
Also oben ist 0...F und darunter wird mit L oder H angegeben ob das entsprechende Bit Ein oder Aus ist. Wenn also die Taste A gedrückt wird soll sich unter A das L in H ändern und bei erneutem drücken wieder in L.
Diese H...L Dualzahl soll dann darunter (wie jetzt) in Hexadezimal und unten in Dezimal angezeigt werden.

#include "Keypad.h" //Pin 2-9 
#include <LiquidCrystal_I2C.h> 
LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 20, 4); // mit HW61 Modul, Pin A4-SDA,A5-SCL,-,+5V

char H[3];
char L[3];
const byte KEYPAD_ROWS = 4;
const byte KEYPAD_COLS = 4;
byte rowPins[KEYPAD_ROWS] = {2, 3, 4, 5};
byte colPins[KEYPAD_COLS] = {6, 7, 8, 9};
char keys[KEYPAD_ROWS][KEYPAD_COLS] = {
  {'0', '1', '2', '3'},
  {'4', '5', '6', '7'},
  {'8', '9', 'A', 'B'},
  {'C', 'D', 'E', 'F'}
};

Keypad keypad(makeKeymap(keys), rowPins, colPins, KEYPAD_ROWS, KEYPAD_COLS);


void setup() {
  lcd.init();
  lcd.backlight();
  lcd.clear();
}

void loop() {
  static byte pos = 0;
  static uint16_t Total = 0;
  char key = keypad.getKey();
  if (key) {
    lcd.setCursor(5 * pos + 3, 1);
    lcd.print(key);

    lcd.setCursor(5 * pos, 0);
    if (key > '9')key -= 7;
    key -= '0';
    for (byte i = 4; i > 0; i--)lcd.print((key & 1 << (i - 1)) ?'1':'0'); // hier kann man H/L schreiben
    Total = Total & ~(0b1111 << 4 * (3 - pos));
    Total = Total | (key << 4 * (3 - pos));
    sprintf (H, "%02X", Total >> 8);
    sprintf (L, "%02X", Total & 0xFF);
    lcd.setCursor(7, 2);
    lcd.print(H);
    lcd.setCursor(17, 2);
    lcd.print(L);

    lcd.setCursor(12, 3);
    lcd.print("     ");
    lcd.setCursor(12, 3);
    lcd.print(Total);

    if (++pos == 4)pos = 0;
  }
}

Könnten Sie es bildlich erklären?
hier ist ein Ausgangsbild für Sie:
изображение

das mit der 0 und 1 ist besser als L und H

Bildlich sollte das Display etwa so wie oben #10 aussehen

FEDC BA98 7654 3210
0000 0010 0000 0001
_________02 01
_________513

(die Striche braucht nur der Editor hier als Platzhalter)

diese Ansicht ist zwar etwas ungewöhnlich, doch die Ausgabe hier erfordert ein Umdenken (...DCBA98... statt ...89ABCD...) sonst würden die darunter liegenden Zahlwerte nicht übereinstimmen