Karl Zweimüller / TMCStepper

Dependents:   TMC2209-Test2

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers TMC2208Stepper.cpp Source File

TMC2208Stepper.cpp

00001 #include "TMCStepper.h"
00002 #include "TMC_MACROS.h"
00003 //#include "SERIAL_SWITCH.h"
00004 
00005 // Protected
00006 // addr needed for TMC2209
00007 TMC2208Stepper::TMC2208Stepper(Stream * SerialPort, float RS, uint8_t addr) :
00008     TMCStepper(RS),
00009     slave_address(addr)
00010     {
00011         HWSerial = SerialPort;
00012         defaults();
00013     }
00014 
00015 TMC2208Stepper::TMC2208Stepper(Stream * SerialPort, float RS, uint8_t addr, uint16_t mul_pin1, uint16_t mul_pin2) :
00016     TMC2208Stepper(SerialPort, RS)
00017     {
00018 //        SSwitch *SMulObj = new SSwitch(mul_pin1, mul_pin2, addr);
00019 //        sswitch = SMulObj;
00020     }
00021 
00022 #if SW_CAPABLE_PLATFORM
00023     // Protected
00024     // addr needed for TMC2209
00025     TMC2208Stepper::TMC2208Stepper(PinName SW_RX_pin, PinName SW_TX_pin, float RS, uint8_t addr) :
00026         TMCStepper(RS),
00027         RXTX_pin(SW_RX_pin == SW_TX_pin ? SW_RX_pin : 0),
00028         slave_address(addr)
00029         {
00030             BufferedSerial *SWSerialObj = new BufferedSerial(SW_TX_pin, SW_RX_pin);
00031             SWSerial = SWSerialObj;
00032             defaults();
00033         }
00034 
00035     void TMC2208Stepper::beginSerial(uint32_t baudrate) {
00036         if (SWSerial != nullptr)
00037         {
00038             //SWSerial->begin(baudrate);
00039             //SWSerial->end();
00040             SWSerial->set_baud(baudrate);
00041             SWSerial->set_format(
00042                         /* bits */ 8,
00043                         /* parity */ BufferedSerial::None,
00044                         /* stop bit */ 1
00045                     );
00046             SWSerial->set_blocking(false);  //set to non-blocking read
00047         }
00048 //        #if defined(ARDUINO_ARCH_AVR)
00049 //            if (RXTX_pin > 0) {
00050 //                digitalWrite(RXTX_pin, HIGH);
00051 //                pinMode(RXTX_pin, OUTPUT);
00052 //           }
00053 //        #endif
00054     }
00055 #endif
00056 
00057 void TMC2208Stepper::begin() {
00058     #if SW_CAPABLE_PLATFORM
00059         beginSerial(115200);
00060         //beginSerial(9600);
00061     #endif
00062     pdn_disable(true);
00063     mstep_reg_select(true);
00064     //Wait to initialize
00065     wait_us(replyDelay*1000);
00066 
00067 }
00068 
00069 void TMC2208Stepper::defaults() {
00070     GCONF_register.i_scale_analog = 1;
00071     GCONF_register.internal_rsense = 0; // OTP
00072     GCONF_register.en_spreadcycle = 0; // OTP
00073     GCONF_register.multistep_filt = 1; // OTP
00074     IHOLD_IRUN_register.iholddelay = 1; // OTP
00075     TPOWERDOWN_register.sr = 20;
00076     CHOPCONF_register.sr = 0x10000053;
00077     PWMCONF_register.sr = 0xC10D0024;
00078   //MSLUT0_register.sr = ???;
00079   //MSLUT1_register.sr = ???;
00080   //MSLUT2_register.sr = ???;
00081   //MSLUT3_register.sr = ???;
00082   //MSLUT4_register.sr = ???;
00083   //MSLUT5_register.sr = ???;
00084   //MSLUT6_register.sr = ???;
00085   //MSLUT7_register.sr = ???;
00086   //MSLUTSTART_register.start_sin90 = 247;
00087 }
00088 
00089 void TMC2208Stepper::push() {
00090     GCONF(GCONF_register.sr);
00091     IHOLD_IRUN(IHOLD_IRUN_register.sr);
00092     SLAVECONF(SLAVECONF_register.sr);
00093     TPOWERDOWN(TPOWERDOWN_register.sr);
00094     TPWMTHRS(TPWMTHRS_register.sr);
00095     VACTUAL(VACTUAL_register.sr);
00096     CHOPCONF(CHOPCONF_register.sr);
00097     PWMCONF(PWMCONF_register.sr);
00098 }
00099 
00100 bool TMC2208Stepper::isEnabled() { return !enn() && toff(); }
00101 
00102 uint8_t TMC2208Stepper::calcCRC(uint8_t datagram[], uint8_t len) {
00103     uint8_t crc = 0;
00104     for (uint8_t i = 0; i < len; i++) {
00105         uint8_t currentByte = datagram[i];
00106         for (uint8_t j = 0; j < 8; j++) {
00107             if ((crc >> 7) ^ (currentByte & 0x01)) {
00108                 crc = (crc << 1) ^ 0x07;
00109             } else {
00110                 crc = (crc << 1);
00111             }
00112             crc &= 0xff;
00113             currentByte = currentByte >> 1;
00114         }
00115     }
00116     return crc;
00117 }
00118 
00119 __attribute__((weak))
00120 int TMC2208Stepper::available() {
00121     int out = 0;
00122     #if SW_CAPABLE_PLATFORM
00123         if (SWSerial != nullptr) {
00124 //            out = SWSerial->available();
00125 out = 1;
00126         } else
00127     #endif
00128         if (HWSerial != nullptr) {
00129 //            out = HWSerial->available();
00130 out = 1;
00131         }
00132 
00133     return out;
00134 }
00135 
00136 __attribute__((weak))
00137 void TMC2208Stepper::preWriteCommunication() {
00138     if (HWSerial != nullptr) {
00139 //        if (sswitch != nullptr)
00140 //            sswitch->active();
00141     }
00142 }
00143 
00144 __attribute__((weak))
00145 void TMC2208Stepper::preReadCommunication() {
00146     #if SW_CAPABLE_PLATFORM
00147         if (SWSerial != nullptr) {
00148 //            SWSerial->listen();
00149         } else
00150     #endif
00151         if (HWSerial != nullptr) {
00152 //            if (sswitch != nullptr)
00153 //                sswitch->active();
00154         }
00155 }
00156 
00157 __attribute__((weak))
00158 int16_t TMC2208Stepper::serial_read() {
00159     int16_t out = 0;
00160     int16_t count = 0;
00161      
00162     #if SW_CAPABLE_PLATFORM
00163         if (SWSerial != nullptr) {
00164 //            out = SWSerial->read();
00165             count = SWSerial->read(&out, 1); // read one character
00166 //            if (SWSerial->readable()) {
00167 //                SWSerial->read(&out, 1); // read one character
00168 //            }
00169 
00170         } else
00171     #endif
00172         if (HWSerial != nullptr) {
00173 //            out = HWSerial->read();
00174             HWSerial->read(&out, 1); // read one character
00175         }
00176     if (count >= 1) {
00177 //       printf("<%02X|",out);
00178        return out;
00179     } else {
00180         return -1;
00181     }
00182 }
00183 
00184 __attribute__((weak))
00185 uint8_t TMC2208Stepper::serial_write(const uint8_t data) {
00186     int out = 0;
00187     #if SW_CAPABLE_PLATFORM
00188         if (SWSerial != nullptr) {
00189 //            printf(">%02X|",data);
00190             return SWSerial->write(&data,1);
00191         } else
00192     #endif
00193         if (HWSerial != nullptr) {
00194             return HWSerial->write(&data,1);
00195         }
00196 
00197     return out;
00198 }
00199 
00200 __attribute__((weak))
00201 void TMC2208Stepper::postWriteCommunication() {}
00202 
00203 __attribute__((weak))
00204 void TMC2208Stepper::postReadCommunication() {
00205     #if SW_CAPABLE_PLATFORM
00206 //        if (SWSerial != nullptr) {
00207 //            SWSerial->end();
00208 //        }
00209     #endif
00210 }
00211 
00212 void TMC2208Stepper::write(uint8_t addr, uint32_t regVal) {
00213     uint8_t len = 7;
00214     addr |= TMC_WRITE;
00215     uint8_t datagram[] = {TMC2208_SYNC, slave_address, addr, (uint8_t)(regVal>>24), (uint8_t)(regVal>>16), (uint8_t)(regVal>>8), (uint8_t)(regVal>>0), 0x00};
00216 
00217     datagram[len] = calcCRC(datagram, len);
00218 
00219     preWriteCommunication();
00220 
00221     for(uint8_t i=0; i<=len; i++) {
00222         bytesWritten += serial_write(datagram[i]);
00223     }
00224     postWriteCommunication();
00225 
00226     //delay(replyDelay);
00227     wait_us(replyDelay*1000);
00228 }
00229 
00230 uint64_t TMC2208Stepper::_sendDatagram(uint8_t datagram[], const uint8_t len, uint16_t timeout) {
00231 
00232 //  while (available() > 0) serial_read(); // Flush
00233     SWSerial->sync();
00234 /*    uint8_t dummy;
00235     while (SWSerial->readable()) {
00236         SWSerial->read(&dummy, 1); // read one character
00237     }
00238 */    
00239 /*    uint8_t dummy;
00240     while (SWSerial->read(&dummy, 1) >= 0) {
00241         ;
00242     }    
00243 */
00244 
00245     #if defined(ARDUINO_ARCH_AVR)
00246         if (RXTX_pin > 0) {
00247             digitalWrite(RXTX_pin, HIGH);
00248             pinMode(RXTX_pin, OUTPUT);
00249         }
00250     #endif
00251 
00252     for(int i=0; i<=len; i++) serial_write(datagram[i]);
00253 
00254     #if defined(ARDUINO_ARCH_AVR)
00255         if (RXTX_pin > 0) {
00256             pinMode(RXTX_pin, INPUT_PULLUP);
00257         }
00258     #endif
00259 
00260     //delay(this->replyDelay);
00261     wait_us(this->replyDelay*1000);
00262 
00263     // scan for the rx frame and read it
00264 
00265 //    uint32_t ms = millis();
00266     uint32_t sync_target = (static_cast<uint32_t>(datagram[0])<<16) | 0xFF00 | datagram[2];
00267     uint32_t sync = 0;
00268     
00269     // 64-bit time doesn't wrap for half a billion years, at least
00270     uint64_t start_ms, now;
00271     start_ms = Kernel::get_ms_count();
00272 
00273 
00274     do {
00275 /*        uint32_t ms2 = millis();
00276         if (ms2 != ms) {
00277             // 1ms tick
00278             ms = ms2;
00279             timeout--;
00280         }
00281         if (!timeout) return 0;
00282 */
00283         // 64-bit time doesn't wrap for half a billion years, at least
00284         now = Kernel::get_ms_count();
00285         if (now - start_ms > timeout) return 0;
00286         
00287         int16_t res = serial_read();
00288         if (res < 0) continue;
00289 
00290         sync <<= 8;
00291         sync |= res & 0xFF;
00292         sync &= 0xFFFFFF;
00293 
00294     } while (sync != sync_target);
00295 
00296     uint64_t out = sync;
00297  //   ms = millis();
00298  //   timeout = this->abort_window;
00299     
00300     start_ms = Kernel::get_ms_count();
00301     
00302     for(uint8_t i=0; i<5;) {
00303 /*        uint32_t ms2 = millis();
00304         if (ms2 != ms) {
00305             // 1ms tick
00306             ms = ms2;
00307             timeout--;
00308         }
00309         if (!timeout) return 0;
00310 */
00311         now = Kernel::get_ms_count();
00312         if (now - start_ms > timeout) return 0;
00313         
00314         int16_t res = serial_read();
00315         if (res < 0) continue;
00316 
00317         out <<= 8;
00318         out |= res & 0xFF;
00319 
00320         i++;
00321     }
00322 
00323     #if defined(ARDUINO_ARCH_AVR)
00324         if (RXTX_pin > 0) {
00325             digitalWrite(RXTX_pin, HIGH);
00326             pinMode(RXTX_pin, OUTPUT);
00327         }
00328     #endif
00329 
00330 //    while (available() > 0) serial_read(); // Flush
00331     SWSerial->sync();
00332 
00333     return out;
00334 
00335 
00336 }
00337 
00338 uint32_t TMC2208Stepper::read(uint8_t addr) {
00339     constexpr uint8_t len = 3;
00340     addr |= TMC_READ;
00341     uint8_t datagram[] = {TMC2208_SYNC, slave_address, addr, 0x00};
00342     datagram[len] = calcCRC(datagram, len);
00343     uint64_t out = 0x00000000UL;
00344 
00345     for (uint8_t i = 0; i < max_retries; i++) {
00346         preReadCommunication();
00347         out = _sendDatagram(datagram, len, abort_window);
00348         postReadCommunication();
00349 
00350 //        delay(replyDelay);
00351 //        wait_us(replyDelay*1000);
00352 
00353         CRCerror = false;
00354         uint8_t out_datagram[] = {
00355             static_cast<uint8_t>(out>>56),
00356             static_cast<uint8_t>(out>>48),
00357             static_cast<uint8_t>(out>>40),
00358             static_cast<uint8_t>(out>>32),
00359             static_cast<uint8_t>(out>>24),
00360             static_cast<uint8_t>(out>>16),
00361             static_cast<uint8_t>(out>> 8),
00362             static_cast<uint8_t>(out>> 0)
00363         };
00364         uint8_t crc = calcCRC(out_datagram, 7);
00365         if ((crc != static_cast<uint8_t>(out)) || crc == 0 ) {
00366             CRCerror = true;
00367             out = 0;
00368         } else {
00369             break;
00370         }
00371     }
00372 
00373     return out>>8;
00374 }
00375 
00376 uint8_t TMC2208Stepper::IFCNT() {
00377     return read(IFCNT_t::address);
00378 }
00379 
00380 void TMC2208Stepper::SLAVECONF(uint16_t input) {
00381     SLAVECONF_register.sr = input&0xF00;
00382     write(SLAVECONF_register.address, SLAVECONF_register.sr);
00383 }
00384 uint16_t TMC2208Stepper::SLAVECONF() {
00385     return SLAVECONF_register.sr;
00386 }
00387 void TMC2208Stepper::senddelay(uint8_t B)   { SLAVECONF_register.senddelay = B; write(SLAVECONF_register.address, SLAVECONF_register.sr); }
00388 uint8_t TMC2208Stepper::senddelay()         { return SLAVECONF_register.senddelay; }
00389 
00390 void TMC2208Stepper::OTP_PROG(uint16_t input) {
00391     write(OTP_PROG_t::address, input);
00392 }
00393 
00394 uint32_t TMC2208Stepper::OTP_READ() {
00395     return read(OTP_READ_t::address);
00396 }
00397 
00398 uint32_t TMC2208Stepper::IOIN() {
00399     return read(TMC2208_n::IOIN_t::address);
00400 }
00401 bool TMC2208Stepper::enn()          { TMC2208_n::IOIN_t r{0}; r.sr = IOIN(); return r.enn;      }
00402 bool TMC2208Stepper::ms1()          { TMC2208_n::IOIN_t r{0}; r.sr = IOIN(); return r.ms1;      }
00403 bool TMC2208Stepper::ms2()          { TMC2208_n::IOIN_t r{0}; r.sr = IOIN(); return r.ms2;      }
00404 bool TMC2208Stepper::diag()         { TMC2208_n::IOIN_t r{0}; r.sr = IOIN(); return r.diag;     }
00405 bool TMC2208Stepper::pdn_uart()     { TMC2208_n::IOIN_t r{0}; r.sr = IOIN(); return r.pdn_uart; }
00406 bool TMC2208Stepper::step()         { TMC2208_n::IOIN_t r{0}; r.sr = IOIN(); return r.step;     }
00407 bool TMC2208Stepper::sel_a()        { TMC2208_n::IOIN_t r{0}; r.sr = IOIN(); return r.sel_a;    }
00408 bool TMC2208Stepper::dir()          { TMC2208_n::IOIN_t r{0}; r.sr = IOIN(); return r.dir;      }
00409 uint8_t TMC2208Stepper::version()   { TMC2208_n::IOIN_t r{0}; r.sr = IOIN(); return r.version;  }
00410 
00411 /*
00412 uint32_t TMC2224Stepper::IOIN() {
00413     return read(TMC2224_n::IOIN_t::address);
00414 }
00415 bool TMC2224Stepper::enn()          { TMC2224_n::IOIN_t r{0}; r.sr = IOIN(); return r.enn;      }
00416 bool TMC2224Stepper::ms1()          { TMC2224_n::IOIN_t r{0}; r.sr = IOIN(); return r.ms1;      }
00417 bool TMC2224Stepper::ms2()          { TMC2224_n::IOIN_t r{0}; r.sr = IOIN(); return r.ms2;      }
00418 bool TMC2224Stepper::pdn_uart()     { TMC2224_n::IOIN_t r{0}; r.sr = IOIN(); return r.pdn_uart; }
00419 bool TMC2224Stepper::spread()       { TMC2224_n::IOIN_t r{0}; r.sr = IOIN(); return r.spread;   }
00420 bool TMC2224Stepper::step()         { TMC2224_n::IOIN_t r{0}; r.sr = IOIN(); return r.step;     }
00421 bool TMC2224Stepper::sel_a()        { TMC2224_n::IOIN_t r{0}; r.sr = IOIN(); return r.sel_a;    }
00422 bool TMC2224Stepper::dir()          { TMC2224_n::IOIN_t r{0}; r.sr = IOIN(); return r.dir;      }
00423 uint8_t TMC2224Stepper::version()   { TMC2224_n::IOIN_t r{0}; r.sr = IOIN(); return r.version;  }
00424 */
00425 uint16_t TMC2208Stepper::FACTORY_CONF() {
00426     return read(FACTORY_CONF_register.address);
00427 }
00428 void TMC2208Stepper::FACTORY_CONF(uint16_t input) {
00429     FACTORY_CONF_register.sr = input;
00430     write(FACTORY_CONF_register.address, FACTORY_CONF_register.sr);
00431 }
00432 void TMC2208Stepper::fclktrim(uint8_t B){ FACTORY_CONF_register.fclktrim = B; write(FACTORY_CONF_register.address, FACTORY_CONF_register.sr); }
00433 void TMC2208Stepper::ottrim(uint8_t B)  { FACTORY_CONF_register.ottrim = B; write(FACTORY_CONF_register.address, FACTORY_CONF_register.sr); }
00434 uint8_t TMC2208Stepper::fclktrim()      { FACTORY_CONF_t r{0}; r.sr = FACTORY_CONF(); return r.fclktrim; }
00435 uint8_t TMC2208Stepper::ottrim()        { FACTORY_CONF_t r{0}; r.sr = FACTORY_CONF(); return r.ottrim; }
00436 
00437 void TMC2208Stepper::VACTUAL(uint32_t input) {
00438     VACTUAL_register.sr = input;
00439     write(VACTUAL_register.address, VACTUAL_register.sr);
00440 }
00441 uint32_t TMC2208Stepper::VACTUAL() {
00442     return VACTUAL_register.sr;
00443 }
00444 
00445 uint32_t TMC2208Stepper::PWM_SCALE() {
00446     return read(TMC2208_n::PWM_SCALE_t::address);
00447 }
00448 uint8_t TMC2208Stepper::pwm_scale_sum() {
00449     TMC2208_n::PWM_SCALE_t r{0};
00450     r.sr = PWM_SCALE();
00451     return r.pwm_scale_sum;
00452 }
00453 
00454 int16_t TMC2208Stepper::pwm_scale_auto() {
00455     TMC2208_n::PWM_SCALE_t r{0};
00456     r.sr = PWM_SCALE();
00457     return r.pwm_scale_auto;
00458     // Not two's complement? 9nth bit determines sign
00459     /*
00460     uint32_t d = PWM_SCALE();
00461     int16_t response = (d>>PWM_SCALE_AUTO_bp)&0xFF;
00462     if (((d&PWM_SCALE_AUTO_bm) >> 24) & 0x1) return -response;
00463     else return response;
00464     */
00465 }
00466 
00467 // R: PWM_AUTO
00468 uint32_t TMC2208Stepper::PWM_AUTO() {
00469     return read(PWM_AUTO_t::address);
00470 }
00471 uint8_t TMC2208Stepper::pwm_ofs_auto()  { PWM_AUTO_t r{0}; r.sr = PWM_AUTO(); return r.pwm_ofs_auto; }
00472 uint8_t TMC2208Stepper::pwm_grad_auto() { PWM_AUTO_t r{0}; r.sr = PWM_AUTO(); return r.pwm_grad_auto; }