From 0577013c17c3ef03374cb039c4d77b3973201394 Mon Sep 17 00:00:00 2001 From: Alexander Richter Date: Sun, 23 Jul 2023 10:43:43 +0200 Subject: [PATCH 1/8] Support for JoySticks Added new functionality for the use of JoySticks for MPG commands --- LinuxCNC_ArduinoConnector.ino | 161 ++++++++++++++++++++++--- arduino.py | 217 +++++++++++++++++++--------------- 2 files changed, 265 insertions(+), 113 deletions(-) diff --git a/LinuxCNC_ArduinoConnector.ino b/LinuxCNC_ArduinoConnector.ino index b01ec11..d5fa0de 100644 --- a/LinuxCNC_ArduinoConnector.ino +++ b/LinuxCNC_ArduinoConnector.ino @@ -9,7 +9,7 @@ You can create as many digital & analog Inputs, Outputs and PWM Outputs as your Arduino can handle. You can also generate "virtual Pins" by using latching Potentiometers, which are connected to one analog Pin, but are read in Hal as individual Pins. - Currently the Software provides: + Currently the Software Supports: - analog Inputs - latching Potentiometers - 1 binary encoded selector Switch @@ -29,7 +29,9 @@ Analog Inputs = 'A' -write only -Pin State: 0-1024 Latching Potentiometers = 'L' -write only -Pin State: 0-max Position binary encoded Selector = 'K' -write only -Pin State: 0-32 - + rotary encoder = 'R' -write only -Pin State: up/ down / -32768 to 32767 + joystick = 'R' -write only -Pin State: up/ down / -32768 to 32767 + Keyboard Input: Matrix Keypad = 'M' -write only -Pin State: Number of Matrix Key. @@ -61,20 +63,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 = 5; //number of inputs using internal Pullup resistor. (short to ground to trigger) int InPinmap[] = {37,38,39,40,41}; #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 = 5; //number of inputs using internal Pullup resistor. (short to ground to trigger) int sInPinmap[] = {32,33,34,35,36}; #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 = 9; //number of outputs int OutPinmap[] = {10,9,8,7,6,5,4,3,2,21}; @@ -89,8 +91,8 @@ Communication Status = 'E' -read/Write -Pin State: 0:0 //#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; - int AInPinmap[] = {1}; //Potentiometer for SpindleSpeed override + const int AInputs = 2; + int AInPinmap[] = {0,2}; //Potentiometer for SpindleSpeed override int smooth = 200; //number of samples to denoise ADC, try lower numbers on your setup 200 worked good for me. #endif @@ -113,7 +115,7 @@ Note that Analog Pin numbering is different to the Print on the PCB. //#define LPOTIS #ifdef LPOTIS const int LPotis = 2; - int LPotiPins[LPotis][2] = { + const int LPotiPins[LPotis][2] = { {2,9}, //Latching Knob Spindle Overdrive on A1, has 9 Positions {3,4} //Latching Knob Feed Resolution on A2, has 4 Positions }; @@ -126,6 +128,64 @@ Note that Analog Pin numbering is different to the Print on the PCB. #endif +#define ROTENC +//Support for Rotatary Encoders with Quadrature Output. Define Pins for A and B Signals for your encoders. Visit https://www.pjrc.com/teensy/td_libs_Encoder.html for further explanation. + +#ifdef ROTENC + #include + const int RotEncs = 2; //how many Rotary Encoders do you want? + // Encoders have 2 signals, which must be connected to 2 pins. There are three options. + + //Best Performance: Both signals connect to interrupt pins. + //Good Performance: First signal connects to an interrupt pin, second to a non-interrupt pin. + //Low Performance: Both signals connect to non-interrupt pins, details below. + + //Board Interrupt Pins LED Pin(do not use) + //Teensy 4.0 - 4.1 All Digital Pins 13 + //Teensy 3.0 - 3.6 All Digital Pins 13 + //Teensy LC 2 - 12, 14, 15, 20 - 23 13 + //Teensy 2.0 5, 6, 7, 8 11 + //Teensy 1.0 0, 1, 2, 3, 4, 6, 7, 16 + //Teensy++ 2.0 0, 1, 2, 3, 18, 19, 36, 37 6 + //Teensy++ 1.0 0, 1, 2, 3, 18, 19, 36, 37 + //Arduino Due All Digital Pins 13 + //Arduino Uno 2, 3 13 + //Arduino Leonardo 0, 1, 2, 3 13 + //Arduino Mega 2, 3, 18, 19, 20, 21 13 + //Sanguino 2, 10, 11 0 + +Encoder Encoder0(2,3); //A,B Pin +Encoder Encoder1(18,19); //A,B Pin +//Encoder Encoder2(A,B); +//Encoder Encoder3(A,B); +//Encoder Encoder4(A,B); + const int RotEncData[] = {1,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 RotEncMp[] = {1,4}; //some Rotary encoders send multiple Electronical Impulses per mechanical pulse. How many Electrical impulses are send for each mechanical Latch? + +#endif + +#define JOYSTICK //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 JOYSTICK + const int JoySticks = 1; + const int JoyStickPins[JoySticks][2] = { + {A0,A2},//Analog Pins JoyStick 1 is connected to + //{2,3}//Analog Pins JoyStick 2 is connected to + }; + const int JoyStickDeadband = 50; //Area around Middle Position that gets ignored. + const int JoyStickSpeed = 100; //Multiplier to slow down the Output Speed if in counter mode. Higher number = slower. + + + const int JoyStickMaxVal = 500; //The Analog Input gets transformed from 0-1023 to -JoyStickMaxVal to +JoyStickMaxVal, so that the Middle Position of the Joystick is 0. I don't think you should change this. +#endif + + + + + + //The Software will detect if there is an communication issue. When you power on your machine, the Buttons etc won't work, till LinuxCNC is running. THe StatusLED will inform you about the State of Communication. // Slow Flash = Not Connected // Steady on = connected @@ -266,7 +326,15 @@ const int debounceDelay = 50; #ifdef KEYPAD byte KeyState = 0; #endif - +#ifdef ROTENC + long EncCount[RotEncs]; + long OldEncCount[RotEncs]; +#endif +#ifdef JOYSTICK + //int oldJoyStick[JoySticks]; + long JoyStickCount[JoySticks][2]; + +#endif //### global Variables setup### //Please don't touch them @@ -286,8 +354,6 @@ char cmd = 0; uint16_t io = 0; uint16_t value = 0; - - void setup() { #ifdef INPUTS @@ -351,6 +417,15 @@ for(int col = 0; col < numCols; col++) { } #endif +#ifdef JOYSTICK + for(int i= 0; i 510+JoyStickDeadband || var0 < 510-JoyStickDeadband){ + var0 = map(var0,0,1023,JoyStickMaxVal*-1,JoyStickMaxVal); + JoyStickCount[i][0] = JoyStickCount[i][0] + (var0*2); + sendData('R',JoyStickPins[i][0],JoyStickCount[i][0]/(JoyStickMaxVal*JoyStickSpeed)); + } + if(var1 > 510 + JoyStickDeadband || var1 < 510 - JoyStickDeadband){ + var1 = map(var1,0,1023,JoyStickMaxVal*-1,JoyStickMaxVal); + JoyStickCount[i][1] = JoyStickCount[i][1] + (var1*2) ; + sendData('R',JoyStickPins[i][1],JoyStickCount[i][1]/(JoyStickMaxVal*JoyStickSpeed)); + } + + } +} +#endif +void readEncoders(){ + if(RotEncs>=1){ + EncCount[0] = RotEncMp[0]* Encoder0.read(); + } + if(RotEncs>=2){ + EncCount[1] = RotEncMp[1]* Encoder1.read(); + } + if(RotEncs>=3){ + //EncCount[2] = RotEncMp[2]* Encoder2.read(); + } + if(RotEncs>=4){ + //EncCount[3] = RotEncMp[3]* Encoder3.read(); + } + if(RotEncs>=5){ + //EncCount[4] = RotEncMp[4]* Encoder4.read(); + } + + for(int i=0; i<=RotEncs;i++){ + if(OldEncCount[i] != EncCount[i]){ + //sendData("R",i,EncCount[i]); + OldEncCount[i] = EncCount[i]; + } + } +} void comalive(){ #ifdef STATUSLED @@ -510,10 +641,10 @@ int readLPoti(){ #ifdef AINPUTS int readAInputs(){ - unsigned long var = 0; + for(int i= 0;i 0: pass #if destination is set to Linux, don't register a Hal Pin for this key. else: c.newpin("Keypad.{}".format(Chars[port]), hal.HAL_BIT, hal.HAL_IN) +#setup JoyStick Pins +if JoySticks > 0: + for port in range(JoySticks): + c.newpin("Jsk.{}".format(JoyStickPins[port]), hal.HAL_FLOAT, hal.HAL_OUT) c.ready() #setup Serial connection @@ -272,110 +287,116 @@ def managageOutputs(): while True: - - try: - data = arduino.readline().decode('utf-8') #read Data received from Arduino and decode it - if (Debug):print ("I received:{}".format(data)) - data = data.split(":",1) - + time.wait(0.01) + if(arduino.in_waiting()>0): try: - cmd = data[0][0] - if cmd == "": - if (Debug):print ("No Command!:{}.".format(cmd)) - - else: - if not data[0][1]: - io = 0 - else: - io = extract_nbr(data[0]) - value = extract_nbr(data[1]) - if value<0: value = 0 + data = arduino.readline().decode('utf-8') #read Data received from Arduino and decode it + if (Debug):print ("I received:{}".format(data)) + data = data.split(":",1) + + try: + cmd = data[0][0] + if cmd == "": + if (Debug):print ("No Command!:{}.".format(cmd)) + else: + if not data[0][1]: + io = 0 + else: + io = extract_nbr(data[0]) + value = extract_nbr(data[1]) + if value<0: value = 0 + - if cmd == "I": - firstcom = 1 - if value == 1: - c["dIn.{}".format(io)] = 1 - c["dIn.{}-invert".format(io)] = 0 - if(Debug):print("dIn{}:{}".format(io,1)) - - if value == 0: - c["dIn.{}".format(io)] = 0 - c["dIn.{}-invert".format(io)] = 1 - if(Debug):print("dIn{}:{}".format(io,0)) - else:pass + if cmd == "I": + firstcom = 1 + if value == 1: + c["dIn.{}".format(io)] = 1 + c["dIn.{}-invert".format(io)] = 0 + if(Debug):print("dIn{}:{}".format(io,1)) + + if value == 0: + c["dIn.{}".format(io)] = 0 + c["dIn.{}-invert".format(io)] = 1 + if(Debug):print("dIn{}:{}".format(io,0)) + else:pass - elif cmd == "A": - firstcom = 1 - c["aIn.{}".format(io)] = value - if (Debug):print("aIn.{}:{}".format(io,value)) + elif cmd == "A": + firstcom = 1 + c["aIn.{}".format(io)] = value + if (Debug):print("aIn.{}:{}".format(io,value)) - elif cmd == "L": - firstcom = 1 - for Poti in range(LPoti): - if LPotiLatches[Poti][0] == io and SetLPotiValue[Poti] == 0: - for Pin in range(LPotiLatches[Poti][1]): - if Pin == value: - c["LPoti.{}.{}" .format(io,Pin)] = 1 - if(Debug):print("LPoti.{}.{} =1".format(io,Pin)) + elif cmd == "L": + firstcom = 1 + for Poti in range(LPoti): + if LPotiLatches[Poti][0] == io and SetLPotiValue[Poti] == 0: + for Pin in range(LPotiLatches[Poti][1]): + if Pin == value: + c["LPoti.{}.{}" .format(io,Pin)] = 1 + if(Debug):print("LPoti.{}.{} =1".format(io,Pin)) + else: + c["LPoti.{}.{}" .format(io,Pin)] = 0 + if(Debug):print("LPoti.{}.{} =0".format(io,Pin)) + + if LPotiLatches[Poti][0] == io and SetLPotiValue[Poti] == 1: + c["LPoti.{}.{}" .format(io,"out")] = LPotiValues[Poti][value] + if(Debug):print("LPoti.{}.{} = 0".format("out",LPotiValues[Poti][value])) + + elif cmd == "K": + firstcom = 1 + if SetBinSelKnobValue == 0: + for port in range(BinSelKnobPos): + if port == value: + c["BinSelKnob.{}".format(port)] = 1 + if(Debug):print("BinSelKnob.{}:{}".format(port,1)) else: - c["LPoti.{}.{}" .format(io,Pin)] = 0 - if(Debug):print("LPoti.{}.{} =0".format(io,Pin)) - - if LPotiLatches[Poti][0] == io and SetLPotiValue[Poti] == 1: - c["LPoti.{}.{}" .format(io,"out")] = LPotiValues[Poti][value] - if(Debug):print("LPoti.{}.{} = 0".format("out",LPotiValues[Poti][value])) + c["BinSelKnob.{}".format(port)] = 0 + if(Debug):print("BinSelKnob.{}:{}".format(port,0)) + else: + c["BinSelKnob.{}.{}" .format(0,"out")] = BinSelKnobvalues[value] - elif cmd == "K": - firstcom = 1 - if SetBinSelKnobValue == 0: - for port in range(BinSelKnobPos): - if port == value: - c["BinSelKnob.{}".format(port)] = 1 - if(Debug):print("BinSelKnob.{}:{}".format(port,1)) + + elif cmd == "M": + firstcom = 1 + if value == 1: + if Destination[io] == 0 and LinuxKeyboardInput == 1: + subprocess.call(["xdotool", "key", Chars[io]]) + if(Debug):print("Emulating Keypress{}".format(Chars[io])) else: - c["BinSelKnob.{}".format(port)] = 0 - if(Debug):print("BinSelKnob.{}:{}".format(port,0)) - else: - c["BinSelKnob.{}.{}" .format(0,"out")] = BinSelKnobvalues[value] + c["Keypad.{}".format(Chars[io])] = 1 + if(Debug):print("Keypad{}:{}".format(Chars[io],1)) + if value == 0 & Destination[io] == 0: + c["Keypad.{}".format(Chars[io])] = 0 + if(Debug):print("Keypad{}:{}".format(Chars[io],0)) - elif cmd == "M": - firstcom = 1 - if value == 1: - if Destination[io] == 0 and LinuxKeyboardInput == 1: - subprocess.call(["xdotool", "key", Chars[io]]) - if(Debug):print("Emulating Keypress{}".format(Chars[io])) - else: - c["Keypad.{}".format(Chars[io])] = 1 - if(Debug):print("Keypad{}:{}".format(Chars[io],1)) - - if value == 0 & Destination[io] == 0: - c["Keypad.{}".format(Chars[io])] = 0 - if(Debug):print("Keypad{}:{}".format(Chars[io],0)) + elif cmd == "R": + firstcom = 1 + c["Jsk.{}".format(io)] = value + if (Debug):print("aIn.{}:{}".format(io,value)) - elif cmd == 'E': - arduino.write(b"E0:0\n") - if (Debug):print("Sending E0:0 to establish contact") - else: pass - + elif cmd == 'E': + arduino.write(b"E0:0\n") + if (Debug):print("Sending E0:0 to establish contact") + else: pass + - except: pass - + except: pass + - except KeyboardInterrupt: - if (Debug):print ("Keyboard Interrupted.. BYE") - exit() - except: - if (Debug):print ("I received garbage") - arduino.flush() - - if firstcom == 1: managageOutputs() #if ==1: E0:0 has been exchanged, which means Arduino knows that LinuxCNC is running and starts sending and receiving Data + except KeyboardInterrupt: + if (Debug):print ("Keyboard Interrupted.. BYE") + exit() + except: + if (Debug):print ("I received garbage") + arduino.flush() + + if firstcom == 1: managageOutputs() #if ==1: E0:0 has been exchanged, which means Arduino knows that LinuxCNC is running and starts sending and receiving Data - if keepAlive(event): #keep com alive. This is send to help Arduino detect connection loss. - arduino.write(b"E:\n") - if (Debug):print("keepAlive") - event = time.time() - + if keepAlive(event): #keep com alive. This is send to help Arduino detect connection loss. + arduino.write(b"E:\n") + if (Debug):print("keepAlive") + event = time.time() + From dbcbe1ccf7a350e86602af36bc6597ddd26c5445 Mon Sep 17 00:00:00 2001 From: Alexander Richter Date: Sun, 23 Jul 2023 10:50:52 +0200 Subject: [PATCH 2/8] small change --- arduino.py | 196 ++++++++++++++++++++++++++--------------------------- 1 file changed, 98 insertions(+), 98 deletions(-) diff --git a/arduino.py b/arduino.py index cc96ee1..b36c806 100644 --- a/arduino.py +++ b/arduino.py @@ -218,7 +218,7 @@ if Keypad > 0: #setup JoyStick Pins if JoySticks > 0: for port in range(JoySticks): - c.newpin("Jsk.{}".format(JoyStickPins[port]), hal.HAL_FLOAT, hal.HAL_OUT) + c.newpin("Jsk.{}".format(JoyStickPins[port]), hal.HAL_FLOAT, hal.HAL_OUT) c.ready() #setup Serial connection @@ -287,116 +287,116 @@ def managageOutputs(): while True: - time.wait(0.01) - if(arduino.in_waiting()>0): + try: + data = arduino.readline().decode('utf-8') #read Data received from Arduino and decode it + if (Debug):print ("I received:{}".format(data)) + data = data.split(":",1) + try: - data = arduino.readline().decode('utf-8') #read Data received from Arduino and decode it - if (Debug):print ("I received:{}".format(data)) - data = data.split(":",1) - - try: - cmd = data[0][0] - if cmd == "": - if (Debug):print ("No Command!:{}.".format(cmd)) - + cmd = data[0][0] + if cmd == "": + if (Debug):print ("No Command!:{}.".format(cmd)) + + else: + if not data[0][1]: + io = 0 else: - if not data[0][1]: - io = 0 - else: - io = extract_nbr(data[0]) - value = extract_nbr(data[1]) - if value<0: value = 0 - + io = extract_nbr(data[0]) + value = extract_nbr(data[1]) + if value<0: value = 0 + - if cmd == "I": - firstcom = 1 - if value == 1: - c["dIn.{}".format(io)] = 1 - c["dIn.{}-invert".format(io)] = 0 - if(Debug):print("dIn{}:{}".format(io,1)) - - if value == 0: - c["dIn.{}".format(io)] = 0 - c["dIn.{}-invert".format(io)] = 1 - if(Debug):print("dIn{}:{}".format(io,0)) - else:pass + if cmd == "I": + firstcom = 1 + if value == 1: + c["dIn.{}".format(io)] = 1 + c["dIn.{}-invert".format(io)] = 0 + if(Debug):print("dIn{}:{}".format(io,1)) + + if value == 0: + c["dIn.{}".format(io)] = 0 + c["dIn.{}-invert".format(io)] = 1 + if(Debug):print("dIn{}:{}".format(io,0)) + else:pass - elif cmd == "A": - firstcom = 1 - c["aIn.{}".format(io)] = value - if (Debug):print("aIn.{}:{}".format(io,value)) + elif cmd == "A": + firstcom = 1 + c["aIn.{}".format(io)] = value + if (Debug):print("aIn.{}:{}".format(io,value)) - elif cmd == "L": - firstcom = 1 - for Poti in range(LPoti): - if LPotiLatches[Poti][0] == io and SetLPotiValue[Poti] == 0: - for Pin in range(LPotiLatches[Poti][1]): - if Pin == value: - c["LPoti.{}.{}" .format(io,Pin)] = 1 - if(Debug):print("LPoti.{}.{} =1".format(io,Pin)) - else: - c["LPoti.{}.{}" .format(io,Pin)] = 0 - if(Debug):print("LPoti.{}.{} =0".format(io,Pin)) - - if LPotiLatches[Poti][0] == io and SetLPotiValue[Poti] == 1: - c["LPoti.{}.{}" .format(io,"out")] = LPotiValues[Poti][value] - if(Debug):print("LPoti.{}.{} = 0".format("out",LPotiValues[Poti][value])) - - elif cmd == "K": - firstcom = 1 - if SetBinSelKnobValue == 0: - for port in range(BinSelKnobPos): - if port == value: - c["BinSelKnob.{}".format(port)] = 1 - if(Debug):print("BinSelKnob.{}:{}".format(port,1)) + elif cmd == "L": + firstcom = 1 + for Poti in range(LPoti): + if LPotiLatches[Poti][0] == io and SetLPotiValue[Poti] == 0: + for Pin in range(LPotiLatches[Poti][1]): + if Pin == value: + c["LPoti.{}.{}" .format(io,Pin)] = 1 + if(Debug):print("LPoti.{}.{} =1".format(io,Pin)) else: - c["BinSelKnob.{}".format(port)] = 0 - if(Debug):print("BinSelKnob.{}:{}".format(port,0)) - else: - c["BinSelKnob.{}.{}" .format(0,"out")] = BinSelKnobvalues[value] + c["LPoti.{}.{}" .format(io,Pin)] = 0 + if(Debug):print("LPoti.{}.{} =0".format(io,Pin)) + + if LPotiLatches[Poti][0] == io and SetLPotiValue[Poti] == 1: + c["LPoti.{}.{}" .format(io,"out")] = LPotiValues[Poti][value] + if(Debug):print("LPoti.{}.{} = 0".format("out",LPotiValues[Poti][value])) - - elif cmd == "M": - firstcom = 1 - if value == 1: - if Destination[io] == 0 and LinuxKeyboardInput == 1: - subprocess.call(["xdotool", "key", Chars[io]]) - if(Debug):print("Emulating Keypress{}".format(Chars[io])) + elif cmd == "K": + firstcom = 1 + if SetBinSelKnobValue == 0: + for port in range(BinSelKnobPos): + if port == value: + c["BinSelKnob.{}".format(port)] = 1 + if(Debug):print("BinSelKnob.{}:{}".format(port,1)) else: - c["Keypad.{}".format(Chars[io])] = 1 - if(Debug):print("Keypad{}:{}".format(Chars[io],1)) + c["BinSelKnob.{}".format(port)] = 0 + if(Debug):print("BinSelKnob.{}:{}".format(port,0)) + else: + c["BinSelKnob.{}.{}" .format(0,"out")] = BinSelKnobvalues[value] - if value == 0 & Destination[io] == 0: - c["Keypad.{}".format(Chars[io])] = 0 - if(Debug):print("Keypad{}:{}".format(Chars[io],0)) - elif cmd == "R": - firstcom = 1 - c["Jsk.{}".format(io)] = value - if (Debug):print("aIn.{}:{}".format(io,value)) + elif cmd == "M": + firstcom = 1 + if value == 1: + if Destination[io] == 0 and LinuxKeyboardInput == 1: + subprocess.call(["xdotool", "key", Chars[io]]) + if(Debug):print("Emulating Keypress{}".format(Chars[io])) + else: + c["Keypad.{}".format(Chars[io])] = 1 + if(Debug):print("Keypad{}:{}".format(Chars[io],1)) + + if value == 0 & Destination[io] == 0: + c["Keypad.{}".format(Chars[io])] = 0 + if(Debug):print("Keypad{}:{}".format(Chars[io],0)) + + elif cmd == "R": + firstcom = 1 + c["Jsk.{}".format(io)] = value + if (Debug):print("aIn.{}:{}".format(io,value)) - elif cmd == 'E': - arduino.write(b"E0:0\n") - if (Debug):print("Sending E0:0 to establish contact") - else: pass - + elif cmd == 'E': + arduino.write(b"E0:0\n") + if (Debug):print("Sending E0:0 to establish contact") + else: pass + - except: pass - + except: pass + - except KeyboardInterrupt: - if (Debug):print ("Keyboard Interrupted.. BYE") - exit() - except: - if (Debug):print ("I received garbage") - arduino.flush() - - if firstcom == 1: managageOutputs() #if ==1: E0:0 has been exchanged, which means Arduino knows that LinuxCNC is running and starts sending and receiving Data + except KeyboardInterrupt: + if (Debug):print ("Keyboard Interrupted.. BYE") + exit() + except: + if (Debug):print ("I received garbage") + arduino.flush() + + if firstcom == 1: managageOutputs() #if ==1: E0:0 has been exchanged, which means Arduino knows that LinuxCNC is running and starts sending and receiving Data - if keepAlive(event): #keep com alive. This is send to help Arduino detect connection loss. - arduino.write(b"E:\n") - if (Debug):print("keepAlive") - event = time.time() - + if keepAlive(event): #keep com alive. This is send to help Arduino detect connection loss. + arduino.write(b"E:\n") + if (Debug):print("keepAlive") + event = time.time() + + time.wait(0.01) + From c98dba6fc84abef0807574d3ca95e49f8036e769 Mon Sep 17 00:00:00 2001 From: Alexander Richter Date: Sun, 23 Jul 2023 14:17:07 +0200 Subject: [PATCH 3/8] fixed bugs modified int extraction function to also read neg numbers --- arduino.py | 43 +++++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 20 deletions(-) mode change 100644 => 100755 arduino.py diff --git a/arduino.py b/arduino.py old mode 100644 new mode 100755 index b36c806..3a45b4d --- a/arduino.py +++ b/arduino.py @@ -96,10 +96,13 @@ BinSelKnobvalues = [[180,190,200,0,0,0,0,0,0,0,0,0,0,0,0,10,20,30,40,50,60,70,80 #Quadrature Encoders -#Joystick -JoySticks = 1 -JoyStickPins = [[54,56], - [3,1]] +#Enable Joystick support. +# Intended for use as MPG. useing the Joystick will update a counter, which can be used as Jog Input. +# Moving the Joystick will either increase or decrease the counter. Modify Jog-scale in hal to increase or decrease speed. +JoySticks = 1 #number of installed Joysticks +JoyStickPins = [54,55] #Pins the Joysticks are connected to. + #in this example X&Y Pins of the Joystick are connected to Pin A0& A1. Remember, to use the Atmega Pin names here! + # for more than one Joystick just add the other pins to the array for example: JoyStickPins = [54,55,56,57] @@ -217,8 +220,8 @@ if Keypad > 0: c.newpin("Keypad.{}".format(Chars[port]), hal.HAL_BIT, hal.HAL_IN) #setup JoyStick Pins if JoySticks > 0: - for port in range(JoySticks): - c.newpin("Jsk.{}".format(JoyStickPins[port]), hal.HAL_FLOAT, hal.HAL_OUT) + for port in range(JoySticks*2): + c.newpin("Joystick.{}".format(JoyStickPins[port]), hal.HAL_S32, hal.HAL_OUT) c.ready() #setup Serial connection @@ -232,7 +235,7 @@ timeout = 9 #send something after max 9 seconds ######## Functions ######## def keepAlive(event): - return event + timeout < time.time() + return event + timeout < time.time() def readinput(input_str): for i in range(50): @@ -245,14 +248,14 @@ def readinput(input_str): def extract_nbr(input_str): - if input_str is None or input_str == '': - return 0 + if input_str is None or input_str == '': + return 0 - out_number = '' - for ele in input_str: - if ele.isdigit(): - out_number += ele - return int(out_number) + out_number = '' + for i, ele in enumerate(input_str): + if ele.isdigit() or (ele == '-' and i+1 < len(input_str) and input_str[i+1].isdigit()): + out_number += ele + return int(out_number) def managageOutputs(): for port in range(PwmOutputs): @@ -295,7 +298,7 @@ while True: try: cmd = data[0][0] if cmd == "": - if (Debug):print ("No Command!:{}.".format(cmd)) + if (Debug):print ("No Command!:{}".format(cmd)) else: if not data[0][1]: @@ -303,8 +306,8 @@ while True: else: io = extract_nbr(data[0]) value = extract_nbr(data[1]) - if value<0: value = 0 - + #if value<0: value = 0 + if (Debug):print ("No Command!:{}.".format(cmd)) if cmd == "I": firstcom = 1 @@ -370,8 +373,8 @@ while True: elif cmd == "R": firstcom = 1 - c["Jsk.{}".format(io)] = value - if (Debug):print("aIn.{}:{}".format(io,value)) + c["Joystick.{}".format(io)] = value + if (Debug):print("Joystick.{}:{}".format(io,value)) @@ -398,5 +401,5 @@ while True: if (Debug):print("keepAlive") event = time.time() - time.wait(0.01) + time.sleep(0.01) From a63a3f5c8172acb87f2d49eca97dc5c2fedf4f17 Mon Sep 17 00:00:00 2001 From: Alexander Richter Date: Sun, 23 Jul 2023 14:18:18 +0200 Subject: [PATCH 4/8] fixed bugs Joysticks work now --- LinuxCNC_ArduinoConnector.ino | 98 +++++++++++++++++------------------ 1 file changed, 48 insertions(+), 50 deletions(-) diff --git a/LinuxCNC_ArduinoConnector.ino b/LinuxCNC_ArduinoConnector.ino index d5fa0de..b31535c 100644 --- a/LinuxCNC_ArduinoConnector.ino +++ b/LinuxCNC_ArduinoConnector.ino @@ -169,16 +169,11 @@ Encoder Encoder1(18,19); //A,B Pin #define JOYSTICK //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 JOYSTICK - const int JoySticks = 1; - const int JoyStickPins[JoySticks][2] = { - {A0,A2},//Analog Pins JoyStick 1 is connected to - //{2,3}//Analog Pins JoyStick 2 is connected to - }; - const int JoyStickDeadband = 50; //Area around Middle Position that gets ignored. - const int JoyStickSpeed = 100; //Multiplier to slow down the Output Speed if in counter mode. Higher number = slower. - - - const int JoyStickMaxVal = 500; //The Analog Input gets transformed from 0-1023 to -JoyStickMaxVal to +JoyStickMaxVal, so that the Middle Position of the Joystick is 0. I don't think you should change this. +const int JoySticks = 1; // Number of potentiometers connected +const int JoyStickPins[JoySticks*2] = {A0, A1}; // Analog input pins for the potentiometers +const int middleValue = 512; // Middle value of the potentiometer +const int deadband = 20; // Deadband range around the middleValue +const float scalingFactor = 0.01; // Scaling factor to control the impact of distanceFromMiddle #endif @@ -331,8 +326,11 @@ const int debounceDelay = 50; long OldEncCount[RotEncs]; #endif #ifdef JOYSTICK - //int oldJoyStick[JoySticks]; - long JoyStickCount[JoySticks][2]; + +long counter[JoySticks*2] = {0}; // Initialize an array for the counters +long prevCounter[JoySticks*2] = {0}; // Initialize an array for the previous counters +float incrementFactor[JoySticks*2] = {0.0}; // Initialize an array for the incrementFactors +unsigned long lastUpdateTime[JoySticks*2] = {0}; // Store the time of the last update for each potentiometer #endif @@ -417,14 +415,6 @@ for(int col = 0; col < numCols; col++) { } #endif -#ifdef JOYSTICK - for(int i= 0; i 510+JoyStickDeadband || var0 < 510-JoyStickDeadband){ - var0 = map(var0,0,1023,JoyStickMaxVal*-1,JoyStickMaxVal); - JoyStickCount[i][0] = JoyStickCount[i][0] + (var0*2); - sendData('R',JoyStickPins[i][0],JoyStickCount[i][0]/(JoyStickMaxVal*JoyStickSpeed)); - } - if(var1 > 510 + JoyStickDeadband || var1 < 510 - JoyStickDeadband){ - var1 = map(var1,0,1023,JoyStickMaxVal*-1,JoyStickMaxVal); - JoyStickCount[i][1] = JoyStickCount[i][1] + (var1*2) ; - sendData('R',JoyStickPins[i][1],JoyStickCount[i][1]/(JoyStickMaxVal*JoyStickSpeed)); - } + // Check if it's time to update the counter for this potentiometer + if (currentTime - lastUpdateTime[i] >= 100) { // Adjust 100 milliseconds based on your needs + lastUpdateTime[i] = currentTime; // Update the last update time for this potentiometer + int potValue = analogRead(JoyStickPins[i]); // Read the potentiometer value + + // Calculate the distance of the potentiometer value from the middle + int distanceFromMiddle = potValue - middleValue; + + // Apply deadband to ignore small variations around middleValue + if (abs(distanceFromMiddle) <= deadband) { + incrementFactor[i] = 0.0; // Set incrementFactor to 0 within the deadband range + } else { + // Apply non-linear scaling to distanceFromMiddle to get the incrementFactor + incrementFactor[i] = pow((distanceFromMiddle * scalingFactor), 3); + } + + // Update the counter if the incrementFactor has reached a full number + if (incrementFactor[i] >= 1.0 || incrementFactor[i] <= -1.0) { + counter[i] += static_cast(incrementFactor[i]); // Increment or decrement the counter by the integer part of incrementFactor + incrementFactor[i] -= static_cast(incrementFactor[i]); // Subtract the integer part from incrementFactor + } + + // Check if the counter value has changed + if (counter[i] != prevCounter[i]) { + sendData('R',JoyStickPins[i],counter[i]); + // Update the previous counter value with the current counter value + prevCounter[i] = counter[i]; + } + } } } #endif + + void readEncoders(){ if(RotEncs>=1){ EncCount[0] = RotEncMp[0]* Encoder0.read(); @@ -520,7 +525,7 @@ void readEncoders(){ for(int i=0; i<=RotEncs;i++){ if(OldEncCount[i] != EncCount[i]){ - //sendData("R",i,EncCount[i]); + //("R",i,EncCount[i]); OldEncCount[i] = EncCount[i]; } } @@ -731,20 +736,13 @@ void readKeypad(){ pinMode(rowPins[row], INPUT_PULLUP); if (digitalRead(rowPins[row]) == LOW && lastKey != keys[row][col]) { // A button has been pressed - - Serial.print("M"); - Serial.print(keys[row][col]); - Serial.print(":"); - Serial.println(1); + 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 - Serial.print("M"); - Serial.print(keys[row][col]); - Serial.print(":"); - Serial.println(0); + sendData('M',keys[row][col],0); lastKey = 0; row = numRows; } From 163e76906f61f2db38963090c39457e0afeac43c Mon Sep 17 00:00:00 2001 From: Alexander Richter Date: Sun, 23 Jul 2023 15:22:16 +0200 Subject: [PATCH 5/8] added Arduino Support for Quadrature Encoders Python adaptation needed next. --- LinuxCNC_ArduinoConnector.ino | 49 +++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/LinuxCNC_ArduinoConnector.ino b/LinuxCNC_ArduinoConnector.ino index b31535c..cbf73aa 100644 --- a/LinuxCNC_ArduinoConnector.ino +++ b/LinuxCNC_ArduinoConnector.ino @@ -63,10 +63,10 @@ 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 = 5; //number of inputs using internal Pullup resistor. (short to ground to trigger) - int InPinmap[] = {37,38,39,40,41}; + int InPinmap[] = {52,38,39,40,41}; #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. @@ -128,7 +128,7 @@ Note that Analog Pin numbering is different to the Print on the PCB. #endif -#define ROTENC +//#define ROTENC //Support for Rotatary Encoders with Quadrature Output. Define Pins for A and B Signals for your encoders. Visit https://www.pjrc.com/teensy/td_libs_Encoder.html for further explanation. #ifdef ROTENC @@ -155,19 +155,17 @@ Note that Analog Pin numbering is different to the Print on the PCB. //Sanguino 2, 10, 11 0 Encoder Encoder0(2,3); //A,B Pin -Encoder Encoder1(18,19); //A,B Pin +Encoder Encoder1(31,33); //A,B Pin //Encoder Encoder2(A,B); //Encoder Encoder3(A,B); //Encoder Encoder4(A,B); - const int RotEncData[] = {1,2}; //define wich kind of Signal you want to generate. + const int RotEncSig[] = {1,1}; //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 RotEncMp[] = {1,4}; //some Rotary encoders send multiple Electronical Impulses per mechanical pulse. How many Electrical impulses are send for each mechanical Latch? - + const int RotEncMp[] = {1,4}; //some Rotary encoders send multiple Electronical Impulses per mechanical pulse. How many Electrical impulses are send for each mechanical Latch? #endif -#define JOYSTICK //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 JOYSTICK //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 JOYSTICK const int JoySticks = 1; // Number of potentiometers connected const int JoyStickPins[JoySticks*2] = {A0, A1}; // Analog input pins for the potentiometers @@ -192,7 +190,7 @@ const float scalingFactor = 0.01; // Scaling factor to control the impact of d //#define STATUSLED #ifdef STATUSLED - const int StatLedPin = 5; //Pin for Status LED + const int StatLedPin = 13; //Pin for Status LED const int StatLedErrDel[] = {1000,10}; //Blink Timing for Status LED Error (no connection) const int DLEDSTATUSLED = 1; //set to 1 to use Digital LED instead. set StatLedPin to the according LED number in the chain. #endif @@ -508,29 +506,42 @@ void readJoySticks() { void readEncoders(){ if(RotEncs>=1){ - EncCount[0] = RotEncMp[0]* Encoder0.read(); + EncCount[0] = Encoder0.read()/RotEncMp[0]; } if(RotEncs>=2){ - EncCount[1] = RotEncMp[1]* Encoder1.read(); + EncCount[1] = Encoder1.read()/RotEncMp[1]; } if(RotEncs>=3){ - //EncCount[2] = RotEncMp[2]* Encoder2.read(); + //EncCount[2] = Encoder2.read()/RotEncMp[2]; } if(RotEncs>=4){ - //EncCount[3] = RotEncMp[3]* Encoder3.read(); + //EncCount[3] = Encoder3.read()/RotEncMp[3]; } if(RotEncs>=5){ - //EncCount[4] = RotEncMp[4]* Encoder4.read(); + //EncCount[4] = Encoder4.read()/RotEncMp[4]; } - for(int i=0; i<=RotEncs;i++){ - if(OldEncCount[i] != EncCount[i]){ - //("R",i,EncCount[i]); - OldEncCount[i] = EncCount[i]; + for(int i=0; i EncCount[i]){ + sendData('R',i,0); //send Increase by 1 Signal + OldEncCount[i] = EncCount[i]; + } } } } + void comalive(){ #ifdef STATUSLED if(millis() - lastcom > timeout){ From edb005e77876ac51ea7c4477cdf369230c4627a3 Mon Sep 17 00:00:00 2001 From: Alexander Richter Date: Sun, 23 Jul 2023 16:44:40 +0200 Subject: [PATCH 6/8] updating to change workplace --- arduino.py | 98 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 83 insertions(+), 15 deletions(-) diff --git a/arduino.py b/arduino.py index 3a45b4d..3cd9fbc 100755 --- a/arduino.py +++ b/arduino.py @@ -22,10 +22,10 @@ import serial, time, hal # Data is only send everythime it changes once. # Inputs & Toggle Inputs = 'I' -write only -Pin State: 0,1 -# Outputs = 'O' -read only -Pin State: 0,1 -# PWM Outputs = 'P' -read only -Pin State: 0-255 -# Digital LED Outputs = 'D' -read only -Pin State: 0,1 -# Analog Inputs = 'A' -write only -Pin State: 0-1024 +# Outputs = 'O' -read only -Pin State: 0,1 +# PWM Outputs = 'P' -read only -Pin State: 0-255 +# Digital LED Outputs = 'D' -read only -Pin State: 0,1 +# Analog Inputs = 'A' -write only -Pin State: 0-1024 # 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 @@ -94,7 +94,12 @@ SetBinSelKnobValue = [1] BinSelKnobvalues = [[180,190,200,0,0,0,0,0,0,0,0,0,0,0,0,10,20,30,40,50,60,70,80,90,100,110,120,130,140,150,160,170], [0.001,0.01,0.1,1]] -#Quadrature Encoders +#Enable Quadrature Encoders +QuadEncs = 2 +QuadEncSig = [1,1] +#1 = send up or down signal (typical use for selecting modes in hal) +#2 = send position signal (typical use for MPG wheel) + #Enable Joystick support. # Intended for use as MPG. useing the Joystick will update a counter, which can be used as Jog Input. @@ -169,25 +174,30 @@ if LinuxKeyboardInput: Inputs = Inputs+ SInputs InPinmap += sInPinmap + + +# Storing Variables for counter timing Stuff +counter_last_update = {} +counter_hold_interval = 100 ######## SetUp of HalPins ######## # setup Input halpins for port in range(Inputs): - c.newpin("dIn.{}".format(InPinmap[port]), hal.HAL_BIT, hal.HAL_OUT) - c.newparam("dIn.{}-invert".format(InPinmap[port]), hal.HAL_BIT, hal.HAL_RW) + c.newpin("dIn.{}".format(InPinmap[port]), hal.HAL_BIT, hal.HAL_OUT) + c.newparam("dIn.{}-invert".format(InPinmap[port]), hal.HAL_BIT, hal.HAL_RW) # setup Output halpins for port in range(Outputs): - c.newpin("dOut.{}".format(OutPinmap[port]), hal.HAL_BIT, hal.HAL_IN) - olddOutStates[port] = 0 + c.newpin("dOut.{}".format(OutPinmap[port]), hal.HAL_BIT, hal.HAL_IN) + olddOutStates[port] = 0 # setup Pwm Output halpins for port in range(PwmOutputs): - c.newpin("PwmOut.{}".format(PwmOutPinmap[port]), hal.HAL_FLOAT, hal.HAL_IN) - oldPwmOutStates[port] = 255 + c.newpin("PwmOut.{}".format(PwmOutPinmap[port]), hal.HAL_FLOAT, hal.HAL_IN) + oldPwmOutStates[port] = 255 # setup Analog Input halpins for port in range(AInputs): - c.newpin("aIn.{}".format(AInPinmap[port]), hal.HAL_FLOAT, hal.HAL_OUT) + c.newpin("aIn.{}".format(AInPinmap[port]), hal.HAL_FLOAT, hal.HAL_OUT) # setup Latching Poti halpins for Poti in range(LPoti): @@ -221,7 +231,19 @@ if Keypad > 0: #setup JoyStick Pins if JoySticks > 0: for port in range(JoySticks*2): - c.newpin("Joystick.{}".format(JoyStickPins[port]), hal.HAL_S32, hal.HAL_OUT) + c.newpin("Counter.{}".format(JoyStickPins[port]), hal.HAL_S32, hal.HAL_OUT) + + +if QuadEncs > 0: + for port in range(QuadEncs): + if QuadEncSig[port] == 1: + c.newpin("CounterUp.{}".format(port), hal.HAL_BIT, hal.HAL_OUT) + c.newpin("CounterDown.{}".format(port), hal.HAL_BIT, hal.HAL_OUT) + if QuadEncSig[port] == 2: + c.newpin("Counter.{}".format(port), hal.HAL_S32, hal.HAL_OUT) + + + c.ready() #setup Serial connection @@ -373,11 +395,57 @@ while True: elif cmd == "R": firstcom = 1 - c["Joystick.{}".format(io)] = value - if (Debug):print("Joystick.{}:{}".format(io,value)) + if JoySticks > 0: + for pins in range(JoySticks*2): + if (io == JoyStickPins[pins]): + c["Counter.{}".format(io)] = value + if (Debug):print("Counter.{}:{}".format(io,value)) + if QuadEncs > 0: + if QuadEncSig[io]== 1: + if value == 0: + c["CounterDown.{}".format(io)] = 1 + time.sleep(0.1) + c["CounterDown.{}".format(io)] = 0 + if value == 1: + c["CounterUp.{}".format(io)] = 1 + time.sleep(0.1) + c["CounterUp.{}".format(io)] = 0 + if QuadEncSig[io]== 2: + c["Counter.{}".format(io)] = value + + + # Check if the button is not already in the dictionary, and set its last update time to 0 + if io not in counter_last_update: + counter_last_update[io] = 0 + + if JoySticks > 0: + for pins in range(JoySticks*2): + if (io == JoyStickPins[pins]): + c["Counter.{}".format(io)] = value + if Debug: + print("Counter.{}:{}".format(io, value)) + + if QuadEncs > 0: + if QuadEncSig[io] == 1: + # Check if enough time has passed since the last update + if millis() - counter_last_update[io] >= counter_hold_interval: + counter_last_update[io] = millis() # Update the last update time for the button + if value == 0: + c["CounterDown.{}".format(io)] = 1 + counter_last_update[io] = millis() # Update the last update time for the button + if value == 1: + c["CounterUp.{}".format(io)] = 1 + counter_last_update[io] = millis() # Update the last update time for the button + elif QuadEncSig[io] == 2: + c["Counter.{}".format(io)] = value + + elif cmd == "R": + firstcom = 1 + handle_button_press(io, value) + elif cmd == 'E': arduino.write(b"E0:0\n") if (Debug):print("Sending E0:0 to establish contact") From 60be9d87367b48fca513f505b556752f45ecba4b Mon Sep 17 00:00:00 2001 From: Alexander Richter Date: Sun, 23 Jul 2023 17:06:16 +0200 Subject: [PATCH 7/8] maybe this works... --- LinuxCNC_ArduinoConnector.ino | 57 +++++++++++++++++------------ arduino.py | 67 +++++++++++------------------------ 2 files changed, 56 insertions(+), 68 deletions(-) diff --git a/LinuxCNC_ArduinoConnector.ino b/LinuxCNC_ArduinoConnector.ino index cbf73aa..af3ceaa 100644 --- a/LinuxCNC_ArduinoConnector.ino +++ b/LinuxCNC_ArduinoConnector.ino @@ -128,12 +128,14 @@ Note that Analog Pin numbering is different to the Print on the PCB. #endif -//#define ROTENC +#define QUADENC //Support for Rotatary Encoders with Quadrature Output. Define Pins for A and B Signals for your encoders. Visit https://www.pjrc.com/teensy/td_libs_Encoder.html for further explanation. -#ifdef ROTENC +#ifdef QUADENC #include - const int RotEncs = 2; //how many Rotary Encoders do you want? + const int QuadEncs = 2; //how many Rotary Encoders do you want? + #define QUADENCS 2 + // Encoders have 2 signals, which must be connected to 2 pins. There are three options. //Best Performance: Both signals connect to interrupt pins. @@ -159,10 +161,11 @@ Encoder Encoder1(31,33); //A,B Pin //Encoder Encoder2(A,B); //Encoder Encoder3(A,B); //Encoder Encoder4(A,B); - const int RotEncSig[] = {1,1}; //define wich kind of Signal you want to generate. + const int QuadEncSig[] = {1,1}; //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 RotEncMp[] = {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[] = {1,4}; //some Rotary encoders send multiple Electronical Impulses per mechanical pulse. How many Electrical impulses are send for each mechanical Latch? + #endif //#define JOYSTICK //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. @@ -319,9 +322,9 @@ const int debounceDelay = 50; #ifdef KEYPAD byte KeyState = 0; #endif -#ifdef ROTENC - long EncCount[RotEncs]; - long OldEncCount[RotEncs]; +#ifdef QUADENC + long EncCount[QuadEncs]; + long OldEncCount[QuadEncs]; #endif #ifdef JOYSTICK @@ -455,7 +458,7 @@ void loop() { readKeypad(); //read Keyboard & send data #endif -#ifdef ROTENC +#ifdef QUADENC readEncoders(); //read Encoders & send data #endif #ifdef JOYSTICK @@ -505,30 +508,40 @@ void readJoySticks() { void readEncoders(){ - if(RotEncs>=1){ - EncCount[0] = Encoder0.read()/RotEncMp[0]; + if(QuadEncs>=1){ + #if QUADENCS >= 1 + EncCount[0] = Encoder0.read()/QuadEncMp[0]; + #endif } - if(RotEncs>=2){ - EncCount[1] = Encoder1.read()/RotEncMp[1]; + if(QuadEncs>=2){ + #if QUADENCS >= 2 + EncCount[1] = Encoder1.read()/QuadEncMp[1]; + #endif } - if(RotEncs>=3){ - //EncCount[2] = Encoder2.read()/RotEncMp[2]; + if(QuadEncs>=3){ + #if QUADENCS >= 3 + EncCount[2] = Encoder2.read()/QuadEncMp[2]; + #endif } - if(RotEncs>=4){ - //EncCount[3] = Encoder3.read()/RotEncMp[3]; + if(QuadEncs>=4){ + #if QUADENCS >= 4 + EncCount[3] = Encoder3.read()/QuadEncMp[3]; + #endif } - if(RotEncs>=5){ - //EncCount[4] = Encoder4.read()/RotEncMp[4]; + if(QuadEncs>=5){ + #if QUADENCS >= 5 + EncCount[4] = Encoder4.read()/QuadEncMp[4]; + #endif } - for(int i=0; i 0: - for pins in range(JoySticks*2): - if (io == JoyStickPins[pins]): - c["Counter.{}".format(io)] = value - if (Debug):print("Counter.{}:{}".format(io,value)) - if QuadEncs > 0: - if QuadEncSig[io]== 1: - if value == 0: - c["CounterDown.{}".format(io)] = 1 - time.sleep(0.1) - c["CounterDown.{}".format(io)] = 0 - if value == 1: - c["CounterUp.{}".format(io)] = 1 - time.sleep(0.1) - c["CounterUp.{}".format(io)] = 0 - if QuadEncSig[io]== 2: - c["Counter.{}".format(io)] = value + firstcom = 1 - - # Check if the button is not already in the dictionary, and set its last update time to 0 + if JoySticks > 0: + for pins in range(JoySticks * 2): + if io == JoyStickPins[pins]: + c["Counter.{}".format(io)] = value + if Debug: + print("Counter.{}:{}".format(io, value)) + + if QuadEncs > 0: if io not in counter_last_update: counter_last_update[io] = 0 + if time.time() - counter_last_update[io] >= min_update_interval: + global counter_last_update + if QuadEncSig[io] == 1: + if value == 0: + c["CounterDown.{}".format(io)] = 1 + counter_last_update[io] = time.time() # Set the last update time + elif value == 1: + c["CounterUp.{}".format(io)] = 1 + counter_last_update[io] = time.time() # Set the last update time + elif QuadEncSig[io] == 2: + c["Counter.{}".format(io)] = value - if JoySticks > 0: - for pins in range(JoySticks*2): - if (io == JoyStickPins[pins]): - c["Counter.{}".format(io)] = value - if Debug: - print("Counter.{}:{}".format(io, value)) - - if QuadEncs > 0: - if QuadEncSig[io] == 1: - # Check if enough time has passed since the last update - if millis() - counter_last_update[io] >= counter_hold_interval: - counter_last_update[io] = millis() # Update the last update time for the button - if value == 0: - c["CounterDown.{}".format(io)] = 1 - counter_last_update[io] = millis() # Update the last update time for the button - if value == 1: - c["CounterUp.{}".format(io)] = 1 - counter_last_update[io] = millis() # Update the last update time for the button - elif QuadEncSig[io] == 2: - c["Counter.{}".format(io)] = value - - elif cmd == "R": - firstcom = 1 - handle_button_press(io, value) - elif cmd == 'E': arduino.write(b"E0:0\n") if (Debug):print("Sending E0:0 to establish contact") From 92cfa1621297baa930ba400eebcb397fdff549cf Mon Sep 17 00:00:00 2001 From: Alexander Richter Date: Sun, 23 Jul 2023 17:29:17 +0200 Subject: [PATCH 8/8] now it works --- arduino.py | 42 ++++++++++++++++++------------------------ 1 file changed, 18 insertions(+), 24 deletions(-) diff --git a/arduino.py b/arduino.py index cbe21ab..84e2c2b 100755 --- a/arduino.py +++ b/arduino.py @@ -96,7 +96,7 @@ BinSelKnobvalues = [[180,190,200,0,0,0,0,0,0,0,0,0,0,0,0,10,20,30,40,50,60,70,80 #Enable Quadrature Encoders QuadEncs = 2 -QuadEncSig = [1,1] +QuadEncSig = [2,2] #1 = send up or down signal (typical use for selecting modes in hal) #2 = send position signal (typical use for MPG wheel) @@ -394,32 +394,26 @@ while True: if(Debug):print("Keypad{}:{}".format(Chars[io],0)) elif cmd == "R": - firstcom = 1 - - if JoySticks > 0: - for pins in range(JoySticks * 2): - if io == JoyStickPins[pins]: - c["Counter.{}".format(io)] = value - if Debug: - print("Counter.{}:{}".format(io, value)) - - if QuadEncs > 0: - if io not in counter_last_update: - counter_last_update[io] = 0 - - if time.time() - counter_last_update[io] >= min_update_interval: - global counter_last_update - - if QuadEncSig[io] == 1: + firstcom = 1 + if JoySticks > 0: + for pins in range(JoySticks*2): + if (io == JoyStickPins[pins]): + c["Counter.{}".format(io)] = value + if (Debug):print("Counter.{}:{}".format(io,value)) + if QuadEncs > 0: + if QuadEncSig[io]== 1: if value == 0: c["CounterDown.{}".format(io)] = 1 - counter_last_update[io] = time.time() # Set the last update time - elif value == 1: + time.sleep(0.05) + c["CounterDown.{}".format(io)] = 0 + time.sleep(0.05) + if value == 1: c["CounterUp.{}".format(io)] = 1 - counter_last_update[io] = time.time() # Set the last update time - elif QuadEncSig[io] == 2: - c["Counter.{}".format(io)] = value - + time.sleep(0.05) + c["CounterUp.{}".format(io)] = 0 + time.sleep(0.05) + if QuadEncSig[io]== 2: + c["Counter.{}".format(io)] = value elif cmd == 'E': arduino.write(b"E0:0\n")