Merge branch 'keyboard_dev'

This commit is contained in:
Alexander Richter 2023-09-23 17:05:55 +02:00
commit 363e8582ef
3 changed files with 159 additions and 24 deletions

View File

@ -16,6 +16,7 @@
- digital Inputs - digital Inputs
- digital Outputs - digital Outputs
- Matrix Keypad - Matrix Keypad
- Multiplexed LEDs
- Quadrature encoders - Quadrature encoders
- Joysticks - Joysticks
@ -32,9 +33,10 @@
binary encoded Selector = 'K' -write only -Pin State: 0-32 binary encoded Selector = 'K' -write only -Pin State: 0-32
rotary encoder = 'R' -write only -Pin State: up/ down / -2147483648 to 2147483647 rotary encoder = 'R' -write only -Pin State: up/ down / -2147483648 to 2147483647
joystick = 'R' -write only -Pin State: up/ down / -2147483648 to 2147483647 joystick = 'R' -write only -Pin State: up/ down / -2147483648 to 2147483647
multiplexed LEDs = 'M' -read only -Pin State: 0,1
Keyboard Input: Keyboard Input:
Matrix Keypad = 'M' -write only -Pin State: Number of Matrix Key. Matrix Keypad = 'M' -write only -Pin State: 0,1
Communication Status = 'E' -read/Write -Pin State: 0:0 Communication Status = 'E' -read/Write -Pin State: 0:0
@ -77,7 +79,7 @@ Communication Status = 'E' -read/Write -Pin State: 0:0
int sInPinmap[] = {10}; int sInPinmap[] = {10};
#endif #endif
//#define OUTPUTS //Use Arduino IO's as Outputs. Define how many Outputs you want in total and then which Pins you want to be Outputs. #define OUTPUTS //Use Arduino IO's as Outputs. Define how many Outputs you want in total and then which Pins you want to be Outputs.
#ifdef OUTPUTS #ifdef OUTPUTS
const int Outputs = 2; //number of outputs const int Outputs = 2; //number of outputs
int OutPinmap[] = {11,12}; int OutPinmap[] = {11,12};
@ -89,7 +91,7 @@ Communication Status = 'E' -read/Write -Pin State: 0:0
int PwmOutPinmap[] = {12,11}; int PwmOutPinmap[] = {12,11};
#endif #endif
#define AINPUTS //Use Arduino ADC's as Analog Inputs. Define how many Analog Inputs you want in total and then which Pins you want to be Analog Inputs. //#define AINPUTS //Use Arduino ADC's as Analog Inputs. Define how many Analog Inputs you want in total and then which Pins you want to be Analog Inputs.
//Note that Analog Pin numbering is different to the Print on the PCB. //Note that Analog Pin numbering is different to the Print on the PCB.
#ifdef AINPUTS #ifdef AINPUTS
const int AInputs = 1; const int AInputs = 1;
@ -113,7 +115,7 @@ Then in the Array, {which Pin, How many Positions}
Note that Analog Pin numbering is different to the Print on the PCB. Note that Analog Pin numbering is different to the Print on the PCB.
*/ */
#define LPOTIS //#define LPOTIS
#ifdef LPOTIS #ifdef LPOTIS
const int LPotis = 2; const int LPotis = 2;
const int LPotiPins[LPotis][2] = { const int LPotiPins[LPotis][2] = {
@ -125,7 +127,7 @@ Note that Analog Pin numbering is different to the Print on the PCB.
#define BINSEL //Support of an Rotating Knob that was build in my Machine. It encodes 32 Positions with 5 Pins in Binary. This will generate 32 Pins in LinuxCNC Hal. //#define BINSEL //Support of an Rotating Knob that was build in my Machine. It encodes 32 Positions with 5 Pins in Binary. This will generate 32 Pins in LinuxCNC Hal.
#ifdef BINSEL #ifdef BINSEL
const int BinSelKnobPins[] = {2,6,4,3,5}; //1,2,4,8,16 const int BinSelKnobPins[] = {2,6,4,3,5}; //1,2,4,8,16
#endif #endif
@ -166,7 +168,7 @@ Encoder Encoder1(31,33); //A,B Pin
const int QuadEncSig[] = {2,2}; //define wich kind of Signal you want to generate. const int QuadEncSig[] = {2,2}; //define wich kind of Signal you want to generate.
//1= send up or down signal (typical use for selecting modes in hal) //1= send up or down signal (typical use for selecting modes in hal)
//2= send position signal (typical use for MPG wheel) //2= send position signal (typical use for MPG wheel)
const int QuadEncMp[] = {1,4}; //some Rotary encoders send multiple Electronical Impulses per mechanical pulse. How many Electrical impulses are send for each mechanical Latch? const int QuadEncMp[] = {4,4}; //some Rotary encoders send multiple Electronical Impulses per mechanical pulse. How many Electrical impulses are send for each mechanical Latch?
#endif #endif
@ -263,21 +265,45 @@ So you could attach a QWERT* Keyboard to the arduino and you will be able to wri
*/ */
//#define KEYPAD //#define KEYPAD
#ifdef KEYPAD #ifdef KEYPAD
const int numRows = 4; // Define the number of rows in the matrix const int numRows = 4; // Define the number of rows in the matrix
const int numCols = 4; // Define the number of columns in the matrix const int numCols = 4; // Define the number of columns in the matrix
// Define the pins connected to the rows and columns of the matrix // Define the pins connected to the rows and columns of the matrix
const int rowPins[numRows] = {2, 3, 4, 5}; const int rowPins[numRows] = {2, 3, 4, 5};
const int colPins[numCols] = {6, 7, 8, 9}; const int colPins[numCols] = {6, 7, 8, 9};
int keys[numRows][numCols] = {0}; int keys[numRows][numCols] = {0};
int lastKey= -1; int lastKey= -1;
#endif #endif
//#define MULTIPLEXLEDS // Special mode for Multiplexed LEDs. This mode is experimental and implemented to support Matrix Keyboards with integrated Key LEDs.
// check out this thread on LinuxCNC Forum for context. https://forum.linuxcnc.org/show-your-stuff/49606-matrix-keyboard-controlling-linuxcnc
// for Each LED an Output Pin is generated in LinuxCNC.
//If your Keyboard shares pins with the LEDs, you have to check polarity.
//rowPins[numRows] = {} are Pullup Inputs
//colPins[numCols] = {} are GND Pins
//the matrix keyboard described in the thread shares GND Pins between LEDs and KEys, therefore LedGndPins[] and colPins[numCols] = {} use same Pins.
#ifdef MULTIPLEXLEDS
const int numVccPins = 8; // Number of rows in the matrix
const int numGndPins = 8; // Number of columns in the matrix
const int LedVccPins[] = {30,31,32,33,34,35,36,37}; // Arduino pins connected to rows
const int LedGndPins[] = {40,41,42,43,44,45,46,47}; // Arduino pins connected to columns
// Define the LED matrix
int ledStates[numVccPins*numGndPins] = {0};
unsigned long previousMillis = 0;
const unsigned long interval = 500; // Time (in milliseconds) per LED display
int currentLED = 0;
#endif
//#define DEBUG //#define DEBUG
//####################################### END OF CONFIG ########################### //####################################### END OF CONFIG ###########################
@ -319,6 +345,9 @@ const int debounceDelay = 50;
#ifdef KEYPAD #ifdef KEYPAD
byte KeyState = 0; byte KeyState = 0;
#endif #endif
#ifdef MULTIPLEXLEDS
byte KeyLedStates[numVccPins*numGndPins];
#endif
#if QUADENCS == 1 #if QUADENCS == 1
const int QuadEncs = 1; const int QuadEncs = 1;
#endif #endif
@ -467,13 +496,15 @@ void loop() {
#ifdef QUADENC #ifdef QUADENC
readEncoders(); //read Encoders & send data readEncoders(); //read Encoders & send data
#endif #endif
#ifdef JOYSTICK #ifdef JOYSTICK
readJoySticks(); //read Encoders & send data readJoySticks(); //read Encoders & send data
#endif #endif
#ifdef MULTIPLEXLEDS
multiplexLeds();// cycle through the 2D LED Matrix}
#endif
} }
#ifdef JOYSTICK #ifdef JOYSTICK
void readJoySticks() { void readJoySticks() {
@ -563,9 +594,7 @@ void readEncoders(){
} }
#endif #endif
void initialiseIO(){
}
void comalive(){ void comalive(){
if(lastcom == 0){ //no connection yet. send E0:0 periodicly and wait for response if(lastcom == 0){ //no connection yet. send E0:0 periodicly and wait for response
while (lastcom == 0){ while (lastcom == 0){
@ -662,7 +691,9 @@ void reconnect(){
#ifdef BINSEL #ifdef BINSEL
readAbsKnob(); //read ABS Encoder & send data readAbsKnob(); //read ABS Encoder & send data
#endif #endif
#ifdef MULTIPLEXLEDS
multiplexLeds(); //Flash LEDS.
#endif
connectionState = 1; connectionState = 1;
@ -862,7 +893,7 @@ int readAbsKnob(){
#ifdef KEYPAD #ifdef KEYPAD
void readKeypad(){ void readKeypad(){
//detect if Button is Pressed //detect if Button is Pressed
for (int col = 0; col < numCols; col++) { for (int col = 0; col < numCols; col++) {
pinMode(colPins[col], OUTPUT); pinMode(colPins[col], OUTPUT);
digitalWrite(colPins[col], LOW); digitalWrite(colPins[col], LOW);
// Read the state of the row pins // Read the state of the row pins
@ -873,6 +904,7 @@ void readKeypad(){
sendData('M',keys[row][col],1); sendData('M',keys[row][col],1);
lastKey = keys[row][col]; lastKey = keys[row][col];
row = numRows; row = numRows;
} }
if (digitalRead(rowPins[row]) == HIGH && lastKey == keys[row][col]) { if (digitalRead(rowPins[row]) == HIGH && lastKey == keys[row][col]) {
// The Last Button has been unpressed // The Last Button has been unpressed
@ -885,6 +917,54 @@ void readKeypad(){
// Set the column pin back to input mode // Set the column pin back to input mode
pinMode(colPins[col], INPUT); pinMode(colPins[col], INPUT);
} }
}
#endif
#ifdef MULTIPLEXLEDS
void multiplexLeds() {
unsigned long currentMillis = millis();
//init Multiplex
#ifdef KEYPAD //if Keyboard is presend disable Pullup Resistors to not mess with LEDs while a Button is pressed.
for (int row = 0; row < numRows; row++) {
pinMode(rowPins[row], OUTPUT);
digitalWrite(rowPins[row], LOW);
}
#endif
for (int i = 0; i < numVccPins; i++) {
pinMode(LedVccPins[i], OUTPUT);
digitalWrite(LedVccPins[i], LOW); // Set to LOW to disable all Vcc Pins
}
for (int i = 0; i < numGndPins; i++) {
pinMode(LedGndPins[i], OUTPUT);
digitalWrite(LedGndPins[i], HIGH); // Set to HIGH to disable all GND Pins
}
for(currentLED = 0; currentLED < numVccPins*numGndPins ;currentLED ++){
if(ledStates[currentLED] == 1){ //only handle turned on LEDs
digitalWrite(LedVccPins[currentLED/numVccPins],HIGH); //turn current LED on
digitalWrite(LedGndPins[currentLED%numVccPins],LOW);
Serial.print("VCC: ");
Serial.print(LedVccPins[currentLED/numVccPins]);
Serial.print(" GND: ");
Serial.println(LedGndPins[currentLED%numVccPins]);
delayMicroseconds(interval); //wait couple ms
digitalWrite(LedVccPins[currentLED/numVccPins],LOW); //turn off and go to next one
digitalWrite(LedGndPins[currentLED%numVccPins],HIGH);
}
}
/*
}
if(ledStates[currentLED]==0){//If currentLED is Off, manage next one.
currentLED++;
}
if(currentLED >= numVccPins*numGndPins){
currentLED= 0;
}
*/
} }
#endif #endif
@ -916,6 +996,21 @@ void commandReceived(char cmd, uint16_t io, uint16_t value){
} }
#endif #endif
#ifdef MULTIPLEXLEDS
if(cmd == 'M'){
ledStates[io] = value; // Set the LED state
lastcom=millis();
#ifdef DEBUG
Serial.print("multiplexed Led No:");
Serial.print(io);
Serial.print("Set to:");
Serial.println(ledStates[io]);
#endif
}
#endif
if(cmd == 'E'){ if(cmd == 'E'){
lastcom=millis(); lastcom=millis();
if(connectionState == 2){ if(connectionState == 2){

View File

@ -32,6 +32,9 @@ It also supports Digital LEDs such as WS2812 or PL9823. This way you can have as
| binary encoded Selector Switch | 1 | 1 | 1 | | binary encoded Selector Switch | 1 | 1 | 1 |
| Quadrature Encoder Input | 3 or more | 1 or more | 1 or more | | Quadrature Encoder Input | 3 or more | 1 or more | 1 or more |
| Joystick Support (2Axis) | 8 | 6 | 3 | | Joystick Support (2Axis) | 8 | 6 | 3 |
| Matrix Keyboard | 1 | 1 | 1 |
| Multiplexed LEDs | ~ 1000 | ~ 1000 | ~ 1000 |
# Compatiblity # Compatiblity
@ -168,6 +171,19 @@ If it doesn't, something is not working and this program will not work either. P
In the Settings a cheap 4x4 Keyboard is used such as https://theartoftinkering.com/recommends/matrix-keyboard/ (referral link) In the Settings a cheap 4x4 Keyboard is used such as https://theartoftinkering.com/recommends/matrix-keyboard/ (referral link)
# Multiplexed LEDs
Special mode for Multiplexed LEDs. This mode is experimental and implemented to support Matrix Keyboards with integrated Key LEDs. Please provide feedback if u use this feature.
check out this thread on LinuxCNC Forum for context. https://forum.linuxcnc.org/show-your-stuff/49606-matrix-keyboard-controlling-linuxcnc
for Each LED an Output Pin is generated in LinuxCNC.
If your Keyboard shares pins with the LEDs, you have to check polarity. The Matrix Keyboard uses Pins as such:
rowPins[numRows] = {} are Pullup Inputs
colPins[numCols] = {} are GND Pins
the matrix keyboard described in the thread shares GND Pins between LEDs and KEYs, therefore LedGndPins[] and colPins[numCols] = {} use same Pins, LedVccPins[] are Outputs and drive the LEDs.
# Quadrature Encoders # Quadrature Encoders
Quadrature Encoders require a Library to be installed. Quadrature Encoders require a Library to be installed.
More Info about the used Library can be found here: https://www.pjrc.com/teensy/td_libs_Encoder.html More Info about the used Library can be found here: https://www.pjrc.com/teensy/td_libs_Encoder.html

View File

@ -29,6 +29,7 @@ import serial, time, hal
# Latching Potentiometers = 'L' -write only -Pin State: 0-max Position # Latching Potentiometers = 'L' -write only -Pin State: 0-max Position
# binary encoded Selector = 'K' -write only -Pin State: 0-32 # binary encoded Selector = 'K' -write only -Pin State: 0-32
# Matrix Keypad = 'M' -write only -Pin State: 0,1 # Matrix Keypad = 'M' -write only -Pin State: 0,1
# Multiplexed LEDs = 'M' -read only -Pin State: 0,1
# Quadrature Encoders = 'R' -write only -Pin State: 0(down),1(up),-2147483648 to 2147483647(counter) # Quadrature Encoders = 'R' -write only -Pin State: 0(down),1(up),-2147483648 to 2147483647(counter)
# Joystick Input = 'R' -write only -Pin State: -2147483648 to 2147483647(counter) # Joystick Input = 'R' -write only -Pin State: -2147483648 to 2147483647(counter)
@ -132,7 +133,7 @@ DLEDcount = 0
Keypad = 0 # Set to 1 to Activate Keypad = 0 # Set to 1 to Activate
LinuxKeyboardInput = 1 #Activate direct Keyboard integration to Linux. LinuxKeyboardInput = 0 # set to 1 to Activate direct Keyboard integration to Linux.
Columns = 4 Columns = 4
@ -166,16 +167,25 @@ Destination = [ #define, which Key should be inserted in LinuxCNC as Input or
# 12, 13, 14, 15 # 12, 13, 14, 15
# #
# this is an experimental feature, meant to support MatrixKeyboards with integrated LEDs in each Key but should work with any other LED Matrix too.
# It creates Output Halpins that can be connected to signals in LinuxCNC
MultiplexLED = 0 # Set to 1 to Activate
LedVccPins = 3
LedGndPins = 3
Debug = 0 #only works when this script is run from halrun in Terminal. "halrun","loadusr arduino" now Debug info will be displayed. Debug = 0 #only works when this script is run from halrun in Terminal. "halrun","loadusr arduino" now Debug info will be displayed.
######## End of Config! ######## ######## End of Config! ########
# global Variables for State Saving
olddOutStates= [0]*Outputs olddOutStates= [0]*Outputs
oldPwmOutStates=[0]*PwmOutputs oldPwmOutStates=[0]*PwmOutputs
oldDLEDStates=[0]*DLEDcount oldDLEDStates=[0]*DLEDcount
oldMledStates = [0]*LedVccPins*LedGndPins
if LinuxKeyboardInput: if LinuxKeyboardInput:
import subprocess import subprocess
@ -241,6 +251,11 @@ if Keypad > 0:
if Destination[port] == 0 & LinuxKeyboardInput: if Destination[port] == 0 & LinuxKeyboardInput:
c.newpin("keypad.{}".format(Chars[port]), hal.HAL_BIT, hal.HAL_IN) c.newpin("keypad.{}".format(Chars[port]), hal.HAL_BIT, hal.HAL_IN)
# setup MultiplexLED halpins
if MultiplexLED > 0:
for port in range(LedVccPins*LedGndPins):
c.newpin("mled.{}".format(port), hal.HAL_BIT, hal.HAL_OUT)
#setup JoyStick Pins #setup JoyStick Pins
if JoySticks > 0: if JoySticks > 0:
@ -326,8 +341,17 @@ def managageOutputs():
if (Debug):print ("Sending:{}".format(command.encode())) if (Debug):print ("Sending:{}".format(command.encode()))
oldDLEDStates[dled] = State oldDLEDStates[dled] = State
time.sleep(0.01) time.sleep(0.01)
if MultiplexLED > 0:
for mled in range(LedVccPins*LedGndPins):
State = int(c["mled.{}".format(mled)])
if oldMledStates[mled] != State: #check if states have changed
Sig = 'M'
Pin = mled
command = "{}{}:{}\n".format(Sig,Pin,State)
arduino.write(command.encode())
if (Debug):print ("Sending:{}".format(command.encode()))
oldMledStates[mled] = State
time.sleep(0.01)
while True: while True: