Programm mit zwei PCF8575 und LED_CLR an P16
// getestet mit Teensy 3.2
//#define DEBUGGING // Einkommentieren für die Serielle Ausgabe
#ifdef DEBUGGING
#define DEBUG_B(...) Serial.begin(__VA_ARGS__)
#define DEBUG_P(...) Serial.print(__VA_ARGS__)
#define DEBUG_L(...) Serial.println(__VA_ARGS__)
#else
#define DEBUG_B(...)
#define DEBUG_P(...)
#define DEBUG_L(...)
#endif
#include <Wire.h>
#include <Keyboard.h> // available when you chose Arduino Leonardo or Pro Micro or Teensy
#include <I2CKeyPad8x8.h> // https://github.com/RobTillaart/I2CKeyPad8x8
I2CKeyPad8x8 keyPad(0x20); // I²C-Adresse für PCF8575 mit Tastenmatrix
uint32_t vorhin;
enum prioritaet {FREI, DREH, MATRIX};
byte prio = FREI; // entweder Drehgeber oder Tastenmatrix darf einen Tastendruck erzeugen
byte aktKeyIndex = 255, altKeyIndex = 255;
#define NOT_SEQUENTIAL_PINOUT // P00 bis P07, P10 bis P17, nicht benutzt, dafür buttonLed benutzt
enum buttonLed {PB_A, PB_B, PB_C, PB_D, PB_E, PB_F, PB_X, PB_Y, LED_FAN, LED_LOCATE, LED_HIGHLIGHT, LED_ODDEVEN, LED_SINGLE, LED_SHIFT, LED_CLR};
#include <PCF8575.h> // https://github.com/xreef/PCF8575_library
PCF8575 pcf8575(0x21); // I²C-Adresse für PCF8575 mit Drehencoder-PushButton und LEDs
const bool pcfLEDein = LOW; // invertierte Logik, LEDs werden nach GND geschaltet zum Leuchten
const bool pcfLEDaus = !pcfLEDein;
const char NOKEY = ' '; // keine gedrückte Taste
#include <NoiascaEncoder.h> // TwoKnobs Example; download library from http://werner.rothschopf.net/microcontroller/202202_noiasca_encoder_en.htm
//const byte pinINT = 12; // INT von PCF8575 Matrix << agmue anpassen!
#include "mq_one.h"
struct Dreh : public Encoder
{
const byte pinPUSH;
const char keyL;
const char keyR;
const char nachricht;
char altKey;
Dreh (const byte pinA, const byte pinB, const byte pinPUSH, const char keyL, const char keyR, const char nachricht)
: Encoder(pinA, pinB), pinPUSH(pinPUSH), keyL(keyL), keyR(keyR), nachricht(nachricht), altKey(NOKEY)
{}
void init()
{
begin();
}
void tastenDruck(const char key, const char * txt)
{
prio = DREH;
if (altKey == NOKEY) {
Keyboard.press(KEY_LEFT_SHIFT);
Keyboard.press(key);
if (pinPUSH != PB_A) pcf8575.digitalWrite(LED_CLR, pcfLEDein); // Erinnerungs-LED einschalten, nicht bei Rotary A
DEBUG_P(nachricht); DEBUG_P(txt); DEBUG_P("\tkey: "); DEBUG_P(key);
if ( !pcf8575.digitalRead(pinPUSH) ) {
altKey = key;
DEBUG_P(F("\tTaster gedrückt"));
} else {
Keyboard.release(KEY_LEFT_SHIFT);
Keyboard.release(key);
prio = FREI;
DEBUG_P("\trelease key: "); DEBUG_P(key);
}
DEBUG_L();
}
}
void run()
{
//uint16_t bitMuster = 0;
switch (getDirection()) // the current direction: 1 (clockwise) or -1 (counter clockwise)
{
case 1:
tastenDruck(keyR, " rechtsrum");
break;
case -1:
tastenDruck(keyL, " linksrum");
break;
default:
if ( (altKey != NOKEY) && pcf8575.digitalRead(pinPUSH) ) {
Keyboard.release(KEY_LEFT_SHIFT);
Keyboard.release(altKey);
DEBUG_P("\taltKey: "); DEBUG_P(altKey); DEBUG_L(F("\tTaster losgelassen"));
altKey = NOKEY;
prio = FREI;
}
break;
}
}
};
Dreh dreh[]
{
// pinPUSH PB_A ... PB_Y
// | nachricht
//DT CLK | keyL keyR |
//| | | | | |
{ 23, 22, PB_A, '1', '2', 'A'}, // Rotary A << agmue DT und CLK anpassen!
{ 21, 20, PB_B, '3', '4', 'B'}, // Rotary B << agmue DT und CLK anpassen!
};
void loop() {
uint32_t jetzt = millis();
if (prio != MATRIX) for (Dreh &d : dreh) d.run();
if (prio != DREH) {
if ( jetzt - vorhin >= 100 ) { // Tastenabfrage nach Zeitintervall
vorhin = jetzt;
aktKeyIndex = keyPad.getKey(); // 0 bis 63 gültig; I2C_KEYPAD8x8_NOKEY = 64; I2C_KEYPAD8x8_FAIL = 65
if (aktKeyIndex != altKeyIndex) {
if (altKeyIndex < I2C_KEYPAD8x8_NOKEY) {
if ( matrix[altKeyIndex].modSC == 'S' ) Keyboard.release(KEY_LEFT_SHIFT);
if ( matrix[altKeyIndex].modSC == 'C' ) Keyboard.release(KEY_LEFT_CTRL);
Keyboard.release( matrix[altKeyIndex].key );
DEBUG_P(millis()); DEBUG_P(F("\taltKeyIndex: ")); DEBUG_P(altKeyIndex);
DEBUG_P(F("\tTaste: ")); DEBUG_P(matrix[altKeyIndex].modSC); DEBUG_L(matrix[altKeyIndex].key);
prio = FREI;
}
altKeyIndex = aktKeyIndex;
if (aktKeyIndex < I2C_KEYPAD8x8_NOKEY) {
if ( matrix[aktKeyIndex].modSC == 'S' ) Keyboard.press(KEY_LEFT_SHIFT);
if ( matrix[aktKeyIndex].modSC == 'C' ) Keyboard.press(KEY_LEFT_CTRL);
Keyboard.press( matrix[aktKeyIndex].key );
DEBUG_P(millis()); DEBUG_P(F("\taktKeyIndex: ")); DEBUG_P(aktKeyIndex);
DEBUG_P(F("\tTaste: ")); DEBUG_P(matrix[aktKeyIndex].modSC); DEBUG_L(matrix[aktKeyIndex].key);
prio = MATRIX;
}
}
}
}
static uint32_t blinkZeit = 0;
static bool anAus = pcfLEDaus;
if (jetzt - blinkZeit >= 1000) {
blinkZeit = jetzt;
pcf8575.digitalWrite(LED_FAN, anAus);
pcf8575.digitalWrite(LED_LOCATE, !anAus);
pcf8575.digitalWrite(LED_HIGHLIGHT, anAus);
pcf8575.digitalWrite(LED_ODDEVEN, !anAus);
pcf8575.digitalWrite(LED_SINGLE, anAus);
pcf8575.digitalWrite(LED_SHIFT, !anAus);
anAus = !anAus;
}
}
void setup() {
Wire.begin();
Wire.setClock(400000);
DEBUG_B(115200);
delay(5000); // zur Sicherheit, sollten die Tastendrücke spinnen
DEBUG_L(F("\nStart"));
if ( !keyPad.begin() ) DEBUG_L(F("\nERROR: cannot communicate to keypad.\nPlease reboot.\n"));
for (byte j = PB_A; j <= PB_Y; j++) pcf8575.pinMode(j, INPUT);
for (byte j = LED_FAN; j <= LED_CLR; j++) pcf8575.pinMode(j, OUTPUT);
pcf8575.begin();
//pinMode(pinINT, INPUT_PULLUP);
for (Dreh &d : dreh) d.init();
}
mq_one.h unverändert
struct Matrix
{
char modSC; // Modifier 'S' für Shift, 'C' für Ctrl
char key;
};
Matrix matrix[]
{
//modSC, key
//{' ', 'p'}, // Taste pur
//{'S', 'p'}, // Taste mit Shift
//{'C', 'p'} // Taste mit Ctrl
{' ', 'a'}, // 0
{' ', 'b'}, // 1
{' ', 'c'}, // 2
{' ', 'd'}, // 3
{' ', 'e'}, // 4
{' ', 'f'}, // 5
{' ', 'g'}, // 6
{' ', 'h'}, // 7
{' ', 'i'}, // 8
{' ', 'j'}, // 9
{' ', 'k'}, // 10
{' ', 'l'}, // 11
{' ', 'm'}, // 12
{' ', 'n'}, // 13
{' ', 'o'}, // 14
{' ', 'p'}, // 15
{' ', 'q'}, // 16
{' ', 'r'}, // 17
{' ', 's'}, // 18
{' ', 't'}, // 19
{' ', 'u'}, // 20
{' ', 'v'}, // 21
{' ', 'w'}, // 22
{' ', 'x'}, // 23
{' ', 'y'}, // 24
{' ', 'z'}, // 25
{' ', '0'}, // 26
{' ', '1'}, // 27
{' ', '2'}, // 28
{' ', '3'}, // 29
{' ', '4'}, // 30
{' ', '5'}, // 31
{' ', '6'}, // 32
{' ', '7'}, // 33
{' ', '8'}, // 34
{' ', '9'}, // 35
{' ', 'A'}, // 36
{' ', 'B'}, // 37
{' ', 'C'}, // 38
{' ', 'D'}, // 39
{' ', 'E'}, // 40
{' ', 'F'}, // 41
{' ', 'G'}, // 42
{' ', 'H'}, // 43
{' ', 'I'}, // 44
{' ', 'J'}, // 45
{' ', 'K'}, // 46
{' ', 'L'}, // 47
{' ', 'M'}, // 48
{' ', 'N'}, // 49
{' ', 'O'}, // 50
{' ', 'P'}, // 51
{' ', 'Q'}, // 52
{' ', 'R'}, // 53
{' ', 'S'}, // 54
{' ', 'T'}, // 55
{' ', 'U'}, // 56
{' ', 'V'}, // 57
{' ', 'W'}, // 58
{' ', 'X'}, // 59
{' ', 'Y'}, // 60
{'S', '1'}, // 61
{'S', '3'}, // 62
{'S', '4'}, // 63
};