From 04840c0313b424c8d22dcadda2faf658c14904ad Mon Sep 17 00:00:00 2001 From: Alexander Richter Date: Wed, 13 Sep 2023 18:09:38 +0200 Subject: [PATCH 01/10] added multiplexed LED feature --- LinuxCNC_ArduinoConnector.ino | 109 ++++++++++++++++++++++++++++------ arduino-connector.py | 33 +++++++++- 2 files changed, 122 insertions(+), 20 deletions(-) diff --git a/LinuxCNC_ArduinoConnector.ino b/LinuxCNC_ArduinoConnector.ino index 1702203..930c9f1 100644 --- a/LinuxCNC_ArduinoConnector.ino +++ b/LinuxCNC_ArduinoConnector.ino @@ -64,14 +64,14 @@ Communication Status = 'E' -read/Write -Pin State: 0:0 //###################################################IO's################################################### -#define INPUTS //Use Arduino IO's as Inputs. Define how many Inputs you want in total and then which Pins you want to be Inputs. +//#define INPUTS //Use Arduino IO's as Inputs. Define how many Inputs you want in total and then which Pins you want to be Inputs. #ifdef INPUTS const int Inputs = 2; //number of inputs using internal Pullup resistor. (short to ground to trigger) int InPinmap[] = {8,9}; #endif //Use Arduino IO's as Toggle Inputs, which means Inputs (Buttons for example) keep HIGH State after Release and Send LOW only after beeing Pressed again. -#define SINPUTS //Define how many Toggle Inputs you want in total and then which Pins you want to be Toggle Inputs. +//#define SINPUTS //Define how many Toggle Inputs you want in total and then which Pins you want to be Toggle Inputs. #ifdef SINPUTS const int sInputs = 1; //number of inputs using internal Pullup resistor. (short to ground to trigger) int sInPinmap[] = {10}; @@ -89,7 +89,7 @@ Communication Status = 'E' -read/Write -Pin State: 0:0 int PwmOutPinmap[] = {12,11}; #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. #ifdef AINPUTS const int AInputs = 1; @@ -113,7 +113,7 @@ Then in the Array, {which Pin, How many Positions} Note that Analog Pin numbering is different to the Print on the PCB. */ -#define LPOTIS +//#define LPOTIS #ifdef LPOTIS const int LPotis = 2; const int LPotiPins[LPotis][2] = { @@ -125,7 +125,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 const int BinSelKnobPins[] = {2,6,4,3,5}; //1,2,4,8,16 #endif @@ -261,7 +261,7 @@ Adafruit_NeoPixel strip(DLEDcount, DLEDPin, NEO_GRB + NEO_KHZ800);//Color sequen Matrix Keypads are supported. The input is NOT added as HAL Pin to LinuxCNC. Instead it is inserted to Linux as Keyboard direktly. So you could attach a QWERT* Keyboard to the arduino and you will be able to write in Linux with it (only while LinuxCNC is running!) */ -//#define KEYPAD +#define KEYPAD #ifdef KEYPAD const int numRows = 4; // Define the number of rows in the matrix const int numCols = 4; // Define the number of columns in the matrix @@ -270,15 +270,35 @@ const int numCols = 4; // Define the number of columns in the matrix const int rowPins[numRows] = {2, 3, 4, 5}; const int colPins[numCols] = {6, 7, 8, 9}; - - int keys[numRows][numCols] = {0}; - int lastKey= -1; #endif -//#define DEBUG +#define MULTIPLEXLEDS // Special mode for Multiplexed 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. + +#ifdef MULTIPLEXLEDS + +const int numVccPins = 4; // Number of rows in the matrix +const int numGndPins = 4; // Number of columns in the matrix +const int LedVccPins[] = {6, 3, 4, 5}; // Arduino pins connected to rows +const int LedGndPins[] = {2, 7, 8, 9}; // Arduino pins connected to columns + +// Define the LED matrix +int ledStates[numVccPins*numGndPins] = {0}; + +unsigned long previousMillis = 0; +const unsigned long interval = 0; // Time (in milliseconds) per LED display + +int currentLED = 0; +#endif + + + + +#define DEBUG //####################################### END OF CONFIG ########################### //###Misc Settings### @@ -319,6 +339,9 @@ const int debounceDelay = 50; #ifdef KEYPAD byte KeyState = 0; #endif +#ifdef MULTIPLEXLEDS + byte KeyLedStates[numRows*numCols]; +#endif #if QUADENCS == 1 const int QuadEncs = 1; #endif @@ -470,7 +493,7 @@ void loop() { #ifdef JOYSTICK readJoySticks(); //read Encoders & send data #endif - + multiplexLeds(); } @@ -563,9 +586,7 @@ void readEncoders(){ } #endif -void initialiseIO(){ - -} + void comalive(){ if(lastcom == 0){ //no connection yet. send E0:0 periodicly and wait for response while (lastcom == 0){ @@ -621,7 +642,7 @@ void reconnect(){ Serial.println("resending Data"); #endif - #ifdef INPUT + #ifdef INPUTS for (int x = 0; x < Inputs; x++){ InState[x]= -1; } @@ -662,7 +683,9 @@ void reconnect(){ #ifdef BINSEL readAbsKnob(); //read ABS Encoder & send data #endif - + #ifdef MULTIPLEXLEDS + multiplexLeds(); //Flash LEDS. + #endif connectionState = 1; @@ -862,7 +885,7 @@ int readAbsKnob(){ #ifdef KEYPAD void readKeypad(){ //detect if Button is Pressed - for (int col = 0; col < numCols; col++) { + for (int col = 0; col < numCols; col++) { pinMode(colPins[col], OUTPUT); digitalWrite(colPins[col], LOW); // Read the state of the row pins @@ -873,6 +896,7 @@ void readKeypad(){ sendData('M',keys[row][col],1); lastKey = keys[row][col]; row = numRows; + } if (digitalRead(rowPins[row]) == HIGH && lastKey == keys[row][col]) { // The Last Button has been unpressed @@ -885,9 +909,45 @@ void readKeypad(){ // Set the column pin back to input mode pinMode(colPins[col], INPUT); } + } #endif +void multiplexLeds() { + unsigned long currentMillis = millis(); + //init Multiplex + 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 + } + + if(ledStates[currentLED]==1){ + digitalWrite(LedVccPins[currentLED%numVccPins],ledStates[currentLED]); + digitalWrite(LedGndPins[currentLED/numVccPins],LOW); + Serial.print(currentLED/numVccPins); //row + Serial.print(":"); + Serial.println(currentLED%numVccPins); //column + //delay(1); + } + else{ //ignore LEDs that are shut off... + currentLED++; + previousMillis = currentMillis; + } + + if (currentMillis - previousMillis >= interval) { // Check if it's time to update the LED matrix + previousMillis = currentMillis; // Save the last update time + currentLED++; + } + if(currentLED >= numVccPins*numGndPins){ + currentLED= 0; + } +} + + void commandReceived(char cmd, uint16_t io, uint16_t value){ #ifdef OUTPUTS if(cmd == 'O'){ @@ -916,6 +976,21 @@ void commandReceived(char cmd, uint16_t io, uint16_t value){ } #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'){ lastcom=millis(); if(connectionState == 2){ diff --git a/arduino-connector.py b/arduino-connector.py index ad71f03..6542f5e 100644 --- a/arduino-connector.py +++ b/arduino-connector.py @@ -29,6 +29,7 @@ import serial, time, hal # Latching Potentiometers = 'L' -write only -Pin State: 0-max Position # binary encoded Selector = 'K' -write only -Pin State: 0-32 # 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) # Joystick Input = 'R' -write only -Pin State: -2147483648 to 2147483647(counter) @@ -166,16 +167,23 @@ Destination = [ #define, which Key should be inserted in LinuxCNC as Input or # 12, 13, 14, 15 # + +MultiplexLED = 1 # Set to 1 to Activate +LedVccPins = 4 +LedGndPins = 4 + + + 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! ######## - +# global Variables for State Saving olddOutStates= [0]*Outputs oldPwmOutStates=[0]*PwmOutputs oldDLEDStates=[0]*DLEDcount - +oldMledStates = [0]*LedVccPins*LedGndPins if LinuxKeyboardInput: import subprocess @@ -241,6 +249,11 @@ if Keypad > 0: if Destination[port] == 0 & LinuxKeyboardInput: 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 if JoySticks > 0: @@ -326,8 +339,22 @@ def managageOutputs(): if (Debug):print ("Sending:{}".format(command.encode())) oldDLEDStates[dled] = State time.sleep(0.01) + + 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) - +# setup MultiplexLED halpins +if MultiplexLED > 0: + for port in range(LedVccPins*LedGndPins): + c.newpin("mled.{}".format(port), hal.HAL_BIT, hal.HAL_OUT) while True: From 117e4fd90bb255e1e2ce0838407459df8395aa00 Mon Sep 17 00:00:00 2001 From: Alexander Richter Date: Wed, 13 Sep 2023 18:14:14 +0200 Subject: [PATCH 02/10] changed for panming's Keyboard --- LinuxCNC_ArduinoConnector.ino | 8 ++++---- arduino-connector.py | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/LinuxCNC_ArduinoConnector.ino b/LinuxCNC_ArduinoConnector.ino index 930c9f1..8c65745 100644 --- a/LinuxCNC_ArduinoConnector.ino +++ b/LinuxCNC_ArduinoConnector.ino @@ -281,10 +281,10 @@ int lastKey= -1; #ifdef MULTIPLEXLEDS -const int numVccPins = 4; // Number of rows in the matrix -const int numGndPins = 4; // Number of columns in the matrix -const int LedVccPins[] = {6, 3, 4, 5}; // Arduino pins connected to rows -const int LedGndPins[] = {2, 7, 8, 9}; // Arduino pins connected to columns +const int numVccPins = 8; // Number of rows in the matrix +const int numGndPins = 7; // Number of columns in the matrix +const int LedVccPins[] = {0,1,2,3,4,5,6,7}; // Arduino pins connected to rows +const int LedGndPins[] = {8,9,10,11,12,13,14}; // Arduino pins connected to columns // Define the LED matrix int ledStates[numVccPins*numGndPins] = {0}; diff --git a/arduino-connector.py b/arduino-connector.py index 6542f5e..4995cbf 100644 --- a/arduino-connector.py +++ b/arduino-connector.py @@ -169,8 +169,8 @@ Destination = [ #define, which Key should be inserted in LinuxCNC as Input or MultiplexLED = 1 # Set to 1 to Activate -LedVccPins = 4 -LedGndPins = 4 +LedVccPins = 8 +LedGndPins = 7 From 8346f020d94d23df9cf6070a326f196b2ad49c9f Mon Sep 17 00:00:00 2001 From: Alexander Richter Date: Sat, 16 Sep 2023 16:36:29 +0200 Subject: [PATCH 03/10] Matrixkeyboard works in Arduino --- LinuxCNC_ArduinoConnector.ino | 39 +++++++++++++++++------------------ 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/LinuxCNC_ArduinoConnector.ino b/LinuxCNC_ArduinoConnector.ino index 8c65745..96c1ad8 100644 --- a/LinuxCNC_ArduinoConnector.ino +++ b/LinuxCNC_ArduinoConnector.ino @@ -261,7 +261,7 @@ Adafruit_NeoPixel strip(DLEDcount, DLEDPin, NEO_GRB + NEO_KHZ800);//Color sequen Matrix Keypads are supported. The input is NOT added as HAL Pin to LinuxCNC. Instead it is inserted to Linux as Keyboard direktly. So you could attach a QWERT* Keyboard to the arduino and you will be able to write in Linux with it (only while LinuxCNC is running!) */ -#define KEYPAD +//#define KEYPAD #ifdef KEYPAD const int numRows = 4; // Define the number of rows in the matrix const int numCols = 4; // Define the number of columns in the matrix @@ -281,16 +281,16 @@ int lastKey= -1; #ifdef MULTIPLEXLEDS -const int numVccPins = 8; // Number of rows in the matrix -const int numGndPins = 7; // Number of columns in the matrix -const int LedVccPins[] = {0,1,2,3,4,5,6,7}; // Arduino pins connected to rows -const int LedGndPins[] = {8,9,10,11,12,13,14}; // Arduino pins connected to columns +const int numVccPins = 3; // Number of rows in the matrix +const int numGndPins = 3; // Number of columns in the matrix +const int LedVccPins[] = {3,4,5}; // Arduino pins connected to rows +const int LedGndPins[] = {8,9,10}; // Arduino pins connected to columns // Define the LED matrix int ledStates[numVccPins*numGndPins] = {0}; unsigned long previousMillis = 0; -const unsigned long interval = 0; // Time (in milliseconds) per LED display +const unsigned long interval = 1; // Time (in milliseconds) per LED display int currentLED = 0; #endif @@ -340,7 +340,7 @@ const int debounceDelay = 50; byte KeyState = 0; #endif #ifdef MULTIPLEXLEDS - byte KeyLedStates[numRows*numCols]; + byte KeyLedStates[numVccPins*numGndPins]; #endif #if QUADENCS == 1 const int QuadEncs = 1; @@ -924,19 +924,18 @@ void multiplexLeds() { pinMode(LedGndPins[i], OUTPUT); digitalWrite(LedGndPins[i], HIGH); // Set to HIGH to disable all GND Pins } - - if(ledStates[currentLED]==1){ - digitalWrite(LedVccPins[currentLED%numVccPins],ledStates[currentLED]); - digitalWrite(LedGndPins[currentLED/numVccPins],LOW); - Serial.print(currentLED/numVccPins); //row - Serial.print(":"); - Serial.println(currentLED%numVccPins); //column - //delay(1); - } - else{ //ignore LEDs that are shut off... - currentLED++; - previousMillis = currentMillis; - } + if(ledStates[currentLED]==1){ + digitalWrite(LedVccPins[currentLED%numVccPins],ledStates[currentLED]); + digitalWrite(LedGndPins[currentLED/numVccPins],LOW); + #ifdef DEBUG + Serial.print(currentLED%numVccPins); //row + Serial.print("/ "); + Serial.print(currentLED/numVccPins); //column + Serial.print(" wrt "); + Serial.print(ledStates[currentLED]); //row + Serial.println(" /"); + #endif + } if (currentMillis - previousMillis >= interval) { // Check if it's time to update the LED matrix previousMillis = currentMillis; // Save the last update time From 21699f23f9639d0ac0f2f77a532ebbf05020609d Mon Sep 17 00:00:00 2001 From: Alexander Richter Date: Sat, 16 Sep 2023 16:50:36 +0200 Subject: [PATCH 04/10] more changes to multiplex LEDs --- LinuxCNC_ArduinoConnector.ino | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/LinuxCNC_ArduinoConnector.ino b/LinuxCNC_ArduinoConnector.ino index 96c1ad8..f51a8d8 100644 --- a/LinuxCNC_ArduinoConnector.ino +++ b/LinuxCNC_ArduinoConnector.ino @@ -924,23 +924,26 @@ void multiplexLeds() { pinMode(LedGndPins[i], OUTPUT); digitalWrite(LedGndPins[i], HIGH); // Set to HIGH to disable all GND Pins } - if(ledStates[currentLED]==1){ - digitalWrite(LedVccPins[currentLED%numVccPins],ledStates[currentLED]); + if(ledStates[currentLED]==1){//turn active LEDs on. + digitalWrite(LedVccPins[currentLED%numVccPins],HIGH); digitalWrite(LedGndPins[currentLED/numVccPins],LOW); + delayMicroseconds(interval); #ifdef DEBUG Serial.print(currentLED%numVccPins); //row - Serial.print("/ "); + Serial.print(" % row ;/ col"); Serial.print(currentLED/numVccPins); //column - Serial.print(" wrt "); - Serial.print(ledStates[currentLED]); //row + Serial.print(" write "); + Serial.print(ledStates[currentLED]); //LED State Serial.println(" /"); #endif } - + currentLED++; + /* if (currentMillis - previousMillis >= interval) { // Check if it's time to update the LED matrix previousMillis = currentMillis; // Save the last update time currentLED++; } + */ if(currentLED >= numVccPins*numGndPins){ currentLED= 0; } From 6e44c697cc4cf865d928c99aa7337271755c9955 Mon Sep 17 00:00:00 2001 From: Alexander Richter Date: Sat, 16 Sep 2023 20:38:05 +0200 Subject: [PATCH 05/10] Disable MatrixLED Pullup Pins added --- LinuxCNC_ArduinoConnector.ino | 53 +++++++++++++++++------------------ 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/LinuxCNC_ArduinoConnector.ino b/LinuxCNC_ArduinoConnector.ino index f51a8d8..bb31ead 100644 --- a/LinuxCNC_ArduinoConnector.ino +++ b/LinuxCNC_ArduinoConnector.ino @@ -263,12 +263,12 @@ So you could attach a QWERT* Keyboard to the arduino and you will be able to wri */ //#define KEYPAD #ifdef KEYPAD -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 numRows = 3; // Define the number of rows in the matrix +const int numCols = 3; // Define the number of columns in the matrix // Define the pins connected to the rows and columns of the matrix -const int rowPins[numRows] = {2, 3, 4, 5}; -const int colPins[numCols] = {6, 7, 8, 9}; +const int rowPins[numRows] = {5,6,7}; //Iputs +const int colPins[numCols] = {8, 9, 10}; //"Output 8-14" int keys[numRows][numCols] = {0}; int lastKey= -1; @@ -283,7 +283,7 @@ int lastKey= -1; const int numVccPins = 3; // Number of rows in the matrix const int numGndPins = 3; // Number of columns in the matrix -const int LedVccPins[] = {3,4,5}; // Arduino pins connected to rows +const int LedVccPins[] = {2,3,4}; // Arduino pins connected to rows const int LedGndPins[] = {8,9,10}; // Arduino pins connected to columns // Define the LED matrix @@ -916,34 +916,33 @@ void readKeypad(){ void multiplexLeds() { unsigned long currentMillis = millis(); //init Multiplex - 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 - } if(ledStates[currentLED]==1){//turn active LEDs on. + #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 + } digitalWrite(LedVccPins[currentLED%numVccPins],HIGH); digitalWrite(LedGndPins[currentLED/numVccPins],LOW); - delayMicroseconds(interval); - #ifdef DEBUG - Serial.print(currentLED%numVccPins); //row - Serial.print(" % row ;/ col"); - Serial.print(currentLED/numVccPins); //column - Serial.print(" write "); - Serial.print(ledStates[currentLED]); //LED State - Serial.println(" /"); - #endif + + if (currentMillis - previousMillis >= interval) { // Check if it's time to update the LED matrix + previousMillis = currentMillis; // Save the last update time + currentLED++; } - currentLED++; - /* - if (currentMillis - previousMillis >= interval) { // Check if it's time to update the LED matrix - previousMillis = currentMillis; // Save the last update time + } + if(ledStates[currentLED]==0){//If currentLED is Off, manage next one. currentLED++; } - */ if(currentLED >= numVccPins*numGndPins){ currentLED= 0; } From 142366491ddf03ea6165bccfb2c6e259dc064f1d Mon Sep 17 00:00:00 2001 From: Alexander Richter Date: Sat, 16 Sep 2023 21:06:28 +0200 Subject: [PATCH 06/10] Adapted Python Code to make it work too --- LinuxCNC_ArduinoConnector.ino | 11 +++++++---- arduino-connector.py | 37 +++++++++++++++-------------------- 2 files changed, 23 insertions(+), 25 deletions(-) diff --git a/LinuxCNC_ArduinoConnector.ino b/LinuxCNC_ArduinoConnector.ino index bb31ead..c8d9a32 100644 --- a/LinuxCNC_ArduinoConnector.ino +++ b/LinuxCNC_ArduinoConnector.ino @@ -261,7 +261,7 @@ Adafruit_NeoPixel strip(DLEDcount, DLEDPin, NEO_GRB + NEO_KHZ800);//Color sequen Matrix Keypads are supported. The input is NOT added as HAL Pin to LinuxCNC. Instead it is inserted to Linux as Keyboard direktly. So you could attach a QWERT* Keyboard to the arduino and you will be able to write in Linux with it (only while LinuxCNC is running!) */ -//#define KEYPAD +#define KEYPAD #ifdef KEYPAD const int numRows = 3; // Define the number of rows in the matrix const int numCols = 3; // Define the number of columns in the matrix @@ -298,7 +298,7 @@ int currentLED = 0; -#define DEBUG +//#define DEBUG //####################################### END OF CONFIG ########################### //###Misc Settings### @@ -490,13 +490,15 @@ void loop() { #ifdef QUADENC readEncoders(); //read Encoders & send data #endif + #ifdef JOYSTICK readJoySticks(); //read Encoders & send data #endif +#ifdef MULTIPLEXLEDS multiplexLeds(); +#endif } - #ifdef JOYSTICK void readJoySticks() { @@ -913,6 +915,7 @@ void readKeypad(){ } #endif +#ifdef MULTIPLEXLEDS void multiplexLeds() { unsigned long currentMillis = millis(); //init Multiplex @@ -947,7 +950,7 @@ void multiplexLeds() { currentLED= 0; } } - +#endif void commandReceived(char cmd, uint16_t io, uint16_t value){ #ifdef OUTPUTS diff --git a/arduino-connector.py b/arduino-connector.py index 4995cbf..07d265e 100644 --- a/arduino-connector.py +++ b/arduino-connector.py @@ -132,12 +132,12 @@ DLEDcount = 0 # You can specify special Charakters however, which will be handled as Inputs in LinuxCNC. Define those in the LCNC Array below. -Keypad = 0 # Set to 1 to Activate +Keypad = 1 # Set to 1 to Activate LinuxKeyboardInput = 1 #Activate direct Keyboard integration to Linux. -Columns = 4 -Rows = 4 +Columns = 3 +Rows = 3 Chars = [ #here you must define as many characters as your Keypad has keys. calculate columns * rows . for example 4 *4 = 16. You can write it down like in the example for ease of readability. "1", "2", "3", "A", "4", "5", "6", "B", @@ -169,8 +169,8 @@ Destination = [ #define, which Key should be inserted in LinuxCNC as Input or MultiplexLED = 1 # Set to 1 to Activate -LedVccPins = 8 -LedGndPins = 7 +LedVccPins = 3 +LedGndPins = 3 @@ -339,22 +339,17 @@ def managageOutputs(): if (Debug):print ("Sending:{}".format(command.encode())) oldDLEDStates[dled] = State time.sleep(0.01) - - 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) - -# setup MultiplexLED halpins -if MultiplexLED > 0: - for port in range(LedVccPins*LedGndPins): - c.newpin("mled.{}".format(port), hal.HAL_BIT, hal.HAL_OUT) + 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: From 2eaa6a25253fb6103d679269efd7d9e71e65cdea Mon Sep 17 00:00:00 2001 From: Alexander Richter Date: Sun, 17 Sep 2023 14:24:22 +0200 Subject: [PATCH 07/10] modifyed LED Multiplex Code. --- LinuxCNC_ArduinoConnector.ino | 64 +++++++++++++++++------------------ 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/LinuxCNC_ArduinoConnector.ino b/LinuxCNC_ArduinoConnector.ino index c8d9a32..52089fd 100644 --- a/LinuxCNC_ArduinoConnector.ino +++ b/LinuxCNC_ArduinoConnector.ino @@ -263,13 +263,12 @@ So you could attach a QWERT* Keyboard to the arduino and you will be able to wri */ #define KEYPAD #ifdef KEYPAD -const int numRows = 3; // Define the number of rows in the matrix -const int numCols = 3; // Define the number of columns in the matrix +const int numRows = 8; // Define the number of rows in the matrix +const int numCols = 8; // Define the number of columns in the matrix // Define the pins connected to the rows and columns of the matrix -const int rowPins[numRows] = {5,6,7}; //Iputs -const int colPins[numCols] = {8, 9, 10}; //"Output 8-14" - +const int rowPins[numRows] = {2,3,4,5,6,7,8,9}; //Iputs +const int colPins[numCols] = {40,41,42,43,44,45,46,47}; //"Output 8-14" int keys[numRows][numCols] = {0}; int lastKey= -1; #endif @@ -281,16 +280,16 @@ int lastKey= -1; #ifdef MULTIPLEXLEDS -const int numVccPins = 3; // Number of rows in the matrix -const int numGndPins = 3; // Number of columns in the matrix -const int LedVccPins[] = {2,3,4}; // Arduino pins connected to rows -const int LedGndPins[] = {8,9,10}; // Arduino pins connected to columns +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 = 1; // Time (in milliseconds) per LED display +const unsigned long interval = 0; // Time (in milliseconds) per LED display int currentLED = 0; #endif @@ -495,7 +494,8 @@ void loop() { readJoySticks(); //read Encoders & send data #endif #ifdef MULTIPLEXLEDS - multiplexLeds(); +//for(int i=0;i<20;i++){ + multiplexLeds();//} #endif } @@ -919,36 +919,36 @@ void readKeypad(){ void multiplexLeds() { unsigned long currentMillis = millis(); //init Multiplex - if(ledStates[currentLED]==1){//turn active LEDs on. - #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 + #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 - } - digitalWrite(LedVccPins[currentLED%numVccPins],HIGH); - digitalWrite(LedGndPins[currentLED/numVccPins],LOW); - - if (currentMillis - previousMillis >= interval) { // Check if it's time to update the LED matrix - previousMillis = currentMillis; // Save the last update time - currentLED++; + 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){ + digitalWrite(LedVccPins[currentLED%numVccPins],HIGH); + digitalWrite(LedGndPins[currentLED/numVccPins],LOW); } } +/* + } if(ledStates[currentLED]==0){//If currentLED is Off, manage next one. currentLED++; } if(currentLED >= numVccPins*numGndPins){ currentLED= 0; } + */ } #endif From ec99d210935d8310bb976cb0b0c055472e521ae2 Mon Sep 17 00:00:00 2001 From: Alexander Richter Date: Sun, 17 Sep 2023 15:03:19 +0200 Subject: [PATCH 08/10] new version --- LinuxCNC_ArduinoConnector.ino | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/LinuxCNC_ArduinoConnector.ino b/LinuxCNC_ArduinoConnector.ino index 52089fd..3eeabe1 100644 --- a/LinuxCNC_ArduinoConnector.ino +++ b/LinuxCNC_ArduinoConnector.ino @@ -289,7 +289,7 @@ const int LedGndPins[] = {40,41,42,43,44,45,46,47}; // Arduino pins connected to int ledStates[numVccPins*numGndPins] = {0}; unsigned long previousMillis = 0; -const unsigned long interval = 0; // Time (in milliseconds) per LED display +const unsigned long interval = 500; // Time (in milliseconds) per LED display int currentLED = 0; #endif @@ -934,10 +934,20 @@ void multiplexLeds() { 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){ - digitalWrite(LedVccPins[currentLED%numVccPins],HIGH); + 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); } } /* From 5a60f79ad486ea3f95e6fea9c16e23d2f6d5802f Mon Sep 17 00:00:00 2001 From: Alexander Richter Date: Sun, 17 Sep 2023 15:41:10 +0200 Subject: [PATCH 09/10] update 2D Matrix direction for multiplexed LEDs --- LinuxCNC_ArduinoConnector.ino | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/LinuxCNC_ArduinoConnector.ino b/LinuxCNC_ArduinoConnector.ino index 3eeabe1..20f17de 100644 --- a/LinuxCNC_ArduinoConnector.ino +++ b/LinuxCNC_ArduinoConnector.ino @@ -937,17 +937,17 @@ void multiplexLeds() { 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); + digitalWrite(LedVccPins[currentLED/numVccPins],HIGH); //turn current LED on + digitalWrite(LedGndPins[currentLED%numVccPins],LOW); Serial.print("VCC: "); - Serial.print(LedVccPins[currentLED%numVccPins]); + Serial.print(LedVccPins[currentLED/numVccPins]); Serial.print(" GND: "); - Serial.println(LedGndPins[currentLED/numVccPins]); + 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); + digitalWrite(LedVccPins[currentLED/numVccPins],LOW); //turn off and go to next one + digitalWrite(LedGndPins[currentLED%numVccPins],HIGH); } } /* From 2fa2cf4265328714be3537c4088c4871cd767669 Mon Sep 17 00:00:00 2001 From: Alexander Richter Date: Sat, 23 Sep 2023 17:05:27 +0200 Subject: [PATCH 10/10] making the code ready to merge with main --- LinuxCNC_ArduinoConnector.ino | 34 ++++++++++++++++++++-------------- README.md | 16 ++++++++++++++++ arduino-connector.py | 16 +++++++++------- 3 files changed, 45 insertions(+), 21 deletions(-) diff --git a/LinuxCNC_ArduinoConnector.ino b/LinuxCNC_ArduinoConnector.ino index 20f17de..ef1e3b6 100644 --- a/LinuxCNC_ArduinoConnector.ino +++ b/LinuxCNC_ArduinoConnector.ino @@ -16,6 +16,7 @@ - digital Inputs - digital Outputs - Matrix Keypad + - Multiplexed LEDs - Quadrature encoders - Joysticks @@ -32,9 +33,10 @@ binary encoded Selector = 'K' -write only -Pin State: 0-32 rotary encoder = '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: - 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 @@ -64,20 +66,20 @@ Communication Status = 'E' -read/Write -Pin State: 0:0 //###################################################IO's################################################### -//#define INPUTS //Use Arduino IO's as Inputs. Define how many Inputs you want in total and then which Pins you want to be Inputs. +#define INPUTS //Use Arduino IO's as Inputs. Define how many Inputs you want in total and then which Pins you want to be Inputs. #ifdef INPUTS const int Inputs = 2; //number of inputs using internal Pullup resistor. (short to ground to trigger) int InPinmap[] = {8,9}; #endif //Use Arduino IO's as Toggle Inputs, which means Inputs (Buttons for example) keep HIGH State after Release and Send LOW only after beeing Pressed again. -//#define SINPUTS //Define how many Toggle Inputs you want in total and then which Pins you want to be Toggle Inputs. +#define SINPUTS //Define how many Toggle Inputs you want in total and then which Pins you want to be Toggle Inputs. #ifdef SINPUTS const int sInputs = 1; //number of inputs using internal Pullup resistor. (short to ground to trigger) int sInPinmap[] = {10}; #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 const int Outputs = 2; //number of outputs int OutPinmap[] = {11,12}; @@ -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. //1= send up or down signal (typical use for selecting modes in hal) //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 @@ -261,23 +263,28 @@ Adafruit_NeoPixel strip(DLEDcount, DLEDPin, NEO_GRB + NEO_KHZ800);//Color sequen Matrix Keypads are supported. The input is NOT added as HAL Pin to LinuxCNC. Instead it is inserted to Linux as Keyboard direktly. So you could attach a QWERT* Keyboard to the arduino and you will be able to write in Linux with it (only while LinuxCNC is running!) */ -#define KEYPAD +//#define KEYPAD #ifdef KEYPAD -const int numRows = 8; // Define the number of rows in the matrix -const int numCols = 8; // Define the number of columns 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 // Define the pins connected to the rows and columns of the matrix -const int rowPins[numRows] = {2,3,4,5,6,7,8,9}; //Iputs -const int colPins[numCols] = {40,41,42,43,44,45,46,47}; //"Output 8-14" +const int rowPins[numRows] = {2, 3, 4, 5}; +const int colPins[numCols] = {6, 7, 8, 9}; int keys[numRows][numCols] = {0}; int lastKey= -1; #endif -#define MULTIPLEXLEDS // Special mode for Multiplexed LEDs. +//#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 @@ -494,8 +501,7 @@ void loop() { readJoySticks(); //read Encoders & send data #endif #ifdef MULTIPLEXLEDS -//for(int i=0;i<20;i++){ - multiplexLeds();//} + multiplexLeds();// cycle through the 2D LED Matrix} #endif } diff --git a/README.md b/README.md index 0fb90ab..ca1db6c 100644 --- a/README.md +++ b/README.md @@ -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 | | Quadrature Encoder Input | 3 or more | 1 or more | 1 or more | | Joystick Support (2Axis) | 8 | 6 | 3 | +| Matrix Keyboard | 1 | 1 | 1 | +| Multiplexed LEDs | ~ 1000 | ~ 1000 | ~ 1000 | + # 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) +# 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 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 diff --git a/arduino-connector.py b/arduino-connector.py index 07d265e..40a6b95 100644 --- a/arduino-connector.py +++ b/arduino-connector.py @@ -132,12 +132,12 @@ DLEDcount = 0 # You can specify special Charakters however, which will be handled as Inputs in LinuxCNC. Define those in the LCNC Array below. -Keypad = 1 # Set to 1 to Activate -LinuxKeyboardInput = 1 #Activate direct Keyboard integration to Linux. +Keypad = 0 # Set to 1 to Activate +LinuxKeyboardInput = 0 # set to 1 to Activate direct Keyboard integration to Linux. -Columns = 3 -Rows = 3 +Columns = 4 +Rows = 4 Chars = [ #here you must define as many characters as your Keypad has keys. calculate columns * rows . for example 4 *4 = 16. You can write it down like in the example for ease of readability. "1", "2", "3", "A", "4", "5", "6", "B", @@ -167,14 +167,16 @@ Destination = [ #define, which Key should be inserted in LinuxCNC as Input or # 12, 13, 14, 15 # - -MultiplexLED = 1 # Set to 1 to Activate -LedVccPins = 3 +# 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. + ######## End of Config! ########