├── stepper.png ├── README.md ├── Adafruit_MCP23017.h ├── Trinamic_TMC2130.h ├── Adafruit_MCP23017.cpp ├── Trinamic_TMC2130_registers.h ├── Trinamic_TMC2130.cpp └── CI-V_stepper.ino /stepper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ok1hra/CI-V_stepper/master/stepper.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Icom CI-V stepper 2 | 3 | Firmware for Arduino Leonardo chip 4 | [Web page](https://remoteqth.com/civ-stepper.php) 5 | 6 | ![Hardware](stepper.png) 7 | -------------------------------------------------------------------------------- /Adafruit_MCP23017.h: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | This is a library for the MCP23017 i2c port expander 3 | 4 | These displays use I2C to communicate, 2 pins are required to 5 | interface 6 | Adafruit invests time and resources providing this open source code, 7 | please support Adafruit and open-source hardware by purchasing 8 | products from Adafruit! 9 | 10 | Written by Limor Fried/Ladyada for Adafruit Industries. 11 | BSD license, all text above must be included in any redistribution 12 | ****************************************************/ 13 | 14 | #ifndef _Adafruit_MCP23017_H_ 15 | #define _Adafruit_MCP23017_H_ 16 | 17 | // Don't forget the Wire library 18 | #ifndef ARDUINO_AVR_GEMMA 19 | //TinyWireM is now part of 20 | // Adafruit version of Wire Library, so this 21 | // will work with Adafruit ATtiny85's 22 | //But Arduino Gemma doesn't use that library 23 | // We do NOT want to include Wire if it's an arduino Gemma 24 | #include 25 | #else 26 | #include 27 | #define Wire TinyWireM 28 | #endif 29 | 30 | 31 | class Adafruit_MCP23017 { 32 | public: 33 | void begin(uint8_t addr); 34 | void begin(void); 35 | 36 | void pinMode(uint8_t p, uint8_t d); 37 | void digitalWrite(uint8_t p, uint8_t d); 38 | void pullUp(uint8_t p, uint8_t d); 39 | uint8_t digitalRead(uint8_t p); 40 | 41 | void writeGPIOAB(uint16_t); 42 | uint16_t readGPIOAB(); 43 | uint8_t readGPIO(uint8_t b); 44 | 45 | void setupInterrupts(uint8_t mirroring, uint8_t open, uint8_t polarity); 46 | void setupInterruptPin(uint8_t p, uint8_t mode); 47 | uint8_t getLastInterruptPin(); 48 | uint8_t getLastInterruptPinValue(); 49 | 50 | private: 51 | uint8_t i2caddr; 52 | 53 | uint8_t bitForPin(uint8_t pin); 54 | uint8_t regForPin(uint8_t pin, uint8_t portAaddr, uint8_t portBaddr); 55 | 56 | uint8_t readRegister(uint8_t addr); 57 | void writeRegister(uint8_t addr, uint8_t value); 58 | 59 | /** 60 | * Utility private method to update a register associated with a pin (whether port A/B) 61 | * reads its value, updates the particular bit, and writes its value. 62 | */ 63 | void updateRegisterBit(uint8_t p, uint8_t pValue, uint8_t portAaddr, uint8_t portBaddr); 64 | 65 | }; 66 | 67 | #define MCP23017_ADDRESS 0x20 68 | 69 | // registers 70 | #define MCP23017_IODIRA 0x00 71 | #define MCP23017_IPOLA 0x02 72 | #define MCP23017_GPINTENA 0x04 73 | #define MCP23017_DEFVALA 0x06 74 | #define MCP23017_INTCONA 0x08 75 | #define MCP23017_IOCONA 0x0A 76 | #define MCP23017_GPPUA 0x0C 77 | #define MCP23017_INTFA 0x0E 78 | #define MCP23017_INTCAPA 0x10 79 | #define MCP23017_GPIOA 0x12 80 | #define MCP23017_OLATA 0x14 81 | 82 | 83 | #define MCP23017_IODIRB 0x01 84 | #define MCP23017_IPOLB 0x03 85 | #define MCP23017_GPINTENB 0x05 86 | #define MCP23017_DEFVALB 0x07 87 | #define MCP23017_INTCONB 0x09 88 | #define MCP23017_IOCONB 0x0B 89 | #define MCP23017_GPPUB 0x0D 90 | #define MCP23017_INTFB 0x0F 91 | #define MCP23017_INTCAPB 0x11 92 | #define MCP23017_GPIOB 0x13 93 | #define MCP23017_OLATB 0x15 94 | 95 | #define MCP23017_INT_ERR 255 96 | 97 | #endif 98 | -------------------------------------------------------------------------------- /Trinamic_TMC2130.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file Trinamic_TMC2130.h 4 | @author Moritz Walter 5 | @license GPLv3 (see license.txt) 6 | 7 | SPI configuration tool for Trinamic TMC2130 Motor Drivers 8 | 9 | @section HISTORY 10 | 11 | v0.1 - it works 12 | */ 13 | /**************************************************************************/ 14 | #ifndef TRINAMIC_TMC2130_H 15 | #define TRINAMIC_TMC2130_H 16 | 17 | #if ARDUINO >= 100 18 | #include "Arduino.h" 19 | #else 20 | #include "WProgram.h" 21 | #endif 22 | 23 | #include 24 | 25 | #include "Trinamic_TMC2130_registers.h" 26 | 27 | class Trinamic_TMC2130{ 28 | public: 29 | Trinamic_TMC2130(uint8_t csPin); 30 | void init(); 31 | void init_SPI(); 32 | 33 | uint8_t read_STAT(); 34 | uint8_t read_REG( uint8_t address , uint32_t *data ); 35 | uint8_t write_REG( uint8_t address, uint32_t data ); 36 | uint8_t alter_REG(uint8_t address, uint32_t data, uint32_t mask); 37 | 38 | uint8_t set_GCONF(uint8_t bit, uint8_t value); 39 | uint8_t set_I_scale_analog(uint8_t value); 40 | uint8_t set_internal_Rsense(uint8_t value); 41 | uint8_t set_en_pwm_mode(uint8_t value); 42 | uint8_t set_enc_commutation(uint8_t value); 43 | uint8_t set_shaft(uint8_t value); 44 | uint8_t set_diag0_error(uint8_t value); 45 | uint8_t set_diag0_otpw(uint8_t value); 46 | uint8_t set_diag0_stall(uint8_t value); 47 | uint8_t set_diag1_stall(uint8_t value); 48 | uint8_t set_diag1_index(uint8_t value); 49 | uint8_t set_diag1_onstate(uint8_t value); 50 | uint8_t set_diag1_steps_skipped(uint8_t value); 51 | uint8_t set_diag0_int_pushpull(uint8_t value); 52 | uint8_t set_diag1_int_pushpull(uint8_t value); 53 | uint8_t set_small_hysteresis(uint8_t value); 54 | uint8_t set_stop_enable(uint8_t value); 55 | uint8_t set_direct_mode(uint8_t value); 56 | //uint8_t test_mode(uint8_t value); 57 | 58 | uint8_t set_IHOLD_IRUN(uint8_t ihold, uint8_t irun, uint8_t iholddelay); 59 | uint8_t set_TPOWERDOWN(uint8_t value); 60 | uint32_t get_TSTEP(); 61 | uint8_t set_TPWMTHRS(uint32_t value); 62 | uint8_t set_TCOOLTHRS(uint32_t value); 63 | uint8_t set_THIGH(uint32_t value); 64 | uint8_t set_XDIRECT(uint32_t value); 65 | uint8_t set_XDIRECT(int16_t coil_a, int16_t coil_b); 66 | int32_t get_XDIRECT(); 67 | uint8_t set_VDCMIN(int32_t value); 68 | 69 | uint8_t set_MSLUT0(uint32_t value); 70 | uint8_t set_MSLUT1(uint32_t value); 71 | uint8_t set_MSLUT2(uint32_t value); 72 | uint8_t set_MSLUT3(uint32_t value); 73 | uint8_t set_MSLUT4(uint32_t value); 74 | uint8_t set_MSLUT5(uint32_t value); 75 | uint8_t set_MSLUT6(uint32_t value); 76 | uint8_t set_MSLUT7(uint32_t value); 77 | uint8_t set_MSLUTSEL(uint32_t value); 78 | uint8_t set_MSLUTSTART(uint8_t start_sin, uint8_t start_sin90); 79 | uint16_t get_MSCNT(); 80 | int32_t get_MSCURACT(); 81 | 82 | uint8_t set_CHOPCONF(uint8_t position, uint8_t value); 83 | uint8_t set_dedge(uint8_t value); 84 | uint8_t set_diss2g(uint8_t value); 85 | uint8_t set_intpol(uint8_t value); 86 | uint8_t set_mres(uint16_t value); 87 | uint8_t set_sync(uint8_t value); 88 | uint8_t set_vhighchm(uint8_t value); 89 | uint8_t set_vhighfs(uint8_t value); 90 | uint8_t set_vsense(uint8_t value); 91 | uint8_t set_tbl(uint8_t value); 92 | uint8_t set_chm(uint8_t value); 93 | uint8_t set_rndtf(uint8_t value); 94 | uint8_t set_disfdcc(uint8_t value); 95 | uint8_t set_fd(uint8_t value); 96 | uint8_t set_hend(uint8_t value); 97 | uint8_t set_hstrt(uint8_t value); 98 | uint8_t set_toff(uint8_t value); 99 | 100 | uint8_t alter_COOLCONF(uint32_t data, uint32_t mask); 101 | uint8_t set_COOLCONF(uint8_t position, uint8_t value); 102 | uint8_t set_sfilt(uint8_t value); 103 | uint8_t set_sgt(uint8_t value); 104 | uint8_t set_seimin(uint8_t value); 105 | uint8_t set_sedn(uint8_t value); 106 | uint8_t set_semax(uint8_t value); 107 | uint8_t set_seup(uint8_t value); 108 | uint8_t set_semin(uint8_t value); 109 | 110 | uint8_t set_DCCTRL(uint16_t dc_time, uint16_t dc_sg); 111 | 112 | uint8_t alter_PWMCONF(uint32_t data, uint32_t mask); 113 | uint8_t set_PWMCONF(uint8_t position, uint8_t value); 114 | uint8_t set_freewheel(uint8_t value); 115 | uint8_t set_pwm_symmetric(uint8_t value); 116 | uint8_t set_pwm_autoscale(uint8_t value); 117 | uint8_t set_pwm_freq(uint8_t value); 118 | uint8_t set_PWM_GRAD(uint8_t value); 119 | uint8_t set_PWM_AMPL(uint8_t value); 120 | 121 | uint8_t set_ENCM_CTRL(uint8_t value); 122 | 123 | boolean isReset(); 124 | boolean isError(); 125 | boolean isStallguard(); 126 | boolean isStandstill(); 127 | String debug(); 128 | 129 | private: 130 | uint32_t _coolconf; 131 | uint32_t _pwmconf; 132 | uint8_t _csPin; 133 | uint8_t _status; 134 | String _debug; 135 | }; 136 | 137 | #endif // TRINAMIC_TMC2130_H 138 | -------------------------------------------------------------------------------- /Adafruit_MCP23017.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | This is a library for the MCP23017 i2c port expander 3 | 4 | These displays use I2C to communicate, 2 pins are required to 5 | interface 6 | Adafruit invests time and resources providing this open source code, 7 | please support Adafruit and open-source hardware by purchasing 8 | products from Adafruit! 9 | 10 | Written by Limor Fried/Ladyada for Adafruit Industries. 11 | BSD license, all text above must be included in any redistribution 12 | ****************************************************/ 13 | 14 | #ifdef __AVR 15 | #include 16 | #elif defined(ESP8266) 17 | #include 18 | #endif 19 | #include "Adafruit_MCP23017.h" 20 | 21 | #if ARDUINO >= 100 22 | #include "Arduino.h" 23 | #else 24 | #include "WProgram.h" 25 | #endif 26 | 27 | // minihelper to keep Arduino backward compatibility 28 | static inline void wiresend(uint8_t x) { 29 | #if ARDUINO >= 100 30 | Wire.write((uint8_t) x); 31 | #else 32 | Wire.send(x); 33 | #endif 34 | } 35 | 36 | static inline uint8_t wirerecv(void) { 37 | #if ARDUINO >= 100 38 | return Wire.read(); 39 | #else 40 | return Wire.receive(); 41 | #endif 42 | } 43 | 44 | /** 45 | * Bit number associated to a give Pin 46 | */ 47 | uint8_t Adafruit_MCP23017::bitForPin(uint8_t pin){ 48 | return pin%8; 49 | } 50 | 51 | /** 52 | * Register address, port dependent, for a given PIN 53 | */ 54 | uint8_t Adafruit_MCP23017::regForPin(uint8_t pin, uint8_t portAaddr, uint8_t portBaddr){ 55 | return(pin<8) ?portAaddr:portBaddr; 56 | } 57 | 58 | /** 59 | * Reads a given register 60 | */ 61 | uint8_t Adafruit_MCP23017::readRegister(uint8_t addr){ 62 | // read the current GPINTEN 63 | Wire.beginTransmission(MCP23017_ADDRESS | i2caddr); 64 | wiresend(addr); 65 | Wire.endTransmission(); 66 | Wire.requestFrom(MCP23017_ADDRESS | i2caddr, 1); 67 | return wirerecv(); 68 | } 69 | 70 | 71 | /** 72 | * Writes a given register 73 | */ 74 | void Adafruit_MCP23017::writeRegister(uint8_t regAddr, uint8_t regValue){ 75 | // Write the register 76 | Wire.beginTransmission(MCP23017_ADDRESS | i2caddr); 77 | wiresend(regAddr); 78 | wiresend(regValue); 79 | Wire.endTransmission(); 80 | } 81 | 82 | 83 | /** 84 | * Helper to update a single bit of an A/B register. 85 | * - Reads the current register value 86 | * - Writes the new register value 87 | */ 88 | void Adafruit_MCP23017::updateRegisterBit(uint8_t pin, uint8_t pValue, uint8_t portAaddr, uint8_t portBaddr) { 89 | uint8_t regValue; 90 | uint8_t regAddr=regForPin(pin,portAaddr,portBaddr); 91 | uint8_t bit=bitForPin(pin); 92 | regValue = readRegister(regAddr); 93 | 94 | // set the value for the particular bit 95 | bitWrite(regValue,bit,pValue); 96 | 97 | writeRegister(regAddr,regValue); 98 | } 99 | 100 | //////////////////////////////////////////////////////////////////////////////// 101 | 102 | /** 103 | * Initializes the MCP23017 given its HW selected address, see datasheet for Address selection. 104 | */ 105 | void Adafruit_MCP23017::begin(uint8_t addr) { 106 | if (addr > 7) { 107 | addr = 7; 108 | } 109 | i2caddr = addr; 110 | 111 | Wire.begin(); 112 | 113 | // set defaults! 114 | // all inputs on port A and B 115 | writeRegister(MCP23017_IODIRA,0xff); 116 | writeRegister(MCP23017_IODIRB,0xff); 117 | } 118 | 119 | /** 120 | * Initializes the default MCP23017, with 000 for the configurable part of the address 121 | */ 122 | void Adafruit_MCP23017::begin(void) { 123 | begin(0); 124 | } 125 | 126 | /** 127 | * Sets the pin mode to either INPUT or OUTPUT 128 | */ 129 | void Adafruit_MCP23017::pinMode(uint8_t p, uint8_t d) { 130 | updateRegisterBit(p,(d==INPUT),MCP23017_IODIRA,MCP23017_IODIRB); 131 | } 132 | 133 | /** 134 | * Reads all 16 pins (port A and B) into a single 16 bits variable. 135 | */ 136 | uint16_t Adafruit_MCP23017::readGPIOAB() { 137 | uint16_t ba = 0; 138 | uint8_t a; 139 | 140 | // read the current GPIO output latches 141 | Wire.beginTransmission(MCP23017_ADDRESS | i2caddr); 142 | wiresend(MCP23017_GPIOA); 143 | Wire.endTransmission(); 144 | 145 | Wire.requestFrom(MCP23017_ADDRESS | i2caddr, 2); 146 | a = wirerecv(); 147 | ba = wirerecv(); 148 | ba <<= 8; 149 | ba |= a; 150 | 151 | return ba; 152 | } 153 | 154 | /** 155 | * Read a single port, A or B, and return its current 8 bit value. 156 | * Parameter b should be 0 for GPIOA, and 1 for GPIOB. 157 | */ 158 | uint8_t Adafruit_MCP23017::readGPIO(uint8_t b) { 159 | 160 | // read the current GPIO output latches 161 | Wire.beginTransmission(MCP23017_ADDRESS | i2caddr); 162 | if (b == 0) 163 | wiresend(MCP23017_GPIOA); 164 | else { 165 | wiresend(MCP23017_GPIOB); 166 | } 167 | Wire.endTransmission(); 168 | 169 | Wire.requestFrom(MCP23017_ADDRESS | i2caddr, 1); 170 | return wirerecv(); 171 | } 172 | 173 | /** 174 | * Writes all the pins in one go. This method is very useful if you are implementing a multiplexed matrix and want to get a decent refresh rate. 175 | */ 176 | void Adafruit_MCP23017::writeGPIOAB(uint16_t ba) { 177 | Wire.beginTransmission(MCP23017_ADDRESS | i2caddr); 178 | wiresend(MCP23017_GPIOA); 179 | wiresend(ba & 0xFF); 180 | wiresend(ba >> 8); 181 | Wire.endTransmission(); 182 | } 183 | 184 | void Adafruit_MCP23017::digitalWrite(uint8_t pin, uint8_t d) { 185 | uint8_t gpio; 186 | uint8_t bit=bitForPin(pin); 187 | 188 | 189 | // read the current GPIO output latches 190 | uint8_t regAddr=regForPin(pin,MCP23017_OLATA,MCP23017_OLATB); 191 | gpio = readRegister(regAddr); 192 | 193 | // set the pin and direction 194 | bitWrite(gpio,bit,d); 195 | 196 | // write the new GPIO 197 | regAddr=regForPin(pin,MCP23017_GPIOA,MCP23017_GPIOB); 198 | writeRegister(regAddr,gpio); 199 | } 200 | 201 | void Adafruit_MCP23017::pullUp(uint8_t p, uint8_t d) { 202 | updateRegisterBit(p,d,MCP23017_GPPUA,MCP23017_GPPUB); 203 | } 204 | 205 | uint8_t Adafruit_MCP23017::digitalRead(uint8_t pin) { 206 | uint8_t bit=bitForPin(pin); 207 | uint8_t regAddr=regForPin(pin,MCP23017_GPIOA,MCP23017_GPIOB); 208 | return (readRegister(regAddr) >> bit) & 0x1; 209 | } 210 | 211 | /** 212 | * Configures the interrupt system. both port A and B are assigned the same configuration. 213 | * Mirroring will OR both INTA and INTB pins. 214 | * Opendrain will set the INT pin to value or open drain. 215 | * polarity will set LOW or HIGH on interrupt. 216 | * Default values after Power On Reset are: (false, false, LOW) 217 | * If you are connecting the INTA/B pin to arduino 2/3, you should configure the interupt handling as FALLING with 218 | * the default configuration. 219 | */ 220 | void Adafruit_MCP23017::setupInterrupts(uint8_t mirroring, uint8_t openDrain, uint8_t polarity){ 221 | // configure the port A 222 | uint8_t ioconfValue=readRegister(MCP23017_IOCONA); 223 | bitWrite(ioconfValue,6,mirroring); 224 | bitWrite(ioconfValue,2,openDrain); 225 | bitWrite(ioconfValue,1,polarity); 226 | writeRegister(MCP23017_IOCONA,ioconfValue); 227 | 228 | // Configure the port B 229 | ioconfValue=readRegister(MCP23017_IOCONB); 230 | bitWrite(ioconfValue,6,mirroring); 231 | bitWrite(ioconfValue,2,openDrain); 232 | bitWrite(ioconfValue,1,polarity); 233 | writeRegister(MCP23017_IOCONB,ioconfValue); 234 | } 235 | 236 | /** 237 | * Set's up a pin for interrupt. uses arduino MODEs: CHANGE, FALLING, RISING. 238 | * 239 | * Note that the interrupt condition finishes when you read the information about the port / value 240 | * that caused the interrupt or you read the port itself. Check the datasheet can be confusing. 241 | * 242 | */ 243 | void Adafruit_MCP23017::setupInterruptPin(uint8_t pin, uint8_t mode) { 244 | 245 | // set the pin interrupt control (0 means change, 1 means compare against given value); 246 | updateRegisterBit(pin,(mode!=CHANGE),MCP23017_INTCONA,MCP23017_INTCONB); 247 | // if the mode is not CHANGE, we need to set up a default value, different value triggers interrupt 248 | 249 | // In a RISING interrupt the default value is 0, interrupt is triggered when the pin goes to 1. 250 | // In a FALLING interrupt the default value is 1, interrupt is triggered when pin goes to 0. 251 | updateRegisterBit(pin,(mode==FALLING),MCP23017_DEFVALA,MCP23017_DEFVALB); 252 | 253 | // enable the pin for interrupt 254 | updateRegisterBit(pin,HIGH,MCP23017_GPINTENA,MCP23017_GPINTENB); 255 | 256 | } 257 | 258 | uint8_t Adafruit_MCP23017::getLastInterruptPin(){ 259 | uint8_t intf; 260 | 261 | // try port A 262 | intf=readRegister(MCP23017_INTFA); 263 | for(int i=0;i<8;i++) if (bitRead(intf,i)) return i; 264 | 265 | // try port B 266 | intf=readRegister(MCP23017_INTFB); 267 | for(int i=0;i<8;i++) if (bitRead(intf,i)) return i+8; 268 | 269 | return MCP23017_INT_ERR; 270 | 271 | } 272 | uint8_t Adafruit_MCP23017::getLastInterruptPinValue(){ 273 | uint8_t intPin=getLastInterruptPin(); 274 | if(intPin!=MCP23017_INT_ERR){ 275 | uint8_t intcapreg=regForPin(intPin,MCP23017_INTCAPA,MCP23017_INTCAPB); 276 | uint8_t bit=bitForPin(intPin); 277 | return (readRegister(intcapreg)>>bit) & (0x01); 278 | } 279 | 280 | return MCP23017_INT_ERR; 281 | } 282 | 283 | 284 | -------------------------------------------------------------------------------- /Trinamic_TMC2130_registers.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file Trinamic_TMC2130_registers.h 4 | @author Moritz Walter 5 | @license GPLv3 (see license.txt) 6 | 7 | SPI configuration tool for Trinamic TMC2130 Motor Drivers 8 | 9 | @section HISTORY 10 | 11 | v0.1 - it works 12 | */ 13 | /**************************************************************************/ 14 | #ifndef TRINAMIC_TMC2130_REGISTERS_H 15 | #define TRINAMIC_TMC2130_REGISTERS_H 16 | 17 | #if ARDUINO >= 100 18 | #include "Arduino.h" 19 | #else 20 | #include "WProgram.h" 21 | #endif 22 | 23 | #include 24 | 25 | // SPI 26 | #define TMC_SPI_CLOCK_DIVIDER SPI_CLOCK_DIV8 27 | #define TMC_SPI_DATA_MODE SPI_MODE3 28 | #define TMC_SPI_BIT_ORDER MSBFIRST 29 | 30 | // RW 31 | #define TMC_READ (0x00) 32 | #define TMC_WRITE (0x80) 33 | 34 | // SPISTATUS MASKS 35 | #define TMC_SPISTATUS_RESET_MASK (0x01) 36 | #define TMC_SPISTATUS_ERROR_MASK (0x02) 37 | #define TMC_SPISTATUS_STALLGUARD_MASK (0x04) 38 | #define TMC_SPISTATUS_STANDSTILL_MASK (0x08) 39 | 40 | // REGISTERS 41 | #define TMC_REG_GCONF (0x00) // RW // 17 // Global configuration flags 42 | #define TMC_REG_GSTAT (0x01) // RC // 3 // Global status flags 43 | #define TMC_REG_IOIN (0x04) // R // 8+8 // Reads the state of all input pins available 44 | #define TMC_REG_IHOLD_IRUN (0x10) // W // 5+5+4 // Driver current control 45 | #define TMC_REG_TPOWERDOWN (0x11) // W // 8 // sets delay time after stand still (stst) to motor current power down (0-4 seconds) 0_((2^8)-1) * 2^18 tclk 46 | #define TMC_REG_TSTEP (0x12) // R // 20 // Actual measured time between two 1/256 microsteps derived from the step input frequency in units of 1/fCLK. Measured value is (2^20)-1 in case of overflow or stand still 47 | #define TMC_REG_TPWMTHRS (0x13) // W // 20 // Upper velocity threshold for stealthChop voltage PWM mode 48 | #define TMC_REG_TCOOLTHRS (0x14) // W // 20 // Lower threshold velocity for switching on smart energy coolStep and stallGuard feature (unsigned) 49 | #define TMC_REG_THIGH (0x15) // W // 20 // Velocity dependend switching into different chopper mode and fullstepping to maximize torque (unsigned) 50 | #define TMC_REG_XDIRECT (0x2D) // RW // 32 // specifies motor coil currents and polarity directly programmed via SPI. Use signed, two's complement numbers. In this mode, the current is scaled by IHOLD. Velocity based current regulation of voltage PWM is not available in this mode. +- 255 for both coils 51 | #define TMC_REG_VDCMIN (0x33) // W // 23 // automatic commutation dcStep becomes enabled by the external signal DCEN. VDCMIN is used as the minimum step velocity when the motor is heavily loaded. Hint: Also set DCCTRL parameters in order to operate dcStep 52 | #define TMC_REG_MSLUT0 (0x60) // W // 32 // Each bit gives the difference between entry x and entry x+1 when combined with the corresponding MSLUTSEL W bits. Differential coding for the first quarter of a wave. Start values for CUR_A and CUR_B are stored for MSCNT position 0 in START_SIN and START_SIN90. 53 | #define TMC_REG_MSLUT1 (0x61) // W // 32 // 54 | #define TMC_REG_MSLUT2 (0x62) // W // 32 // 55 | #define TMC_REG_MSLUT3 (0x63) // W // 32 // 56 | #define TMC_REG_MSLUT4 (0x64) // W // 32 // 57 | #define TMC_REG_MSLUT5 (0x65) // W // 32 // 58 | #define TMC_REG_MSLUT6 (0x66) // W // 32 // 59 | #define TMC_REG_MSLUT7 (0x67) // W // 32 // 60 | #define TMC_REG_MSLUTSEL (0x68) // W // 32 // defines four segments within each quarter MSLUT wave. Four 2 bit entries determine the meaning of a 0 and a 1 bit in the corresponding segment of MSLUT 61 | #define TMC_REG_MSLUTSTART (0x69) // W // 8+8 // 62 | #define TMC_REG_MSCNT (0x6A) // R // 10 // 63 | #define TMC_REG_MSCURACT (0x6B) // R // 9+9 // 64 | #define TMC_REG_CHOPCONF (0x6C) // RW // 32 // 65 | #define TMC_REG_COOLCONF (0x6D) // W // 25 // 66 | #define TMC_REG_DCCTRL (0x6E) // W // 24 // 67 | #define TMC_REG_DRV_STATUS (0x6F) // R // 22 // 68 | #define TMC_REG_PWMCONF (0x70) // W // 8 // 69 | #define TMC_REG_PWM_SCALE (0x71) // R // 8 // 70 | #define TMC_REG_ENCM_CTRL (0x72) // W // 2 // 71 | #define TMC_REG_LOST_STEPS (0x73) // R // 20 // 72 | 73 | // GCONF OFFSETS 74 | // for shifting incoming values to the right register position 75 | #define TMC_GCONF_I_SCALE_ANALOG (0) // 0: Internal, 1: AIN 76 | #define TMC_GCONF_INTERNAL_RSENSE (1) // 0: Normal, 1: Internal 77 | #define TMC_GCONF_EN_PWM_MODE (2) // 0: Disable, 1: Enable 78 | #define TMC_GCONF_ENC_COMMUTATION (3) // 0: Disable, 1: Enable 79 | #define TMC_GCONF_SHAFT (4) // 0: Normal, 1: Invert 80 | #define TMC_GCONF_DIAG0_ERROR (5) // 0: Disable, 1: Enable 81 | #define TMC_GCONF_DIAG0_OTPW (6) // 0: Disable, 1: Enable 82 | #define TMC_GCONF_DIAG0_STALL (7) // 0: Disable, 1: Enable 83 | #define TMC_GCONF_DIAG1_STALL (8) // 0: Disable, 1: Enable 84 | #define TMC_GCONF_DIAG1_INDEX (9) // 0: Disable, 1: Enable 85 | #define TMC_GCONF_DIAG1_ONSTATE (10) // 0: Disable, 1: Enable 86 | #define TMC_GCONF_DIAG1_STEPS_SKIPPED (11) // 0: Disable, 1: Enable 87 | #define TMC_GCONF_DIAG0_INT_PUSHPULL (12) // 0: Open Collector, 1: Push Pull 88 | #define TMC_GCONF_DIAG1_INT_PUSHPULL (13) // 0: Open Collector, 1: Push Pull 89 | #define TMC_GCONF_SMALL_HYSTERESIS (14) // 0: 1/16, 1: 1/32 90 | #define TMC_GCONF_STOP_ENABLE (15) // 0: Normal, 1: Emergency Stop 91 | #define TMC_GCONF_DIRECT_MODE (16) // 0: Normal, 1: XDIRECT 92 | #define TMC_GCONF_TEST_MODE (17) // 0: Normal, 1: Enable, Don't use! 93 | 94 | // GCONF MASKS 95 | // not required, all 1 bit 96 | 97 | // IHOLD_IRUN OFFSETS 98 | // for shifting incoming values to the right register position 99 | #define TMC_IHOLD (0) 100 | #define TMC_IRUN (8) 101 | #define TMC_IHOLDDELAY (16) 102 | 103 | // IHOLD IRUN MASKS 104 | #define TMC_IHOLD_MASK (0b11111UL) 105 | #define TMC_IRUN_MASK (0b11111UL) 106 | #define TMC_IHOLDDELAY_MASK (0b1111UL) 107 | 108 | // TPOWERDOWN 109 | // no offsets required 110 | #define TMC_TPOWERDOWN_MASK (0b11111111UL) 111 | 112 | // TSTEP 113 | // no offsets required 114 | #define TMC_TSTEP_MASK (0b11111111111111111111UL) 115 | 116 | // TPWMTHRS 117 | // no offsets required 118 | #define TMC_TPWMTHRS_MASK (0b11111111111111111111UL) 119 | 120 | // TCOOLTHRS 121 | #define TMC_TCOOLTHRS_MASK (0b11111111111111111111UL) 122 | 123 | // THIGH 124 | // no offsets required 125 | #define TMC_THIGH_MASK (0b11111111111111111111UL) 126 | 127 | // XDIRECT OFFSETS 128 | // for shifting incoming values to the right register position 129 | #define TMC_XDIRECT_COIL_A (0) 130 | #define TMC_XDIRECT_COIL_B (16) 131 | 132 | // XDIRECT MASKS 133 | // mask the bits from the values we want to set 134 | #define TMC_XDIRECT_MASK (0xFFFFFFFFUL) 135 | #define TMC_XDIRECT_COIL_A_MASK (0xFFFFUL) 136 | #define TMC_XDIRECT_COIL_B_MASK (0xFFFFUL) 137 | // no offsets required 138 | // needs no mask 139 | 140 | // VDCMIN 141 | // no offsets required 142 | #define TMC_VDCMIN_MASK (0b11111111111111111111111UL) 143 | 144 | // MSLUT 145 | // no offsets required 146 | // needs no mask 147 | 148 | // MSLUTSEL 149 | // no offsets required 150 | // needs no mask 151 | 152 | // MSLUTSTART OFFSETS 153 | #define TMC_MSLUTSTART_START_SIN (0) 154 | #define TMC_MSLUTSTART_START_SIN90 (8) 155 | 156 | // MSLUTSTART MASKS 157 | #define TMC_MSLUTSTART_MASK (0xFFFFUL) 158 | #define TMC_MSLUTSTART_START_SIN_MASK (0xFF) 159 | #define TMC_MSLUTSTART_START_SIN90_MASK (0xFF) 160 | 161 | 162 | // MSCNT 163 | // no offsets required 164 | #define TMC_MSCNT_MASK (0b1111111111) 165 | 166 | // MSCURACT 167 | // no offsets required 168 | #define TMC_MSCURACT_MASK (0b111111111111111111UL) 169 | 170 | // CHOPCONF MASKS 171 | // mask the bits from the values we want to set 172 | 173 | const uint32_t TMC_CHOPCONF_MASKS[] = { 174 | 0b1111UL, // 0 TOFF 175 | 0b111UL, // 1 176 | 0b11UL, // 2 177 | 0b1UL, // 3 178 | 0b111UL, // 4 HYSTERESIS_START 179 | 0b11UL, // 5 180 | 0b1UL, // 6 181 | 0b0001UL, // 7 HYSTERESIS_LOW 182 | 0b001UL, // 8 183 | 0b01UL, // 9 184 | 0b1UL, // 10 185 | 0b1UL, // 11 FAST_DECAY_TIMING 186 | 0b1UL, // 12 FAST_DECAY_MODE 187 | 0b1UL, // 13 RANDOM_TOFF 188 | 0b1UL, // 14 CHOPPER_MODE 189 | 0b11UL, // 15 TBL 190 | 0b1UL, // 16 191 | 0b1UL, // 17 SENSE_CURRENT_SCALING 192 | 0b1UL, // 18 HIGH_VELOCITY_STEPS 193 | 0b1UL, // 19 HIGH_VELOCITY_CHOPPER 194 | 0b1111UL, // 20 SYNC_PWM 195 | 0b111UL, // 21 196 | 0b11UL, // 22 197 | 0b1UL, // 23 198 | 0b1111UL, // 24 MRES 199 | 0b111UL, // 25 200 | 0b11UL, // 26 201 | 0b1UL, // 27 202 | 0b1UL, // 28 INTERPOLATE 203 | 0b1UL, // 29 DOUBLE_EDGE_PULSES 204 | 0b1UL, // 30 SHORT_PROTECTION 205 | 0b1UL // 31 206 | }; 207 | 208 | // CHOPCONF OFFSETS 209 | // for shifting incoming values to the right register position 210 | #define TMC_CHOPCONF_DISS2G (30) 211 | #define TMC_CHOPCONF_DEDGE (29) 212 | #define TMC_CHOPCONF_INTPOL (28) 213 | #define TMC_CHOPCONF_MRES (24) 214 | #define TMC_CHOPCONF_SYNC (20) 215 | #define TMC_CHOPCONF_VHIGHCHM (19) 216 | #define TMC_CHOPCONF_VHIGHFS (18) 217 | #define TMC_CHOPCONF_VSENSE (17) 218 | #define TMC_CHOPCONF_TBL (15) 219 | #define TMC_CHOPCONF_CHM (14) 220 | #define TMC_CHOPCONF_RNDTF (13) 221 | #define TMC_CHOPCONF_DISFDCC (12) 222 | #define TMC_CHOPCONF_FD (11) 223 | #define TMC_CHOPCONF_HEND (7) 224 | #define TMC_CHOPCONF_HSTRT (4) 225 | #define TMC_CHOPCONF_TOFF (0) 226 | 227 | // COOLCONF BIT OFFSETS 228 | // for shifting incoming values to the right register position 229 | #define TMC_COOLCONF_SFILT (24) 230 | #define TMC_COOLCONF_SGT (16) 231 | #define TMC_COOLCONF_SEIMIN (15) 232 | #define TMC_COOLCONF_SEDN (13) 233 | #define TMC_COOLCONF_SEMAX (8) 234 | #define TMC_COOLCONF_SEUP (5) 235 | #define TMC_COOLCONF_SEMIN (0) 236 | 237 | // COOLCONF MASKS 238 | // mask the bits from the values we want to set 239 | const int TMC_COOLCONF_MASKS[] = { 240 | 0b1111UL, // 0 TMC_COOLCONF_SEMIN 241 | 0b111UL, // 1 242 | 0b11UL, // 2 243 | 0b1UL, // 3 244 | 0b0UL, // 4 245 | 0b11UL, // 5 TMC_COOLCONF_SEUP 246 | 0b1UL, // 6 247 | 0b0UL, // 7 248 | 0b1111UL, // 8 TMC_COOLCONF_SEMAX 249 | 0b111UL, // 9 250 | 0b11UL, // 10 251 | 0b1UL, // 11 252 | 0b0UL, // 12 253 | 0b11UL, // 13 TMC_COOLCONF_SEDN 254 | 0b1UL, // 14 255 | 0b1UL, // 15 TMC_COOLCONF_SEIMIN 256 | 0b1111111UL, // 16 TMC_COOLCONF_SGT 257 | 0b111111UL, // 17 258 | 0b11111UL, // 18 259 | 0b1111UL, // 19 260 | 0b111UL, // 20 261 | 0b11UL, // 21 262 | 0b1UL, // 22 263 | 0b0UL, // 23 264 | 0b1UL, // 24 TMC_COOLCONF_SFILT 265 | }; 266 | 267 | // DCCTRL OFFSETS 268 | // for shifting incoming values to the right register position 269 | #define TMC_DCCTRL_DC_TIME (0) 270 | #define TMC_DCCTRL_DC_SG (16) 271 | 272 | // DCCTRL MASKS 273 | // mask the bits from the values we want to set 274 | #define TMC_DCCTRL_MASK (0b1111111111UL) 275 | #define TMC_DCCTRL_DC_TIME_MASK (0b11111111UL) 276 | #define TMC_DCCTRL_DC_SG_MASK (0b111111110000001111111111UL) 277 | 278 | 279 | // PWMCONF OFFSETS 280 | // for shifting incoming values to the right register position 281 | #define TMC_PWMCONF_FREEWHEEL (20) 282 | #define TMC_PWMCONF_PWM_SYMMETRIC (19) 283 | #define TMC_PWMCONF_PWM_AUTOSCALE (18) 284 | #define TMC_PWMCONF_PWM_FREQ (16) 285 | #define TMC_PWMCONF_PWM_GRAD (8) 286 | #define TMC_PWMCONF_PWM_AMPL (0) 287 | 288 | // PWMCONF MASKS 289 | // mask the bits from the values we want to set 290 | const int TMC_PWMCONF_MASKS[] = { 291 | 0b11111111UL, // 0 TMC_PWMCONF_PWM_AMPL 292 | 0b1111111UL, // 1 293 | 0b111111UL, // 2 294 | 0b11111UL, // 3 295 | 0b1111UL, // 4 296 | 0b111UL, // 5 297 | 0b11UL, // 6 298 | 0b1UL, // 7 299 | 0b11111111UL, // 8 TMC_PWMCONF_PWM_GRAD 300 | 0b1111111UL, // 9 301 | 0b111111UL, // 10 302 | 0b11111UL, // 11 303 | 0b1111UL, // 12 304 | 0b111UL, // 13 305 | 0b11UL, // 14 306 | 0b1UL, // 15 307 | 0b11UL, // 16 TMC_PWMCONF_PWM_FREQ 308 | 0b1UL, // 17 309 | 0b1UL, // 18 TMC_PWMCONF_PWM_AUTOSCALE 310 | 0b1UL, // 19 TMC_PWMCONF_PWM_SYMMETRIC 311 | 0b11UL, // 20 TMC_PWMCONF_FREEWHEEL 312 | 0b1UL, // 21 313 | }; 314 | 315 | // ENCM_CTRL MASK 316 | // mask the bits from the values we want to set 317 | #define TMC_ENCM_CTRL_MASK (0b11); 318 | 319 | #endif // TRINAMIC_TMC2130_REGISTERS_H 320 | -------------------------------------------------------------------------------- /Trinamic_TMC2130.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file Trinamic_TMC2130.cpp 4 | @author Moritz Walter 5 | @license GPLv3 (see license.txt) 6 | 7 | SPI configuration tool for Trinamic TMC2130 Motor Drivers 8 | 9 | @section HISTORY 10 | 11 | v0.1 - it works 12 | */ 13 | /**************************************************************************/ 14 | #if ARDUINO >= 100 15 | #include "Arduino.h" 16 | #else 17 | #include "WProgram.h" 18 | #endif 19 | 20 | #include 21 | 22 | #include "Trinamic_TMC2130.h" 23 | #include "Trinamic_TMC2130_registers.h" 24 | 25 | Trinamic_TMC2130::Trinamic_TMC2130(uint8_t csPin) 26 | { 27 | _csPin=csPin; 28 | _status=0; 29 | _debug=""; 30 | } 31 | 32 | // initialize the driver with its CS/SS pin 33 | void Trinamic_TMC2130::init() { 34 | pinMode(_csPin, OUTPUT); 35 | digitalWrite(_csPin, HIGH); 36 | init_SPI(); 37 | read_STAT(); 38 | } 39 | 40 | // initialize SPI 41 | void Trinamic_TMC2130::init_SPI() { 42 | SPI.setDataMode(TMC_SPI_DATA_MODE); 43 | SPI.setBitOrder(TMC_SPI_BIT_ORDER); 44 | SPI.setClockDivider(TMC_SPI_CLOCK_DIVIDER); 45 | SPI.begin(); 46 | } 47 | 48 | // read status 49 | uint8_t Trinamic_TMC2130::read_STAT() 50 | { 51 | init_SPI(); 52 | digitalWrite(_csPin, LOW); 53 | 54 | // read address 55 | _status = SPI.transfer(0x00); 56 | 57 | // flush 4 bytes 58 | for(int i=0;i<4;i++){ 59 | SPI.transfer(0x00); 60 | } 61 | 62 | digitalWrite(_csPin, HIGH); 63 | 64 | return _status; 65 | } 66 | 67 | // read a register 68 | uint8_t Trinamic_TMC2130::read_REG(uint8_t address, uint32_t *data) 69 | { 70 | init_SPI(); 71 | digitalWrite(_csPin, LOW); 72 | 73 | // read address 74 | _status = SPI.transfer(address&~TMC_WRITE); 75 | 76 | // flush 4 bytes 77 | for(int i=0;i<4;i++){ 78 | SPI.transfer(0x00); 79 | } 80 | 81 | digitalWrite(_csPin, HIGH); 82 | // restart transmission 83 | digitalWrite(_csPin, LOW); 84 | 85 | // read address 86 | _status = SPI.transfer(address&~TMC_WRITE); 87 | 88 | // retrieve data 89 | *data = SPI.transfer(0x00)&0xFF; 90 | *data <<=8; 91 | *data |= SPI.transfer(0x00)&0xFF; 92 | *data <<=8; 93 | *data |= SPI.transfer(0x00)&0xFF; 94 | *data <<=8; 95 | *data |= SPI.transfer(0x00)&0xFF; 96 | 97 | digitalWrite(_csPin, HIGH); 98 | 99 | return _status; 100 | } 101 | 102 | // write to a register 103 | uint8_t Trinamic_TMC2130::write_REG(uint8_t address, uint32_t data) 104 | { 105 | digitalWrite(_csPin, LOW); 106 | 107 | // write address 108 | _status = SPI.transfer(address|TMC_WRITE); 109 | 110 | // write data 111 | SPI.transfer((data>>24UL)&0xFF); 112 | SPI.transfer((data>>16UL)&0xFF); 113 | SPI.transfer((data>> 8UL)&0xFF); 114 | SPI.transfer((data>> 0UL)&0xFF); 115 | 116 | digitalWrite(_csPin, HIGH); 117 | 118 | return _status; 119 | } 120 | 121 | // alter a register using a bitmask 122 | uint8_t Trinamic_TMC2130::alter_REG(uint8_t address, uint32_t data, uint32_t mask) 123 | { 124 | uint32_t oldData, newData; 125 | 126 | read_REG( address, &oldData ); 127 | 128 | newData = ( oldData&~mask ) | ( data&mask ); 129 | 130 | write_REG( address, newData ); 131 | 132 | return _status; 133 | } 134 | 135 | // set single bits in the GCONF register 136 | uint8_t Trinamic_TMC2130::set_GCONF(uint8_t position, uint8_t value) 137 | { 138 | alter_REG(TMC_REG_GCONF, uint32_t(value)<. 22 | 23 | Credit Trinamic_TMC2130.h driver 24 | @author Moritz Walter 25 | https://github.com/makertum/Trinamic_TMC2130 26 | 27 | Features: 28 | --------- 29 | - control stepper Nema 17 by received frequency from Icom CI-V protocol 30 | - support endstop for adjusting after start up 31 | - without endstop available save lat position to eeprom (not recomended) 32 | - configure via serial USB Command Line Interface (CLI) 33 | - TX inhibit output during stepper operate 34 | - up to 112 frequency memory 35 | - up to 16 stepper counter memory for each frequency, selected by BCD inputs 36 | - linear iterpolation on/off adjustable in CLI 37 | - reverse on/off adjustable in CLI 38 | - running/tuning mode in CLI 39 | - tuning wizard for save to eeprom memory in CLI 40 | 41 | Changelog: 42 | ---------- 43 | 2020-01 CLI enter, uSteps settings 44 | 2019-05 first initial version 45 | 46 | // Stepper //////////////////////////////////////////*/ 47 | #define RestoreMemoryFromEeprom // enable load freq table from EEPROM during reboot 48 | // if disable, store table to eeprom with [s] command for every bank separately, and enable again 49 | const int StepsByTurn = 200; // dependancy to using stepper motor 50 | int MicroSteps; // [1,2,4,8,16,32,64,128,256] number of microstep 51 | int CurrentRun; // [0-31] current using during running stepper motor 52 | int CurrentStandby = 0; // [0-31] current using during stepper motor standby 53 | long CurrentRunTimeout[2] = {0,1000}; // Time, after them current switch to standby value 54 | bool EnableStepperStandby = false; // disable stepper (off) in standby - ONLY if MicroSteps = 1 55 | bool EnableSlowStartStop = false; 56 | bool Reverse; 57 | bool TuningMode = 0; 58 | byte BankOfMemory; 59 | byte BankOfMemoryPrev; 60 | const int BcdPin[4] = {9, 11, 5, A1}; // BCD encoder PINs 61 | long BcdRefresh[2] = {0,500}; 62 | int NumberOfMemory; 63 | int NumberOfBank; 64 | bool EnableEndstop; 65 | bool LastPositionSave = true; 66 | bool LinearInterpolation; 67 | 68 | // Misc /////////////////////////////////////////// 69 | #define CLI // Command Line Interface 70 | // #define SERIAL_debug 71 | int DebugLevel = 0; 72 | bool SerialNeedStatus = false; 73 | 74 | // Icom CI-V /////////////////////////////////////////// 75 | #define ICOM_CIV // read frequency from CIV 76 | #if defined(ICOM_CIV) 77 | byte CIV_ADRESS; // CIV input HEX Icom adress (0x is prefix) 78 | #define REQUEST 500 // [ms] use TXD output for sending frequency request 79 | long BAUDRATE1; // [baud] Serial port in/out baudrate 80 | #endif 81 | 82 | // Ethernet /////////////////////////////////////////// 83 | // #define EthModule // enable Ethernet module if installed 84 | #define __USE_DHCP__ // enable DHCP 85 | #define HW_BCD_SW // Enable hardware NET-ID bcd switch on bottom side 86 | 87 | // Hardware /////////////////////////////////////////// 88 | #define ENCODER // select 89 | #define BUTTON // SHORT auto/select-memory/select-step 90 | // LONG /clear-memory /save-step and goto select-memory 91 | 92 | // #define LCD // Uncoment to Enable I2C LCD 93 | #if defined(LCD) 94 | const byte LcdI2Caddress = 0x27; // 0x27 0x3F - may be find with I2C scanner https://playground.arduino.cc/Main/I2cScanner 95 | #define LCD_PCF8574 // If LCD uses PCF8574 chip 96 | //#define LCD_PCF8574T // If LCD uses PCF8574T chip 97 | //#define LCD_PCF8574AT // If LCD uses PCF8574AT chip 98 | #endif 99 | 100 | const char* REV = "20200127"; 101 | 102 | #include "Trinamic_TMC2130.h" 103 | const int StepPin = 8; 104 | const int CS_PIN = 6; 105 | const int DIR_PIN = 4; 106 | const int EN_PIN = 12; 107 | // bool CurrentStatus = false; 108 | Trinamic_TMC2130 myStepper(CS_PIN); 109 | const int Stepper_us = 200; // one step in us (SPEED) 110 | int StepCounter; 111 | 112 | const int EndStopPin = 7; 113 | const int TxInhibitPin = 13; 114 | 115 | // Serial 116 | const int BAUDRATE0 = 115200; // USB CLI/Debug 117 | bool WizardEnable = false; 118 | int WizardStep = 0; 119 | 120 | #if defined(LCD) 121 | #if defined(LCD_PCF8574T) || defined(LCD_PCF8574) 122 | #include 123 | LiquidCrystal_PCF8574 lcd(LcdI2Caddress); 124 | #endif 125 | #if defined(LCD_PCF8574AT) 126 | #include 127 | LiquidCrystal_I2C lcd(LcdI2Caddress,16,2); 128 | #endif 129 | 130 | long LcdRefresh[2]{0,500}; 131 | // byte LockChar[8] = {0b00100, 0b01010, 0b01010, 0b11111, 0b11011, 0b11011, 0b11111, 0b00000}; 132 | uint8_t LockChar[8] = {0x4,0xa,0xa,0x1f,0x1b,0x1b,0x1f,0x0}; 133 | uint8_t EthChar[8] = {0x0,0x0,0x1f,0x11,0x11,0x1b,0x1f,0x0}; 134 | bool LcdNeedRefresh = false; 135 | #endif 136 | 137 | // Steppers 138 | unsigned int Multiplier = 1; 139 | int uSeconds; 140 | volatile long SteppersCounter = 0; 141 | volatile long SteppersCounterTarget = 0; 142 | long SteppersCounterLimit; 143 | volatile int InDeCrement; 144 | 145 | unsigned long StorageFreqToStep[112][2] = { //0 - 4 294 967 295 146 | // {freq Hz, uStep} 147 | // 0 148 | {7000000, 0}, 149 | {7010000, 500}, 150 | {7020000, 1000}, 151 | {7030000, 1500}, 152 | {7040000, 2000}, 153 | {7050000, 2500}, 154 | {7060000, 3000}, 155 | {7070000, 3500}, 156 | {7080000, 4000}, 157 | {7090000, 4500}, 158 | // 10 159 | {1830000, 5000}, 160 | {1831000, 5500}, 161 | {1832000, 6000}, 162 | {1833000, 6500}, 163 | {1834000, 7000}, 164 | {1835000, 7500}, 165 | {1836000, 8000}, 166 | {1837000, 8500}, 167 | {1838000, 9000}, 168 | {1839000, 9500}, 169 | // 20 170 | {0, 0}, 171 | {0, 0}, 172 | {0, 0}, 173 | {0, 0}, 174 | {0, 0}, 175 | {0, 0}, 176 | {0, 0}, 177 | {0, 0}, 178 | {0, 0}, 179 | {0, 0}, 180 | // 30 181 | {0, 0}, 182 | {0, 0}, 183 | {0, 0}, 184 | {0, 0}, 185 | {0, 0}, 186 | {0, 0}, 187 | {0, 0}, 188 | {0, 0}, 189 | {0, 0}, 190 | {0, 0}, 191 | // 40 192 | {0, 0}, 193 | {0, 0}, 194 | {0, 0}, 195 | {0, 0}, 196 | {0, 0}, 197 | {0, 0}, 198 | {0, 0}, 199 | {0, 0}, 200 | {0, 0}, 201 | {0, 0}, 202 | // 50 203 | {0, 0}, 204 | {0, 0}, 205 | {0, 0}, 206 | {0, 0}, 207 | {0, 0}, 208 | {0, 0}, 209 | {0, 0}, 210 | {0, 0}, 211 | {0, 0}, 212 | {0, 0}, 213 | // 60 214 | {0, 0}, 215 | {0, 0}, 216 | {0, 0}, 217 | {0, 0}, 218 | {0, 0}, 219 | {0, 0}, 220 | {0, 0}, 221 | {0, 0}, 222 | {0, 0}, 223 | {0, 0}, 224 | // 70 225 | {0, 0}, 226 | {0, 0}, 227 | {0, 0}, 228 | {0, 0}, 229 | {0, 0}, 230 | {0, 0}, 231 | {0, 0}, 232 | {0, 0}, 233 | {0, 0}, 234 | {0, 0}, 235 | // 80 236 | {0, 0}, 237 | {0, 0}, 238 | {0, 0}, 239 | {0, 0}, 240 | {0, 0}, 241 | {0, 0}, 242 | {0, 0}, 243 | {0, 0}, 244 | {0, 0}, 245 | {0, 0}, 246 | // 90 247 | {0, 0}, 248 | {0, 0}, 249 | {0, 0}, 250 | {0, 0}, 251 | {0, 0}, 252 | {0, 0}, 253 | {0, 0}, 254 | {0, 0}, 255 | {0, 0}, 256 | {0, 0}, 257 | // 100 258 | {0, 0}, 259 | {0, 0}, 260 | {0, 0}, 261 | {0, 0}, 262 | {0, 0}, 263 | {0, 0}, 264 | {0, 0}, 265 | {0, 0}, 266 | {0, 0}, 267 | {0, 0}, 268 | // 110 269 | {0, 0}, 270 | {0, 0}, 271 | // 112 272 | }; 273 | 274 | #if defined(ICOM_CIV) 275 | long RequestTimeout[2]={0, 276 | #if defined(REQUEST) 277 | REQUEST 278 | #else 279 | 0 280 | #endif 281 | }; 282 | int fromAdress = 0xE0; // 0E 283 | byte rdI[10]; // read data icom 284 | String rdIS; // read data icom string 285 | int state = 1; // state machine 286 | bool StateMachineEnd = false; 287 | #endif 288 | 289 | unsigned long freq = 0; 290 | unsigned long freqPrev; 291 | byte InputByte[21]; 292 | byte incomingByte = 0; 293 | byte incomingByte1 = 0; 294 | 295 | #if defined(EthModule) 296 | const byte RemoteDevice = 'g'; 297 | const byte ThisDevice = 'p'; 298 | bool EthLinkStatus = 0; 299 | long EthLinkStatusTimer[2]={1500,1000}; 300 | byte NET_ID = 0x00; // NetID [hex] MUST BE UNIQUE IN NETWORK - replace by P6 board encoder 301 | bool EnableEthernet = 1; 302 | bool EnableDHCP = 1; 303 | #include 304 | #include 305 | // #include 306 | // #include 307 | // #include 308 | // #include 309 | // #include 310 | #include 311 | byte LastMac = 0x00 + NET_ID; 312 | 313 | byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0x22, LastMac}; 314 | // byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, LastMac}; 315 | // IPAddress ip(192, 168, 1, 222); // IP 316 | // IPAddress gateway(192, 168, 1, 200); // GATE 317 | // IPAddress subnet(255, 255, 255, 0); // MASK 318 | // IPAddress myDns(8, 8, 8, 8); // DNS (google pub) 319 | // EthernetServer server(80); // Web server PORT 320 | // String HTTP_req; 321 | 322 | unsigned int UdpCommandPort = 88; // local UDP port listen to command 323 | #define UDP_TX_PACKET_MAX_SIZE 40 // MIN 30 324 | unsigned char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; //buffer to hold incoming packet, 325 | // unsigned char packetBuffer[12]; //buffer to hold incoming packet, 326 | int UDPpacketSize; 327 | EthernetUDP UdpCommand; // An EthernetUDP instance to let us send and receive packets over UDP 328 | IPAddress BroadcastIP(0, 0, 0, 0); // Broadcast IP address 329 | int BroadcastPort = 88; // destination broadcast packet port 330 | // IPAddress RemoteSwIP(0, 0, 0, 0); // remote UDP IP switch - set from UDP DetectRemote array 331 | // int RemoteSwPort = 0; // remote UDP IP switch port 332 | // int BandDecoderChange = 0; // If band change, send query packet to Remote IP switch 333 | long RemoteSwLatency[2]; // start, stop mark 334 | byte RemoteSwLatencyAnsw = 0; // answer (offline) detect 335 | byte TxUdpBuffer[8]; 336 | long IpTimeout[1][2] = {0, 60000}; // UDP Broadcast packet [8][0-timer/1-timeout] 337 | #endif 338 | 339 | #include 340 | 341 | //------------------------------------------------------------------------------------ 342 | 343 | void setup(){ 344 | pinMode(StepPin, OUTPUT); 345 | digitalWrite(StepPin, LOW); // no step yet 346 | pinMode(CS_PIN, OUTPUT); 347 | pinMode(DIR_PIN, OUTPUT); 348 | digitalWrite(DIR_PIN, LOW); 349 | pinMode(EN_PIN, OUTPUT); 350 | pinMode(EndStopPin, INPUT_PULLUP); 351 | pinMode(TxInhibitPin, OUTPUT); 352 | digitalWrite(TxInhibitPin, LOW); 353 | for (int i = 0; i < 4; i++) { 354 | pinMode(BcdPin[i], INPUT); 355 | } 356 | 357 | Serial.begin(BAUDRATE0, SERIAL_8N2); 358 | 359 | // EEPROM 0-99 byte free, 100-1000 freq/ustep array 360 | #if defined(EthModule) 361 | NET_ID=EEPROM.read(1); // address, value 362 | LastMac = 0x00 + NET_ID; 363 | mac[5] = LastMac; 364 | EthernetCheck(); 365 | #endif 366 | Reverse = EEPROM.read(2); 367 | BankOfMemory = EEPROM.read(3); 368 | if(BankOfMemory>15){ 369 | BankOfMemory=0; 370 | } 371 | BankOfMemoryPrev=BankOfMemory; 372 | SteppersCounterLimit=EEPROMReadlong(4); 373 | 374 | NumberOfMemory=EEPROM.read(8); 375 | if(NumberOfMemory>112){ 376 | NumberOfMemory=112; 377 | } 378 | NumberOfBank=224/(NumberOfMemory+1); 379 | if(NumberOfBank>16){ 380 | NumberOfBank=16; 381 | } 382 | 383 | EnableEndstop=EEPROM.read(9); 384 | if(EnableEndstop>1){ 385 | EnableEndstop=false; 386 | } 387 | if(EnableEndstop==true){ 388 | SteppersCounter = SteppersCounterLimit; 389 | SteppersCounterTarget = 0; 390 | } 391 | 392 | if(EnableEndstop==false){ 393 | SteppersCounter=EEPROMReadlong(10); 394 | SteppersCounterTarget = SteppersCounter; 395 | } 396 | 397 | 398 | #if defined(ICOM_CIV) 399 | CIV_ADRESS=EEPROM.read(14); 400 | #endif 401 | 402 | #if defined(ICOM_CIV) 403 | BAUDRATE1=EEPROMReadlong(15); 404 | if(BAUDRATE1<80 || BAUDRATE1>115200){ 405 | BAUDRATE1=9600; 406 | } 407 | Serial1.begin(BAUDRATE1, SERIAL_8N2); 408 | #endif 409 | 410 | MicroSteps=EEPROM.read(19); 411 | if(MicroSteps<0 || MicroSteps>7){ 412 | MicroSteps=16; 413 | } 414 | 415 | CurrentRun=EEPROM.read(20); 416 | if(CurrentRun<0 || CurrentRun>31){ 417 | CurrentRun=10; 418 | } 419 | 420 | // stepper 1 421 | myStepper.init(); 422 | myStepper.set_mres(MicroSteps); // ({1,2,4,8,16,32,64,128,256}) number of microsteps 423 | myStepper.set_IHOLD_IRUN(0,0,0); // ([0-31],[0-31],[0-5]) sets all currents to maximum 424 | myStepper.set_I_scale_analog(1); // ({0,1}) 0: I_REF internal, 1: sets I_REF to AIN 425 | myStepper.set_tbl(1); // ([0-3]) set comparator blank time to 16, 24, 36 or 54 clocks, 1 or 2 is recommended 426 | myStepper.set_toff(8); // ([0-15]) 0: driver disable, 1: use only with TBL>2, 2-15: off time setting during slow decay phase 427 | myStepper.set_en_pwm_mode(1); // StealtChop mode 1-ON 0-OFF 428 | uStepTouSeconds(); 429 | if(MicroSteps>1){ 430 | EnableStepperStandby = true; 431 | } 432 | if(EnableStepperStandby==true){ 433 | digitalWrite(EN_PIN, LOW); // LOW = enable 434 | }else{ 435 | digitalWrite(EN_PIN, HIGH); // HIGH = disable 436 | } 437 | 438 | LinearInterpolation=EEPROM.read(21); 439 | 440 | // for (int x=0; x<224; x++) { 441 | // EEPROMWritelong( x*4+100, x); 442 | // } 443 | // set array from eeprom 444 | #if defined(RestoreMemoryFromEeprom) 445 | for (int x=0; x 0) { 509 | incomingByte = Serial.read(); 510 | 511 | // w 512 | if(incomingByte==119 && TuningMode==1){ 513 | WizardEnable=true; 514 | Serial.println(); 515 | Serial.print(F("Wizard started...")); 516 | if(BankOfMemory==0){ 517 | Serial.print(F(" WARNING - Bank-0 overwrite frequency (/ for escape tuning mode)")); 518 | } 519 | Serial.println(); 520 | 521 | #if defined(SERIAL_debug) 522 | // * 523 | }else if(incomingByte==42){ 524 | Serial.println(F("Press Debug level 0-2...")); 525 | Serial.print(F("> ")); 526 | while (Serial.available() == 0) { 527 | // Wait 528 | } 529 | Serial.println(); 530 | incomingByte = Serial.read(); 531 | if( incomingByte>=48 && incomingByte<=50 ){ 532 | DebugLevel=incomingByte-48; 533 | Serial.print(F("** Serial DEBUG level ")); 534 | Serial.print(DebugLevel); 535 | Serial.println(F(" **")); 536 | }else{ 537 | Serial.print(F(" [")); 538 | Serial.write(incomingByte); //, DEC); 539 | Serial.println(F("] unknown command - for more info press '?'")); 540 | } 541 | #endif 542 | 543 | // r 544 | }else if(incomingByte==114){ 545 | Reverse= !Reverse; 546 | EEPROM.write(2, Reverse); // address, value 547 | Serial.print(F(" ** Reverse ")); 548 | if(Reverse==0){ 549 | Serial.println(F("[OFF] **")); 550 | }else if(Reverse==1){ 551 | Serial.println(F("[ON]**")); 552 | } 553 | 554 | // + 555 | }else if(incomingByte==43){ 556 | EnableEndstop= !EnableEndstop; 557 | EEPROM.write(9, EnableEndstop); // address, value 558 | Serial.print(F(" ** Enable ")); 559 | if(EnableEndstop==true){ 560 | Serial.println(F("[Endstop] **")); 561 | }else if(EnableEndstop==false){ 562 | Serial.println(F("[Last position save to eeprom] **")); 563 | EEPROMWritelong(10, SteppersCounter); 564 | } 565 | 566 | // i 567 | }else if(incomingByte==105){ 568 | LinearInterpolation=!LinearInterpolation; 569 | Serial.print(F(" ** Linear Interpolation ")); 570 | if(LinearInterpolation==false){ 571 | Serial.println(F("[OFF] **")); 572 | }else if(LinearInterpolation==true){ 573 | Serial.println(F("[ON]**")); 574 | } 575 | EEPROM.write(21, LinearInterpolation); 576 | 577 | // / 578 | }else if(incomingByte==47){ 579 | TuningMode=!TuningMode; 580 | Serial.print(F(" ** Tuning mode ")); 581 | if(TuningMode==0){ 582 | Serial.println(F("[OFF] **")); 583 | WizardEnable=false; 584 | WizardStep=0; 585 | }else if(TuningMode==1){ 586 | Serial.println(F("[ON]**")); 587 | } 588 | 589 | // u 590 | }else if(incomingByte==117 && TuningMode==1){ 591 | Serial.print(F("Save actual u step counter = ")); 592 | Serial.print(SteppersCounter); 593 | Serial.print(F(" = ")); 594 | float GRAD = 360/(float(StepsByTurn)*float(MicroSteps))*float(SteppersCounter); 595 | Serial.print(GRAD); 596 | Serial.println(F("° as upper limit?")); 597 | Serial.print(F("> [y/n] or [r] for reset to upper limit ")); 598 | while (Serial.available() == 0) { 599 | // Wait 600 | } 601 | incomingByte = Serial.read(); 602 | if(incomingByte==121){ 603 | SteppersCounterLimit=SteppersCounter; 604 | EEPROMWritelong(4, SteppersCounterLimit); 605 | Serial.println(F("Save")); 606 | }else if(incomingByte==114){ 607 | SteppersCounterLimit=2147483647L; 608 | EEPROMWritelong(4, SteppersCounterLimit); 609 | Serial.println(F("Reset")); 610 | }else{ 611 | Serial.println(F("Discard")); 612 | } 613 | 614 | // 4 <- CCW 615 | }else if(incomingByte==52 && TuningMode==1){ 616 | if( (SteppersCounterTarget-(MicroSteps*Multiplier))>=0 ){ 617 | SteppersCounterTarget=SteppersCounterTarget-(MicroSteps*Multiplier); 618 | Serial.print(F("<")); 619 | // Serial.println(SteppersCounterTarget); 620 | #if defined(LCD) 621 | LcdNeedRefresh = true; 622 | #endif 623 | SerialNeedStatus = true; 624 | } 625 | 626 | // 6 -> CW 627 | }else if(incomingByte==54 && TuningMode==1){ 628 | SteppersCounterTarget=SteppersCounterTarget+(MicroSteps*Multiplier); 629 | Serial.print(F(">")); 630 | // Serial.println(SteppersCounterTarget); 631 | #if defined(LCD) 632 | LcdNeedRefresh = true; 633 | #endif 634 | SerialNeedStatus = true; 635 | 636 | // 8 up 637 | }else if(incomingByte==56 && TuningMode==1){ 638 | if(Multiplier<1000){ 639 | Multiplier=Multiplier*10; 640 | Serial.print(F("Multiplier up to ")); 641 | Serial.print(Multiplier); 642 | Serial.println(F("x")); 643 | } 644 | // 2 dwn 645 | }else if(incomingByte==50 && TuningMode==1){ 646 | if(Multiplier>=10){ 647 | Multiplier=Multiplier/10; 648 | Serial.print(F("Multiplier dwn to ")); 649 | Serial.print(Multiplier); 650 | Serial.println(F("x")); 651 | } 652 | 653 | // ? 654 | }else if(incomingByte==63){ 655 | ListCommands(); 656 | 657 | // c 658 | }else if(incomingByte==99){ 659 | Serial.println(F("Press CI-V address in hex (two chars 0-f)")); 660 | Serial.print(F("> ")); 661 | while (Serial.available() == 0) { 662 | // Wait 663 | } 664 | incomingByte = Serial.read(); 665 | Serial.write(incomingByte); 666 | if( (incomingByte>=48 && incomingByte<=57) || (incomingByte>=97 && incomingByte<=102) ){ 667 | if(incomingByte>=48 && incomingByte<=57){ 668 | incomingByte = incomingByte-48; 669 | }else{ 670 | incomingByte = incomingByte-87; 671 | } 672 | CIV_ADRESS = incomingByte; 673 | CIV_ADRESS = CIV_ADRESS<<4; 674 | while (Serial.available() == 0) { 675 | // Wait 676 | } 677 | incomingByte = Serial.read(); 678 | Serial.write(incomingByte); 679 | if( (incomingByte>=48 && incomingByte<=57) || (incomingByte>=97 && incomingByte<=102) ){ 680 | if(incomingByte>=48 && incomingByte<=57){ 681 | incomingByte = incomingByte-48; 682 | }else{ 683 | incomingByte = incomingByte-87; 684 | } 685 | CIV_ADRESS = CIV_ADRESS | incomingByte; 686 | EEPROM.write(14, CIV_ADRESS); 687 | Serial.println(); 688 | 689 | Serial.println(F("Baudrate and [enter]")); 690 | // Serial.print(F("> ")); 691 | // while(!Serial.available()){ 692 | // } 693 | // delay(2000); 694 | // long CompareInt = Serial.parseInt(); 695 | Enter(); 696 | int intBuf=0; 697 | int mult=1; 698 | for (int j=InputByte[0]; j>0; j--){ 699 | intBuf = intBuf + ((InputByte[j]-48)*mult); 700 | mult = mult*10; 701 | } 702 | if(intBuf>=80 && intBuf<=115200){ 703 | BAUDRATE1 = intBuf; 704 | EEPROMWritelong(15, BAUDRATE1); 705 | Serial.println(F(" write to EEPROM")); 706 | // Serial.println(BAUDRATE1); 707 | Serial1.begin(BAUDRATE1, SERIAL_8N2); 708 | // Serial.print("** device will be restarted **"); 709 | delay(500); 710 | }else{ 711 | Serial.println(F("Out of range.")); 712 | } 713 | }else{ 714 | Serial.println(F(" accepts 0-f, exit")); 715 | } 716 | }else{ 717 | Serial.println(F(" accepts 0-f, exit")); 718 | } 719 | 720 | // @ 721 | }else if(incomingByte==64){ 722 | Serial.println(F("Press micro steps 0-8 (default 4) and [enter], respond 1 2 4 8 16 32 64 128 256 uStep")); 723 | // Serial.print(F("> ")); 724 | // while (Serial.available() == 0) { 725 | // // Wait 726 | // } 727 | // incomingByte = Serial.read(); 728 | Enter(); 729 | int intBuf=0; 730 | int mult=1; 731 | for (int j=InputByte[0]; j>0; j--){ 732 | intBuf = intBuf + ((InputByte[j]-48)*mult); 733 | mult = mult*10; 734 | } 735 | if( (intBuf <= 8) ){ 736 | MicroSteps=0x00; 737 | MicroSteps = MicroSteps | (1< ")); 744 | // while(!Serial.available()){ 745 | // } 746 | // delay(2000); 747 | // long CompareInt = Serial.parseInt(); 748 | Enter(); 749 | int intBuf=0; 750 | int mult=1; 751 | for (int j=InputByte[0]; j>0; j--){ 752 | intBuf = intBuf + ((InputByte[j]-48)*mult); 753 | mult = mult*10; 754 | } 755 | if(intBuf>=0 && intBuf<=31){ 756 | CurrentRun = intBuf; 757 | EEPROMWritelong(20, CurrentRun); 758 | Serial.println(CurrentRun); 759 | // stepper 1 760 | myStepper.init(); 761 | myStepper.set_mres(MicroSteps); // ({1,2,4,8,16,32,64,128,256}) number of microsteps 762 | myStepper.set_IHOLD_IRUN(0,0,0); // ([0-31],[0-31],[0-5]) sets all currents to maximum 763 | myStepper.set_I_scale_analog(1); // ({0,1}) 0: I_REF internal, 1: sets I_REF to AIN 764 | myStepper.set_tbl(1); // ([0-3]) set comparator blank time to 16, 24, 36 or 54 clocks, 1 or 2 is recommended 765 | myStepper.set_toff(8); // ([0-15]) 0: driver disable, 1: use only with TBL>2, 2-15: off time setting during slow decay phase 766 | myStepper.set_en_pwm_mode(1); // StealtChop mode 1-ON 0-OFF 767 | uStepTouSeconds(); 768 | }else{ 769 | Serial.println(F(" accepts 0-31, exit")); 770 | } 771 | }else{ 772 | Serial.println(F(" accepts 0-8, exit")); 773 | } 774 | 775 | // # 776 | #if defined(EthModule) 777 | }else if(incomingByte==35){ 778 | Serial.println(F("Press NET-ID X_ prefix 0-f...")); 779 | Serial.print(F("> ")); 780 | while (Serial.available() == 0) { 781 | // Wait 782 | } 783 | incomingByte = Serial.read(); 784 | if( (incomingByte>=48 && incomingByte<=57) || (incomingByte>=97 && incomingByte<=102) ){ 785 | bitClear(NET_ID, 4); 786 | bitClear(NET_ID, 5); 787 | bitClear(NET_ID, 6); 788 | bitClear(NET_ID, 7); 789 | Serial.write(incomingByte); 790 | Serial.println(); 791 | if(incomingByte>=48 && incomingByte<=57){ 792 | incomingByte = incomingByte-48; 793 | incomingByte = (byte)incomingByte << 4; 794 | NET_ID = NET_ID | incomingByte; 795 | TxUdpBuffer[0] = NET_ID; 796 | }else if(incomingByte>=97 && incomingByte<=102){ 797 | incomingByte = incomingByte-87; 798 | incomingByte = (byte)incomingByte << 4; 799 | NET_ID = NET_ID | incomingByte; 800 | TxUdpBuffer[0] = NET_ID; 801 | } 802 | // sufix 803 | #if !defined(HW_BCD_SW) 804 | Serial.println(F("Press NET-ID _X sufix 0-f...")); 805 | Serial.print(F("> ")); 806 | while (Serial.available() == 0) { 807 | // Wait 808 | } 809 | incomingByte = Serial.read(); 810 | if( (incomingByte>=48 && incomingByte<=57) || (incomingByte>=97 && incomingByte<=102) ){ 811 | bitClear(NET_ID, 0); 812 | bitClear(NET_ID, 1); 813 | bitClear(NET_ID, 2); 814 | bitClear(NET_ID, 3); 815 | Serial.write(incomingByte); 816 | Serial.println(); 817 | if(incomingByte>=48 && incomingByte<=57){ 818 | incomingByte = incomingByte-48; 819 | NET_ID = NET_ID | incomingByte; 820 | TxUdpBuffer[0] = NET_ID; 821 | }else if(incomingByte>=97 && incomingByte<=102){ 822 | incomingByte = incomingByte-87; 823 | NET_ID = NET_ID | incomingByte; 824 | TxUdpBuffer[0] = NET_ID; 825 | } 826 | #endif 827 | EEPROM.write(1, NET_ID); // address, value 828 | // EEPROM.commit(); 829 | Serial.print(F("** Now NET-ID change to 0x")); 830 | Serial.print(NET_ID, HEX); 831 | Serial.println(F(" **")); 832 | #if defined(SERIAL_debug) 833 | if(DebugLevel>1){ 834 | Serial.print(F("EEPROM read [")); 835 | Serial.print(EEPROM.read(1), HEX); 836 | Serial.println(F("]")); 837 | } 838 | #endif 839 | TxUDP(ThisDevice, RemoteDevice, 'b', 'r', 'o'); 840 | #if !defined(HW_BCD_SW) 841 | }else{ 842 | Serial.println(F(" accepts 0-f, exit")); 843 | } 844 | #endif 845 | }else{ 846 | Serial.println(" accepts 0-f, exit"); 847 | } 848 | #endif 849 | 850 | #if !defined(RestoreMemoryFromEeprom) 851 | // s 852 | }else if(incomingByte==115){ 853 | Serial.print(F("* Copy RAM table to EEPROM bank ")); 854 | Serial.println(BankOfMemory); 855 | for (int x=0; x ")); 885 | // while(!Serial.available()){ 886 | // } 887 | // delay(2000); 888 | // int CompareInt = Serial.parseInt(); 889 | Enter(); 890 | int intBuf=0; 891 | int mult=1; 892 | for (int j=InputByte[0]; j>0; j--){ 893 | intBuf = intBuf + ((InputByte[j]-48)*mult); 894 | mult = mult*10; 895 | } 896 | if(intBuf>=2 && intBuf<=112){ 897 | NumberOfMemory = intBuf; 898 | NumberOfBank=224/(NumberOfMemory+1); 899 | if(NumberOfBank>16){ 900 | NumberOfBank=16; 901 | } 902 | EEPROM.write(8, NumberOfMemory); 903 | Serial.print(F(" Set ")); 904 | Serial.print(NumberOfMemory); 905 | Serial.print(F("memory / ")); 906 | Serial.print(NumberOfBank); 907 | Serial.println(F(" bank")); 908 | }else{ 909 | Serial.println(F(" Out of range.")); 910 | } 911 | 912 | // e 913 | }else if(incomingByte==101){ 914 | Serial.println(F("EEPROM #address kHz | uStep by bank...")); 915 | for (int x=0; x ")); 947 | 948 | while(br==false) { 949 | if(Serial.available()){ 950 | incomingByte=Serial.read(); 951 | if(incomingByte==13){ 952 | br=true; 953 | Serial.println(""); 954 | }else{ 955 | Serial.write(incomingByte); 956 | InputByte[InputByte[0]+1]=incomingByte; 957 | InputByte[0]++; 958 | } 959 | if(InputByte[0]==20){ 960 | br=true; 961 | Serial.print(F(" too long")); 962 | } 963 | } 964 | } 965 | } 966 | 967 | //--------------------------------------------------------------------------------------------------------- 968 | void ListCommands(){ 969 | #if defined(CLI) 970 | Serial.println(); 971 | Serial.println(F(" =========================")); 972 | #if defined(EthModule) 973 | Serial.print(F(" IP stepper NET ID: ")); 974 | Serial.println(NET_ID, HEX); 975 | #else 976 | Serial.println(F(" ICOM CI-V stepper")); 977 | #endif 978 | // Serial.print(" [BCD-"); 979 | // Serial.print(digitalRead(Id1Pin)); 980 | // Serial.print(digitalRead(Id2Pin)); 981 | // Serial.print(digitalRead(Id3Pin)); 982 | // Serial.println("]"); 983 | Serial.println(F(" =========================")); 984 | Serial.print(F(" Firmware: ")); 985 | Serial.println(REV); 986 | 987 | #if defined(EthModule) 988 | Serial.println(); 989 | Serial.println(F(" Ethernet")); 990 | Serial.print(F(" - IP address:")); 991 | Serial.println(Ethernet.localIP()); 992 | Serial.print(F(" - IP source [")); 993 | Serial.write(RemoteDevice); 994 | Serial.print(F("]: ")); 995 | Serial.print(UdpCommand.remoteIP()); 996 | Serial.print(F(":")); 997 | Serial.println(UdpCommand.remotePort()); 998 | #endif 999 | 1000 | Serial.println(); 1001 | Serial.println(F(" Stepper settings")); 1002 | Serial.print(F(" - Actual u step counter = ")); 1003 | Serial.print(SteppersCounter); 1004 | Serial.print(F(" = ")); 1005 | float GRAD = 360/(float(StepsByTurn)*float(MicroSteps))*float(SteppersCounter); 1006 | Serial.print(GRAD); 1007 | Serial.println("°"); 1008 | Serial.print(F(" - Steps by turn = ")); 1009 | Serial.println(StepsByTurn); 1010 | Serial.print(F(" - Microsteps = ")); 1011 | Serial.println(MicroSteps); 1012 | Serial.print(F(" - Current Run = ")); 1013 | Serial.println(CurrentRun); 1014 | Serial.print(F(" - Current Standby = ")); 1015 | Serial.println(CurrentStandby); 1016 | Serial.print(F(" - Current Run timeout [ms] = ")); 1017 | Serial.println(CurrentRunTimeout[1]); 1018 | Serial.print(F(" - Enable stepper if standby = ")); 1019 | Serial.println(EnableStepperStandby); 1020 | // Serial.print(F(" - Enable slow start/stop = ")); 1021 | // Serial.println(EnableSlowStartStop); 1022 | Serial.print(F(" - One step uSeconds = ")); 1023 | Serial.println(uSeconds); 1024 | 1025 | #if defined(ICOM_CIV) 1026 | Serial.println(); 1027 | Serial.println(F(" ICOM CI-V")); 1028 | Serial.print(F(" - Actual frequency Hz = ")); 1029 | Serial.println(freq); 1030 | Serial.print(F(" - Address = ")); 1031 | Serial.print(CIV_ADRESS, HEX); 1032 | Serial.println("h"); 1033 | if(EnableEndstop==false){ 1034 | Serial.print(F(" - Request time [ms] = ")); 1035 | Serial.println(REQUEST); 1036 | } 1037 | Serial.print(F(" - Baudrate = ")); 1038 | Serial.println(BAUDRATE1); 1039 | #endif 1040 | Serial.println(); 1041 | Serial.println(F(" BCD input")); 1042 | Serial.print(F(" - Actual Bank-")); 1043 | Serial.println(BankOfMemory); 1044 | Serial.println(); 1045 | Serial.println(F(" -----------------------------")); 1046 | Serial.println(F(" Character commands:")); 1047 | Serial.println(F(" ? for info")); 1048 | Serial.println(F(" c CI-V preset (baud, address)")); 1049 | Serial.println(F(" @ stepper settings")); 1050 | Serial.print(F(" i Linear Interpolation [")); 1051 | if(LinearInterpolation==true){ 1052 | Serial.println(F("ON]")); 1053 | }else if(LinearInterpolation==false){ 1054 | Serial.println(F("OFF], hysteresis +-500Hz")); 1055 | } 1056 | Serial.print(F(" r reverse ")); 1057 | if(Reverse==0){ 1058 | Serial.println(F("[OFF]")); 1059 | }else if(Reverse==1){ 1060 | Serial.println(F("[ON]")); 1061 | } 1062 | Serial.print(F(" + enable ")); 1063 | if(EnableEndstop==true){ 1064 | Serial.println(F("[Endstop]/Last position save to eeprom")); 1065 | }else if(EnableEndstop==false){ 1066 | Serial.print(F("Endstop/[Last position save to eeprom] saved ")); 1067 | Serial.print(EEPROMReadlong(10)); 1068 | Serial.print(F(" = ")); 1069 | GRAD = 360/(float(StepsByTurn)*float(MicroSteps))*float(EEPROMReadlong(10)); 1070 | Serial.print(GRAD); 1071 | Serial.println("°"); 1072 | } 1073 | #if defined(SERIAL_debug) 1074 | Serial.print(F(" * serial debug level [")); 1075 | Serial.print(DebugLevel); 1076 | Serial.println(F("] set")); 1077 | #endif 1078 | Serial.print(F(" m number of frequencies in memory [")); 1079 | Serial.print(NumberOfMemory); 1080 | Serial.print(F("]/")); 1081 | Serial.print(NumberOfBank); 1082 | Serial.println(F(" bank")); 1083 | Serial.print(F(" l Freqency/uSteps listing for actual bank ")); 1084 | Serial.println(BankOfMemory); 1085 | Serial.println(F(" e Freqency/uSteps EEPROM listing ")); 1086 | #if defined(EthModule) 1087 | Serial.println(F(" #0-f network ID prefix [hex]")); 1088 | #if !defined(HW_BCD_SW) 1089 | Serial.println(F(" +network ID sufix [hex]")); 1090 | #endif 1091 | #endif 1092 | #if !defined(RestoreMemoryFromEeprom) 1093 | Serial.println(F(" s Save RAM freq table to EEPROM by selected bank")); 1094 | #endif 1095 | Serial.println(); 1096 | Serial.print(F(" / ")); 1097 | if(TuningMode==0){ 1098 | Serial.println(F("[running]/tuning mode")); 1099 | }else if(TuningMode==1){ 1100 | Serial.println(F("running/[tuning] mode")); 1101 | } 1102 | if(TuningMode==1){ 1103 | Serial.print(F(" u upper ustepper counter limit [")); 1104 | Serial.print(SteppersCounterLimit); 1105 | Serial.print(F(" uStep] = ")); 1106 | GRAD = 360/(float(StepsByTurn)*float(MicroSteps))*float(SteppersCounterLimit); 1107 | Serial.print(GRAD); 1108 | Serial.println("°"); 1109 | Serial.println(); 1110 | Serial.println(F(" 6 rotate CW")); 1111 | Serial.println(F(" 4 rotate CCW")); 1112 | Serial.println(F(" 8 step multiplier up")); 1113 | Serial.println(F(" 2 step multiplier down")); 1114 | Serial.print(F(" actual step multiplier [")); 1115 | Serial.print(Multiplier); 1116 | Serial.println(F("x]")); 1117 | Serial.println(); 1118 | Serial.print(F(" w tuning Wizard [bank ")); 1119 | Serial.print(BankOfMemory); 1120 | if(WizardEnable==true){ 1121 | Serial.print(F("] actual wizard step [")); 1122 | Serial.print(WizardStep); 1123 | } 1124 | Serial.println(F("]")); 1125 | } 1126 | Serial.println(F(" -----------------------------")); 1127 | #endif 1128 | } 1129 | 1130 | //--------------------------------------------------------------------------------------------------------- 1131 | void WizardCLI(){ 1132 | #if defined(CLI) 1133 | if(WizardEnable==true && TuningMode==1){ 1134 | int longer=String(freq/1000).length(); 1135 | switch (WizardStep%2) { 1136 | case 0: // even 1137 | if(BankOfMemory==0){ 1138 | Serial.print(F(" tune FREQUENCY and stepper, then press [5] for storage to mem ")); 1139 | }else{ 1140 | Serial.print(F(" Set frequency to ")); 1141 | Serial.print(StorageFreqToStep[(WizardStep)/2][0]); 1142 | Serial.print(F(" kHz and move stepper, then press [5] for storage to mem ")); 1143 | txCIV(0, freq, CIV_ADRESS); // 0 - set freq 1144 | } 1145 | Serial.print(WizardStep/2); 1146 | Serial.print(F("/")); 1147 | Serial.print(NumberOfMemory); 1148 | Serial.print(F(" bank-")); 1149 | Serial.println(BankOfMemory); 1150 | WizardStep++; 1151 | break; 1152 | case 1: // odd 1153 | // 5 1154 | if(incomingByte==53){ 1155 | if( 1156 | (BankOfMemory==0 && (WizardStep==1 || ( freq>StorageFreqToStep[(WizardStep-1)/2-1][0] && SteppersCounter>StorageFreqToStep[(WizardStep-1)/2-1][1] ))) 1157 | || (BankOfMemory!=0 && (freq==StorageFreqToStep[(WizardStep-1)/2][0] && ( WizardStep==1 || SteppersCounter>StorageFreqToStep[(WizardStep-1)/2-1][1] ))) 1158 | ){ 1159 | Serial.println(); 1160 | Serial.print(F("* Set ")); 1161 | // if(BankOfMemory==0){ 1162 | StorageFreqToStep[(WizardStep-1)/2][0]=freq; 1163 | Serial.print(String(freq/1000).substring(0, longer-3)); 1164 | Serial.print(F(" ")); 1165 | Serial.print(String(freq/1000).substring(longer-3, longer)); 1166 | Serial.print(F(".")); 1167 | Serial.print(String(freq).substring(longer-6, longer)); 1168 | Serial.print(F("kHz ")); 1169 | // } 1170 | StorageFreqToStep[(WizardStep-1)/2][1]=SteppersCounter; 1171 | Serial.print(SteppersCounter); 1172 | Serial.print(F("us to memory ")); 1173 | Serial.print((WizardStep-1)/2); 1174 | Serial.print(F("/")); 1175 | Serial.print(NumberOfMemory-1); 1176 | WizardStep++; 1177 | incomingByte=0x00; 1178 | if(WizardStep==NumberOfMemory*2){ 1179 | Serial.println(F(" - Save to EEPROM, wizard END and switch to RUN mode")); 1180 | Serial.println(); 1181 | WizardStep=0; 1182 | WizardEnable=false; 1183 | TuningMode=0; 1184 | for (int x=0; x")); 1197 | Serial.print(StorageFreqToStep[(WizardStep-1)/2-1][0]); 1198 | }else{ 1199 | Serial.print(F("* NOT set - freq must be set to ")); 1200 | Serial.print(StorageFreqToStep[(WizardStep-1)/2][0]); 1201 | Serial.println(F("kHz and steps must be bigger than previous memory")); 1202 | Serial.print(freq); 1203 | Serial.print(F("=")); 1204 | Serial.print(StorageFreqToStep[(WizardStep-1)/2][0]); 1205 | } 1206 | Serial.print(F(" ")); 1207 | Serial.print(SteppersCounter); 1208 | Serial.print(F(">")); 1209 | Serial.println(StorageFreqToStep[(WizardStep-1)/2-1][1]); 1210 | Serial.println(); 1211 | WizardStep--; 1212 | incomingByte=0x00; 1213 | } 1214 | } 1215 | break; 1216 | } 1217 | } 1218 | #endif 1219 | } 1220 | 1221 | //--------------------------------------------------------------------------------------------------------- 1222 | void ShortStatus(){ 1223 | #if defined(SERIAL_debug) && defined(CLI) 1224 | if(DebugLevel>0){ 1225 | int longer=String(freq/1000).length(); 1226 | if(longer<4){ 1227 | Serial.print(freq); 1228 | }else{ 1229 | Serial.print(String(freq/1000).substring(0, longer-3)); 1230 | Serial.print(F(" ")); 1231 | Serial.print(String(freq/1000).substring(longer-3, longer)); 1232 | Serial.print(F(".")); 1233 | Serial.print(String(freq).substring(longer-6, longer)); 1234 | } 1235 | Serial.print(F("kHz ")); 1236 | Serial.print(SteppersCounter); 1237 | Serial.print(F("us ")); 1238 | float GRAD = 360/(float(StepsByTurn)*float(MicroSteps))*float(SteppersCounter); 1239 | Serial.print(GRAD); 1240 | Serial.println(F("°")); 1241 | } 1242 | #endif 1243 | } 1244 | 1245 | //--------------------------------------------------------------------------------------------------------- 1246 | 1247 | void LcdDisplay(){ 1248 | #if defined(LCD) 1249 | if(millis()-LcdRefresh[0]>LcdRefresh[1] || LcdNeedRefresh == true){ 1250 | 1251 | #if defined(EthModule) 1252 | if(EthLinkStatus==0){ 1253 | lcd.setCursor(0, 0); 1254 | lcd.print((char)1); // EthChar 1255 | lcd.print(F(" Please connect")); 1256 | lcd.setCursor(0, 1); 1257 | lcd.print(F(" ethernet ")); 1258 | }else{ 1259 | #endif 1260 | 1261 | // STEP 1262 | lcd.setCursor(1,0); 1263 | Space(6, String(SteppersCounter).length(), ' '); 1264 | lcd.print(SteppersCounter); 1265 | lcd.print("|"); 1266 | float GRAD = 360/(float(StepsByTurn)*float(MicroSteps))*float(SteppersCounter); 1267 | lcd.print(GRAD); 1268 | lcd.print(char(223)); 1269 | lcd.print(" "); 1270 | 1271 | lcd.setCursor(0,1); 1272 | lcd.print(BankOfMemory, HEX); 1273 | Space(9, String(freq).length(), ' '); 1274 | PrintFreq(); 1275 | lcd.setCursor(12,1); 1276 | lcd.print(" kHz"); 1277 | 1278 | LcdRefresh[0]=millis(); 1279 | LcdNeedRefresh = false; 1280 | 1281 | #if defined(EthModule) 1282 | } 1283 | #endif 1284 | } 1285 | #endif 1286 | } 1287 | 1288 | //------------------------------------------------------------------------------------ 1289 | 1290 | #if defined(LCD) 1291 | void PrintFreq(){ 1292 | int longer=String(freq/1000).length(); 1293 | if(longer<4){ 1294 | lcd.print(" "); 1295 | lcd.print(freq); 1296 | }else{ 1297 | lcd.print(String(freq/1000).substring(0, longer-3)); 1298 | lcd.print(" "); 1299 | lcd.print(String(freq/1000).substring(longer-3, longer)); 1300 | lcd.print("."); 1301 | lcd.print(String(freq).substring(longer-6, longer)); 1302 | } 1303 | } 1304 | #endif 1305 | 1306 | //--------------------------------------------------------------------------------------------------------- 1307 | 1308 | #if defined(LCD) 1309 | void Space(int MAX, int LENGHT, char CHARACTER){ 1310 | int NumberOfSpace = MAX-LENGHT; 1311 | if(NumberOfSpace>0){ 1312 | for (int i=0; i 0) { 1324 | incomingByte1 = Serial1.read(); 1325 | #if defined(SERIAL_debug) 1326 | if(DebugLevel>1){ 1327 | Serial.print(F("CIV ")); 1328 | Serial.print(incomingByte1, HEX); 1329 | Serial.println(); 1330 | } 1331 | #endif 1332 | icomSM(incomingByte1); 1333 | rdIS=""; 1334 | // if(rdI[10]==0xFD){ // state machine end 1335 | if(StateMachineEnd == true){ // state machine end 1336 | StateMachineEnd = false; 1337 | for (int i=9; i>=5; i-- ){ 1338 | if (rdI[i] < 10) { // leading zero 1339 | rdIS = rdIS + 0; 1340 | } 1341 | rdIS = rdIS + String(rdI[i], HEX); // append BCD digit from HEX variable to string 1342 | } 1343 | freq = rdIS.toInt(); 1344 | // Serial.println(freq); 1345 | // Serial.println("-------"); 1346 | // FreqToBandRules(); 1347 | // bandSET(); 1348 | Tune(); 1349 | #if defined(LCD) 1350 | LcdNeedRefresh=true; 1351 | #endif 1352 | RequestTimeout[0]=millis(); 1353 | } 1354 | } 1355 | #endif 1356 | } 1357 | //--------------------------------------------------------------------------------------------------------- 1358 | 1359 | int icomSM(byte b){ // state machine 1360 | #if defined(ICOM_CIV) 1361 | // This filter solves read from 0x00 0x05 0x03 commands and 00 E0 F1 address used by software 1362 | // Serial.print(b, HEX); 1363 | // Serial.print(" | "); 1364 | // Serial.println(state); 1365 | switch (state) { 1366 | case 1: if( b == 0xFE ){ state = 2; rdI[0]=b; rdI[10]=0x00; }; break; 1367 | case 2: if( b == 0xFE ){ state = 3; rdI[1]=b; }else{ state = 1;}; break; 1368 | // addresses that use different software 00-trx, e0-pc-ale, winlinkRMS, f1-winlink trimode 1369 | case 3: if( b == 0x00 || b == 0xE0 || b == 0x0E || b == 0xF1 ){ state = 4; rdI[2]=b; // choose command $03 1370 | }else if( b == CIV_ADRESS ){ state = 6; rdI[2]=b; 1371 | }else if( b == 0xFE ){ state = 3; rdI[1]=b; // FE (3x reduce to 2x) 1372 | }else{ state = 1;}; break; // or $05 1373 | 1374 | case 4: if( b == CIV_ADRESS ){ state = 5; rdI[3]=b; }else{ state = 1;}; break; // select command $03 1375 | case 5: if( b == 0x00 || b == 0x03 ){state = 8; rdI[4]=b; // freq 1376 | }else if( b == 0x04 ){state = 14; rdI[4]=b; // mode 1377 | }else if( b == 0xFE ){ state = 2; rdI[0]=b; // FE 1378 | }else{ state = 1;}; break; 1379 | 1380 | case 6: if( b == 0x00 || b == 0xE0 || b == 0xF1 ){ state = 7; rdI[3]=b; }else{ state = 1;}; break; // select command $05 1381 | case 7: if( b == 0x00 || b == 0x05 ){ state = 8; rdI[4]=b; }else{ state = 1;}; break; 1382 | 1383 | case 8: if( b <= 0x99 ){state = 9; rdI[5]=b; // 10Hz 1Hz 1384 | }else if( b == 0xFE ){ state = 2; rdI[0]=b; // FE 1385 | }else{state = 1;}; break; 1386 | case 9: if( b <= 0x99 ){state = 10; rdI[6]=b; // 1kHz 100Hz 1387 | }else if( b == 0xFE ){ state = 2; rdI[0]=b; // FE 1388 | }else{state = 1;}; break; 1389 | case 10: if( b <= 0x99 ){state = 11; rdI[7]=b; // 100kHz 10kHz 1390 | }else if( b == 0xFE ){ state = 2; rdI[0]=b; // FE 1391 | }else{state = 1;}; break; 1392 | case 11: if( b <= 0x52 ){state = 12; rdI[8]=b; // 10MHz 1Mhz 1393 | }else if( b == 0xFE ){ state = 2; rdI[0]=b; // FE 1394 | }else{state = 1;}; break; 1395 | case 12: if( b <= 0x01 || b == 0x04){state = 13; rdI[9]=b; // 1GHz 100MHz <-- 1xx/4xx MHz limit 1396 | }else if( b == 0xFE ){ state = 2; rdI[0]=b; // FE 1397 | }else{state = 1;}; break; 1398 | case 13: if( b == 0xFD ){state = 1; rdI[10]=b; StateMachineEnd = true; 1399 | }else if( b == 0xFE ){ state = 2; rdI[0]=b; // FE 1400 | }else{state = 1; rdI[10] = 0x00;}; break; 1401 | 1402 | case 14: if( b <= 0x12 ){state = 15; rdI[5]=b; 1403 | }else if( b == 0xFE ){ state = 2; rdI[0]=b; // FE 1404 | }else{state = 1;}; break; // Mode 1405 | case 15: if( b <= 0x03 ){state = 16; rdI[6]=b; 1406 | }else if( b == 0xFE ){ state = 2; rdI[0]=b; // FE 1407 | }else{state = 1;}; break; // Filter 1408 | case 16: if( b == 0xFD ){state = 1; rdI[7]=b; 1409 | }else if( b == 0xFE ){ state = 2; rdI[0]=b; // FE 1410 | }else{state = 1; rdI[7] = 0;}; break; 1411 | } 1412 | #endif 1413 | } 1414 | 1415 | //--------------------------------------------------------------------------------------------------------- 1416 | 1417 | int txCIV(int commandCIV, long dataCIVtx, int toAddress) { 1418 | #if defined(ICOM_CIV) 1419 | Serial1.write(254); // FE 1420 | Serial1.write(254); // FE 1421 | Serial1.write(toAddress); // to adress 1422 | Serial1.write(fromAdress); // from OE 1423 | Serial1.write(commandCIV); // data 1424 | if (dataCIVtx != 0){ 1425 | String freqCIVtx = String(dataCIVtx); // to string 1426 | String freqCIVtxPart; 1427 | while (freqCIVtx.length() < 10) { // leding zeros 1428 | freqCIVtx = 0 + freqCIVtx; 1429 | } 1430 | for (int x=8; x>=0; x=x-2){ // loop for 5x2 char [xx xx xx xx xx] 1431 | freqCIVtxPart = freqCIVtx.substring(x,x+2); // cut freq to five part 1432 | Serial1.write(hexToDec(freqCIVtxPart)); // HEX to DEC, because write as DEC format from HEX variable 1433 | } 1434 | } 1435 | Serial1.write(253); // FD 1436 | #if defined(SERIAL_debug) 1437 | if(DebugLevel>1){ 1438 | Serial.println(F("txCIV")); 1439 | } 1440 | #endif 1441 | // Serial1.flush(); 1442 | while(Serial1.available()){ // clear buffer 1443 | Serial1.read(); 1444 | } 1445 | #endif 1446 | } 1447 | //--------------------------------------------------------------------------------------------------------- 1448 | 1449 | unsigned int hexToDec(String hexString) { 1450 | #if defined(ICOM_CIV) 1451 | unsigned int decValue = 0; 1452 | int nextInt; 1453 | for (int i = 0; i < hexString.length(); i++) { 1454 | nextInt = int(hexString.charAt(i)); 1455 | if (nextInt >= 48 && nextInt <= 57) nextInt = map(nextInt, 48, 57, 0, 9); 1456 | if (nextInt >= 65 && nextInt <= 70) nextInt = map(nextInt, 65, 70, 10, 15); 1457 | if (nextInt >= 97 && nextInt <= 102) nextInt = map(nextInt, 97, 102, 10, 15); 1458 | nextInt = constrain(nextInt, 0, 15); 1459 | decValue = (decValue * 16) + nextInt; 1460 | } 1461 | return decValue; 1462 | #endif 1463 | } 1464 | //--------------------------------------------------------------------------------------------------------- 1465 | 1466 | void FrequencyRequest(){ 1467 | #if defined(REQUEST) && defined(ICOM_CIV) 1468 | 1469 | if((millis() - RequestTimeout[0] > RequestTimeout[1] && EnableEndstop==false) ){ // Request enable only if disable endstop - undefined bug in txCIV 1470 | txCIV(3, 0, CIV_ADRESS); // ([command], [freq]) 3=read 1471 | RequestTimeout[0]=millis(); 1472 | } 1473 | #endif 1474 | } 1475 | //--------------------------------------------------------------------------------------------------------- 1476 | 1477 | void Tune(){ 1478 | // LinearInterpolation 1479 | if(freqPrev!=freq && TuningMode==0){ 1480 | if(LinearInterpolation==true){ 1481 | for (int i = 0; i < NumberOfMemory; i++) { 1482 | if(StorageFreqToStep[i][0] <= freq && freq <= StorageFreqToStep[i+1][0]){ // find range 1483 | SteppersCounterTarget = map(freq, StorageFreqToStep[i][0], StorageFreqToStep[i+1][0], StorageFreqToStep[i][1], StorageFreqToStep[i+1][1]); // map(value, fromLow, fromHigh, toLow, toHigh) //*10 one decimal 1484 | SerialNeedStatus=true; 1485 | break; 1486 | } 1487 | } 1488 | freqPrev=freq; 1489 | // LinearInterpolation OFF 1490 | }else{ 1491 | const int Hysteresis = 500; 1492 | for (int i = 0; i < NumberOfMemory; i++) { 1493 | if( (i==0 1494 | && (StorageFreqToStep[i+1][0]-StorageFreqToStep[i][0])/2+StorageFreqToStep[i][0] >= freq 1495 | && abs(freq-freqPrev)>Hysteresis ) 1496 | || (i!=0 && i!=NumberOfMemory-1 1497 | && (StorageFreqToStep[i][0]-StorageFreqToStep[i-1][0])/2+StorageFreqToStep[i-1][0] <= freq 1498 | && (StorageFreqToStep[i+1][0]-StorageFreqToStep[i][0])/2+StorageFreqToStep[i][0] >= freq 1499 | && abs(freq-freqPrev)>Hysteresis ) 1500 | || ( i==NumberOfMemory-1 1501 | && (StorageFreqToStep[i][0]-StorageFreqToStep[i-1][0])/2+StorageFreqToStep[i-1][0] <= freq 1502 | && abs(freq-freqPrev)>Hysteresis ) 1503 | ){ 1504 | SteppersCounterTarget = StorageFreqToStep[i][1]; 1505 | freqPrev=freq; 1506 | SerialNeedStatus=true; 1507 | break; 1508 | } 1509 | } // end for 1510 | } // end LinearInterpolation OFF 1511 | } // end TuningMode 1512 | } 1513 | //------------------------------------------------------------------------------------ 1514 | 1515 | void OnTheFlyStepperControl(){ 1516 | if(SteppersCounterTarget<=SteppersCounterLimit){ 1517 | if(SteppersCounterTarget!=SteppersCounter){ 1518 | myStepper.set_IHOLD_IRUN(CurrentRun,CurrentRun,5); // ([0-31],[0-31],[0-5]) sets all currents to maximum 1519 | if(EnableStepperStandby==false){ 1520 | digitalWrite(EN_PIN, LOW); // LOW = enable 1521 | } 1522 | digitalWrite(TxInhibitPin, HIGH); 1523 | #if defined(LCD) 1524 | lcd.setCursor(0, 0); 1525 | lcd.print((char)0); // LockChar 1526 | #endif 1527 | 1528 | if(SteppersCounterTargetSteppersCounter){ 1532 | digitalWrite(DIR_PIN, Reverse); 1533 | InDeCrement = 1; 1534 | } 1535 | while(SteppersCounterTarget!=SteppersCounter){ 1536 | // InterruptON(0); 1537 | digitalWrite(StepPin, HIGH); 1538 | delayMicroseconds(uSeconds); 1539 | digitalWrite(StepPin, LOW); 1540 | delayMicroseconds(uSeconds); 1541 | SteppersCounter=SteppersCounter+InDeCrement; 1542 | } 1543 | CurrentRunTimeout[0] = millis(); 1544 | LastPositionSave=false; 1545 | } 1546 | if(SerialNeedStatus==true){ 1547 | ShortStatus(); 1548 | SerialNeedStatus=false; 1549 | } 1550 | }else{ 1551 | #if defined(SERIAL_debug) 1552 | if(DebugLevel>0){ 1553 | Serial.print(F("Target ")); 1554 | Serial.print(SteppersCounterTarget); 1555 | Serial.print(F(" over counter limit ")); 1556 | Serial.println(SteppersCounterLimit); 1557 | SteppersCounterTarget=SteppersCounterLimit; 1558 | } 1559 | #endif 1560 | } 1561 | } 1562 | 1563 | //------------------------------------------------------------------------------------ 1564 | void uStepTouSeconds(){ 1565 | // Microstep long in uSeconds 1566 | switch (MicroSteps) { 1567 | case 1: uSeconds = 2000 ; break; 1568 | case 2: uSeconds = 700 ; break; 1569 | case 4: uSeconds = 600 ; break; 1570 | case 8: uSeconds = 300 ; break; 1571 | case 16: uSeconds = 200 ; break; 1572 | case 32: uSeconds = 60 ; break; 1573 | case 64: uSeconds = 16 ; break; 1574 | case 128: uSeconds = 11 ; break; 1575 | case 256: uSeconds = 11 ; break; 1576 | } 1577 | } 1578 | //------------------------------------------------------------------------------------ 1579 | 1580 | void InterruptON(int endstop){ 1581 | if(endstop==0 && EnableEndstop==true){ 1582 | detachInterrupt(digitalPinToInterrupt(EndStopPin)); 1583 | #if defined(SERIAL_debug) 1584 | if(DebugLevel>0){ 1585 | Serial.print(F("* Interrupt OFF *")); 1586 | } 1587 | #endif 1588 | }else if(endstop==1 && EnableEndstop==true){ 1589 | attachInterrupt(digitalPinToInterrupt(EndStopPin), EndstopNow, FALLING); // need detachInterrupt in RX_UDP() subroutine 1590 | #if defined(SERIAL_debug) 1591 | if(DebugLevel>0){ 1592 | Serial.print(F("* Interrupt ON *")); 1593 | } 1594 | #endif 1595 | } 1596 | } 1597 | 1598 | //--------------------------------------------------------------------------------------------------------- 1599 | void EndstopNow(){ 1600 | SteppersCounter = 0-InDeCrement; 1601 | #if defined(SERIAL_debug) 1602 | if(DebugLevel>0){ 1603 | Serial.println(F("* INTERRUPT NOW *")); 1604 | } 1605 | #endif 1606 | } 1607 | 1608 | //------------------------------------------------------------------------------------ 1609 | //This function will write a 4 byte (32bit) long to the eeprom at 1610 | //the specified address to address + 3. 1611 | void EEPROMWritelong(int address, long value){ 1612 | //Decomposition from a long to 4 bytes by using bitshift. 1613 | //One = Most significant -> Four = Least significant byte 1614 | byte four = (value & 0xFF); 1615 | byte three = ((value >> 8) & 0xFF); 1616 | byte two = ((value >> 16) & 0xFF); 1617 | byte one = ((value >> 24) & 0xFF); 1618 | 1619 | //Write the 4 bytes into the eeprom memory. 1620 | EEPROM.write(address, four); 1621 | EEPROM.write(address + 1, three); 1622 | EEPROM.write(address + 2, two); 1623 | EEPROM.write(address + 3, one); 1624 | } 1625 | 1626 | //------------------------------------------------------------------------------------ 1627 | 1628 | long EEPROMReadlong(long address){ 1629 | //Read the 4 bytes from the eeprom memory. 1630 | long four = EEPROM.read(address); 1631 | long three = EEPROM.read(address + 1); 1632 | long two = EEPROM.read(address + 2); 1633 | long one = EEPROM.read(address + 3); 1634 | 1635 | //Return the recomposed long by using bitshift. 1636 | return ((four << 0) & 0xFF) + ((three << 8) & 0xFFFF) + ((two << 16) & 0xFFFFFF) + ((one << 24) & 0xFFFFFFFF); 1637 | } 1638 | 1639 | //--------------------------------------------------------------------------------------------------------- 1640 | void BcdCheck(){ 1641 | if(millis()-BcdRefresh[0]>BcdRefresh[1]){ 1642 | BankOfMemory=GetBcd(); 1643 | if(BankOfMemory!=BankOfMemoryPrev){ 1644 | BankOfMemoryPrev=BankOfMemory; 1645 | EEPROM.write(3, BankOfMemory); 1646 | Serial.println(); 1647 | Serial.print(F("* Bank change to ")); 1648 | Serial.print(BankOfMemory); 1649 | Serial.println(F(", load memory from EEPROM")); 1650 | // set array from eeprom 1651 | for (int x=0; xCurrentRunTimeout[1]){ 1663 | myStepper.set_IHOLD_IRUN(CurrentStandby,CurrentStandby,0); // ([0-31],[0-31],[0-5]) sets all currents to maximum 1664 | if(EnableStepperStandby==false){ 1665 | digitalWrite(EN_PIN, HIGH); // LOW = enable 1666 | } 1667 | digitalWrite(TxInhibitPin, LOW); 1668 | if(EnableEndstop==false && LastPositionSave==false){ 1669 | EEPROMWritelong(10, SteppersCounter); 1670 | LastPositionSave=true; 1671 | #if defined(SERIAL_debug) 1672 | if(DebugLevel>0){ 1673 | Serial.println(F("* Last position save to eeprom *")); 1674 | } 1675 | #endif 1676 | } 1677 | #if defined(LCD) 1678 | lcd.setCursor(0, 0); 1679 | lcd.print(" "); 1680 | #endif 1681 | } 1682 | } 1683 | 1684 | //--------------------------------------------------------------------------------------------------------- 1685 | byte GetBcd(){ 1686 | byte BCD = 0; 1687 | if(digitalRead(BcdPin[0])==0){ 1688 | BCD = BCD | (1<<0); // Set the n-th bit 1689 | } 1690 | if(digitalRead(BcdPin[1])==0){ 1691 | BCD = BCD | (1<<1); // Set the n-th bit 1692 | } 1693 | if(digitalRead(BcdPin[2])==0){ 1694 | BCD = BCD | (1<<2); // Set the n-th bit 1695 | } 1696 | if(digitalRead(BcdPin[3])==0){ 1697 | BCD = BCD | (1<<3); // Set the n-th bit 1698 | } 1699 | if(BCD>NumberOfBank-1){ 1700 | BCD=NumberOfBank-1; 1701 | } 1702 | return BCD; 1703 | } 1704 | 1705 | //--------------------------------------------------------------------------------------------------------- 1706 | 1707 | void TxUDP(byte FROM, byte TO, byte A, byte B, byte C){ 1708 | #if defined(EthModule) 1709 | InterruptON(0); // ptt, enc 1710 | 1711 | // TxUdpBuffer[0] = NET_ID; 1712 | TxUdpBuffer[1] = FROM; 1713 | TxUdpBuffer[2] = TO; 1714 | TxUdpBuffer[3] = B00111010; // : 1715 | TxUdpBuffer[4] = A; 1716 | TxUdpBuffer[5] = B; 1717 | TxUdpBuffer[6] = C; 1718 | TxUdpBuffer[7] = B00111011; // ; 1719 | 1720 | // BROADCAST 1721 | if(A=='b' && B=='r' && C=='o'){ // b r o 1722 | // if(A==B01100010 && B==B01110010 && C==B01101111){ // b r o 1723 | // direct 1724 | // for (int i=0; i<15; i++){ 1725 | if(UdpCommand.remotePort()!=0){ 1726 | // if(IdSufix(NET_ID)==i ){ 1727 | UdpCommand.beginPacket(UdpCommand.remoteIP(), UdpCommand.remotePort()); 1728 | UdpCommand.write(TxUdpBuffer, sizeof(TxUdpBuffer)); // send buffer 1729 | UdpCommand.endPacket(); 1730 | RemoteSwLatency[0] = millis(); // set START time mark UDP command latency 1731 | RemoteSwLatencyAnsw = 0; // send command, wait to answer 1732 | 1733 | #if defined(SERIAL_debug) 1734 | if(DebugLevel>0){ 1735 | Serial.print(F("TX direct ")); 1736 | // Serial.print(i); 1737 | // Serial.print(F(" ")); 1738 | Serial.print(UdpCommand.remoteIP()); 1739 | Serial.print(F(":")); 1740 | Serial.print(UdpCommand.remotePort()); 1741 | Serial.print(F(" [")); 1742 | Serial.print(TxUdpBuffer[0], HEX); 1743 | for (int i=1; i<8; i++){ 1744 | Serial.print(char(TxUdpBuffer[i])); 1745 | // Serial.print(F(" ")); 1746 | } 1747 | Serial.println(F("]")); 1748 | } 1749 | #endif 1750 | } 1751 | // } 1752 | 1753 | // broadcast 1754 | BroadcastIP = ~Ethernet.subnetMask() | Ethernet.gatewayIP(); 1755 | UdpCommand.beginPacket(BroadcastIP, BroadcastPort); // Send to IP and port from recived UDP command 1756 | UdpCommand.write(TxUdpBuffer, sizeof(TxUdpBuffer)); // send buffer 1757 | UdpCommand.endPacket(); 1758 | IpTimeout[0][0] = millis(); // set time mark 1759 | RemoteSwLatency[0] = millis(); // set START time mark UDP command latency 1760 | RemoteSwLatencyAnsw = 0; // send command, wait to answer 1761 | 1762 | #if defined(SERIAL_debug) 1763 | if(DebugLevel>0){ 1764 | Serial.print(F("TX broadcast ")); 1765 | Serial.print(BroadcastIP); 1766 | Serial.print(F(":")); 1767 | Serial.print(BroadcastPort); 1768 | Serial.print(F(" [")); 1769 | Serial.print(TxUdpBuffer[0], HEX); 1770 | for (int i=1; i<8; i++){ 1771 | Serial.print(char(TxUdpBuffer[i])); 1772 | // Serial.print(F(" ")); 1773 | } 1774 | Serial.println(F("]")); 1775 | } 1776 | #endif 1777 | 1778 | // DATA 1779 | }else{ 1780 | // if(DetectedRemoteSw[IdSufix(NET_ID)][4]!=0){ 1781 | UdpCommand.beginPacket(UdpCommand.remoteIP(), UdpCommand.remotePort()); 1782 | UdpCommand.write(TxUdpBuffer, sizeof(TxUdpBuffer)); // send buffer 1783 | UdpCommand.endPacket(); 1784 | RemoteSwLatency[0] = millis(); // set START time mark UDP command latency 1785 | RemoteSwLatencyAnsw = 0; // send command, wait to answer 1786 | 1787 | #if defined(SERIAL_debug) 1788 | if(DebugLevel>0){ 1789 | Serial.println(); 1790 | Serial.print(F("TX [")); 1791 | Serial.print(TxUdpBuffer[0], HEX); 1792 | for (int i=1; i<4; i++){ 1793 | Serial.print(char(TxUdpBuffer[i])); 1794 | } 1795 | Serial.print(TxUdpBuffer[4], BIN); 1796 | Serial.print(F("|")); 1797 | Serial.print(TxUdpBuffer[5], BIN); 1798 | Serial.print(F("|")); 1799 | Serial.print(TxUdpBuffer[6], BIN); 1800 | Serial.print(char(TxUdpBuffer[7])); 1801 | Serial.print(F("] ")); 1802 | // Serial.print(RemoteSwIP); 1803 | Serial.print(F(":")); 1804 | // Serial.println(RemoteSwPort); 1805 | } 1806 | #endif 1807 | // } 1808 | } 1809 | InterruptON(1); // ptt, enc 1810 | #endif 1811 | } 1812 | //------------------------------------------------------------------------------------------------------- 1813 | 1814 | void EthernetCheck(){ 1815 | #if defined(EthModule) 1816 | if(millis()-EthLinkStatusTimer[0]>EthLinkStatusTimer[1] && EnableEthernet==1){ 1817 | if ((Ethernet.linkStatus() == Unknown || Ethernet.linkStatus() == LinkOFF) && EthLinkStatus==1) { 1818 | EthLinkStatus=0; 1819 | #if defined(SERIAL_debug) 1820 | // if(DEBUG==1){ 1821 | Serial.println(F("Ethernet DISCONNECTED")); 1822 | // } 1823 | #endif 1824 | }else if (Ethernet.linkStatus() == LinkON && EthLinkStatus==0) { 1825 | EthLinkStatus=1; 1826 | #if defined(SERIAL_debug) 1827 | // if(DEBUG==1){ 1828 | Serial.println(F("Ethernet CONNECTED")); 1829 | // } 1830 | #endif 1831 | 1832 | #if defined(LCD) 1833 | lcd.clear(); 1834 | lcd.setCursor(1, 0); 1835 | lcd.print(F("Net-ID: ")); 1836 | lcd.print(NET_ID, HEX); 1837 | lcd.setCursor(1, 1); 1838 | lcd.print(F("[DHCP-")); 1839 | #endif 1840 | if(EnableDHCP==1){ 1841 | #if defined(LCD) 1842 | lcd.print(F("ON]...")); 1843 | #endif 1844 | Ethernet.begin(mac); 1845 | IPAddress CheckIP = Ethernet.localIP(); 1846 | if( CheckIP[0]==0 && CheckIP[1]==0 && CheckIP[2]==0 && CheckIP[3]==0 ){ 1847 | #if defined(LCD) 1848 | lcd.clear(); 1849 | lcd.setCursor(1, 0); 1850 | lcd.print(F("DHCP FAIL")); 1851 | lcd.setCursor(1, 1); 1852 | lcd.print(F("please restart")); 1853 | #endif 1854 | Serial.println(F("DHCP FAIL - please restart")); 1855 | while(1) { 1856 | // infinite loop 1857 | } 1858 | } 1859 | }else{ 1860 | #if defined(LCD) 1861 | lcd.print(F("OFF]")); 1862 | #endif 1863 | // Ethernet.begin(mac, ip, myDns, gateway, subnet); // Fixed IP 1864 | } 1865 | #if defined(LCD) 1866 | delay(2000); 1867 | lcd.clear(); 1868 | lcd.setCursor(1, 0); 1869 | lcd.print(F("IP address:")); 1870 | lcd.setCursor(1, 1); 1871 | lcd.print(Ethernet.localIP()); 1872 | delay(2500); 1873 | lcd.clear(); 1874 | #endif 1875 | Serial.print(F("IP address: ")); 1876 | Serial.println(Ethernet.localIP()); 1877 | Serial.print(F("NET-ID: ")); 1878 | Serial.println(NET_ID, HEX); 1879 | 1880 | // server.begin(); // Web 1881 | UdpCommand.begin(UdpCommandPort); // UDP 1882 | TxUDP(ThisDevice, RemoteDevice, 'b', 'r', 'o'); 1883 | // NeedRxSettings=1; 1884 | } 1885 | EthLinkStatusTimer[0]=millis(); 1886 | } 1887 | #endif 1888 | } 1889 | //--------------------------------------------------------------------------------------------------------- 1890 | byte IdSufix(byte ID){ 1891 | bitClear(ID, 4); 1892 | bitClear(ID, 5); 1893 | bitClear(ID, 6); 1894 | bitClear(ID, 7); 1895 | return(ID); 1896 | } 1897 | //--------------------------------------------------------------------------------------------------------- 1898 | --------------------------------------------------------------------------------