Jump to content

sq7bti

Members
  • Content Count

    24
  • Joined

  • Last visited

  • Days Won

    5

Everything posted by sq7bti

  1. Follow-up in https://hackaday.io/project/9268-telescope-controller s.
  2. Hi @@simpleavr, You might try to hand pick values from wider window, but here are Hamming windows size 16 (mind the symmetry): // round(255 * window('kr',16,6)) //const unsigned char hamming[8] = ( 4, 18, 46, 86, 136, 187, 228, 252); //, 252, 228, 187, 136, 86, 46, 18, 4 ); // round(255 * window('kr',16,4)) const unsigned char hamming[8] = ( 23, 51, 88, 130, 172, 210, 238, 253); //, 253, 238, 210, 172, 130, 88, 51, 23 ); // round(255 * window('kr',16,2)) //const unsigned char hamming[8] = ( 112, 141, 170, 196, 218, 236, 248, 254); //, 254, 248, 236, 218, 196, 170, 141, 112 ); More information regarding window function you will find in Scilab help. S.
  3. Hi, Having a nice matrix led display laying around with no use of I assembled a test circuit with launchpad and modified the code of @simpleavr to run on it. The display is driven by four MAX7219 chips chained on SPI bus. I noticed that the only floating point operation that your code was using is a square root operation in line 257. Once I added a fixed-point square root routine, linking with math lib is not necessary anymore - spared a lot of flash space. The fixed-point routine is also 3 times faster than mathlib floating point one: 50us vs 150us #ifdef FLOATING_POINT // sqrt: 150us #include <math.h> #else // FLOATING_POINT // 50us unsigned char sqrt16(unsigned short a) { unsigned short rem = 0, root = 0; int i; for(i = 0; i < 8; ++i) { root <<= 1; rem = ((rem << 2) + (a >> 14)); a <<= 2; ++root; if(root <= rem) { rem -= root; ++root; } else { --root; } } return (unsigned char)(root >> 1); } #endif // FLOATING_POINT Further I've added Hamm windowing to minimize spectral leakage: // scilab 255 * window('kr',64,6) //const unsigned short hamming[32] = { 4, 6, 9, 13, 17, 23, 29, 35, 43, 51, 60, 70, 80, 91, 102, 114, 126, 138, 151, 163, 175, 187, 198, 208, 218, 227, 234, 241, 247, 251, 253, 255 }; // scilab 255 * window('kr',64,4) const unsigned short hamming[32] = { 23, 29, 35, 42, 50, 58, 66, 75, 84, 94, 104, 113, 124, 134, 144, 154, 164, 174, 183, 192, 201, 210, 217, 224, 231, 237, 242, 246, 250, 252, 254, 255 }; // scilab 255 * window('kr',64,2) //const unsigned short hamming[32] = { 112, 119, 126, 133, 140, 147, 154, 161, 167, 174, 180, 186, 192, 198, 204, 209, 214, 219, 224, 228, 232, 236, 239, 242, 245, 247, 250, 251, 253, 254, 255, 255 }; Applying windowing on 32 samples uses fixed point math: for (i=0;i<Nx;i++) { int hamm = hamming[i<(FFT_SIZE-1)?i:(Nx-1)-i] * data[i]; data[i] = (hamm >> 8); } Finally the display buffer is filled in with output of FFT function: unsigned long mask = 1UL; for (i=0; i<32; ++i, mask <<= 1) { for(j=0;j<8;++j) { if(j<plot[i]) dbuff.ulongs[j] |= mask; else dbuff.ulongs[j] &= ~(mask); } } where dbuff is display buffer organized as: typedef union { unsigned long longs; unsigned int ints[2]; unsigned char chars[4]; } longbytes; union { unsigned char bytes[8*4]; longbytes lbytes[8]; unsigned long ulongs[8]; } dbuff; which make it easy to manipulate: unsigned char spibuff[8]; void SPI_Write(unsigned char* array) { P2OUT &= ~LED_CS; __delay_cycles(50); unsigned int h = 8; while(h) { UCB0TXBUF = *array; while (UCB0STAT & UCBUSY); ++array; --h; } P2OUT |= LED_CS; } void update_display() { unsigned char i; for(i = 0; i < 8; ++i) { spibuff[0] = spibuff[2] = spibuff[4] = spibuff[6] = i+1; spibuff[1] = dbuff.lbytes[i].chars[3]; spibuff[3] = dbuff.lbytes[i].chars[2]; spibuff[5] = dbuff.lbytes[i].chars[1]; spibuff[7] = dbuff.lbytes[i].chars[0]; SPI_Write(spibuff); } } BTW I got a second 8x32 led matrix displays from the same ebay offer, and it turned out to be mirrored - LED matrix is turned around 180deg, so the update_display() routine for the other one have to push bytes in order 0 through 3, and bit-shift operations ( << and >> ) yield opposite display reaction (left vs right scroll). https://youtu.be/Nen6yd5kvZs s. Edit: correct photo attachement and source code snippets led_fft.tar.bz2
  4. Gratis verzending: http://tweakers.net/pricewatch/473997/raspberry-pi-zero.html s.
  5. Formulas for US and EU beginnings and endings of DST: For the United States: Begin DST: Sunday April (2+6*y-y/4) mod 7+1 End DST: Sunday October (31-(y*5/4+1) mod 7) Valid for years 1900 to 2006, though DST wasn't adopted until the 1950s-1960s. 2007 and after: Begin DST: Sunday March 14 - (1 + y*5/4) mod 7 End DST: Sunday November 7 - (1 + y*5/4) mod 7; European Economic Community: Begin DST: Sunday March (31 - (5*y/4 + 4) mod 7) at 1h U.T. End DST: Sunday October (31 - (5*y/4 + 1) mod 7) at 1h U.T. Since 1996, valid through 2099 (Equations by Wei-Hwa Huang (US), and Robert H. van Gent (EC)) taken from http://www.webexhibits.org/daylightsaving/i.html
  6. Thanks for your input. BTW, Regarding the timer used by other libraries I also discovered why I had problems with Timer1: there was a conflict because in my project I am using pin PF_3 for PWM generation with analogWrite(). Perhaps it would be even more flexible yet safe to allow selecting (with begin() method) a specific timer instead of choosing timers one by one from the list of hard-coded list of available ones.
  7. Hi again, I improved the code further: the driverlib calls were replaced with direct HWREG() writes and reads. I found the timer1 unreliable - as far as I can see it is not used for anything else, and when used for triggering steps it is "stuck" after a while. So far I was not able to find the root-cause of this problem - it is only apparent with timer1 - not with the two remaining timers 2 and 3. https://github.com/sq7bti/iAccelStepper iAccelStepper.h #ifndef iAccelStepper_h #define iAccelStepper_h #include <Energia.h> #include "AccelStepper.h" #include "driverlib/sysctl.h" #define MAX_INST 2 //***************************************************************************** // // The list of Timer peripherals. // //***************************************************************************** static const unsigned long g_ulTIMERPeriph[MAX_INST] = { #if defined(PART_TM4C1233H6PM) || defined(PART_LM4F120H5QR) // SYSCTL_PERIPH_TIMER0, // wiring_analog.c analogWrite() // SYSCTL_PERIPH_TIMER1, SYSCTL_PERIPH_TIMER2, SYSCTL_PERIPH_TIMER3 // SYSCTL_PERIPH_TIMER4, // Tone.c // SYSCTL_PERIPH_TIMER5, // wiring.c - millis() micros() // SYSCTL_PERIPH_TIMER6, // SYSCTL_PERIPH_TIMER7 #else #error "**** No PART defined or unsupported PART ****" #endif }; static const unsigned long g_ulTIMERBase[MAX_INST] = { #if defined(PART_TM4C1233H6PM) || defined(PART_LM4F120H5QR) // TIMER0_BASE, // wiring_analog.c analogWrite() // TIMER1_BASE, TIMER2_BASE, TIMER3_BASE // TIMER4_BASE, // Tone.c // TIMER5_BASE, // wiring.c - millis() micros() // TIMER6_BASE, // TIMER7_BASE #else #error "**** No PART defined or unsupported PART ****" #endif }; class iAccelStepper : public AccelStepper { public: iAccelStepper() : AccelStepper() {}; void begin(uint8_t pin1 = 2, uint8_t pin2 = 3, uint8_t pin3 = 4); void moveTo(long absolute); void move(long relative); boolean run(void) { return running; }; unsigned long stepInterval() { return _stepInterval; }; void ISR(void); private: volatile boolean running; unsigned int id; }; #endif iAccelStepper.cpp #include "iAccelStepper.h" #include "driverlib/timer.h" #include "inc/hw_gpio.h" #include "inc/hw_timer.h" static iAccelStepper* me[MAX_INST]; static uint32_t _port_step[MAX_INST]; static uint8_t _pin_step[MAX_INST]; static uint32_t _port_dir[MAX_INST]; static uint8_t _pin_dir[MAX_INST]; static boolean direction[MAX_INST]; static boolean _state[MAX_INST]; static unsigned char all_instances; static uint32_t ulPeriod; void iAccelStepper::ISR(void) { //TimerIntClear(g_ulTIMERBase[id], TIMER_TIMA_TIMEOUT); HWREG(g_ulTIMERBase[id] + TIMER_O_ICR) = TIMER_TIMA_TIMEOUT; // falling edge produce space for length _stepInterval if(_state[id]) { _state[id] = false; // prepare for the next period // falling edge - calculate everything necessary and calculate _stepInterval computeNewSpeed(); if(direction[id] != _direction) { direction[id] = _direction; HWREG(_port_dir[id]) = _direction?_pin_dir[id]:0; } HWREG(_port_step[id]) = 0; //TimerLoadSet(g_ulTIMERBase[id], TIMER_A, _stepInterval - ulPeriod); HWREG(g_ulTIMERBase[id] + TIMER_O_TAILR) = _stepInterval - ulPeriod; //TimerEnable(g_ulTIMERBase[id], TIMER_A); HWREG(g_ulTIMERBase[id] + TIMER_O_CTL) |= TIMER_A & (TIMER_CTL_TAEN | TIMER_CTL_TBEN); } else { // either fire the timer again for another period or switch it off when the move is finished if((_stepInterval == 0) || (abs(distanceToGo()) < 1)) { //TimerDisable(g_ulTIMERBase[id], TIMER_A); HWREG(g_ulTIMERBase[id] + TIMER_O_CTL) &= ~(TIMER_A & (TIMER_CTL_TAEN | TIMER_CTL_TBEN)); running = false; } else { _state[id] = true; if(_direction == DIRECTION_CW) // Clockwise ++_currentPos; else // Anticlockwise --_currentPos; //TimerLoadSet(g_ulTIMERBase[id], TIMER_A, ulPeriod); HWREG(g_ulTIMERBase[id] + TIMER_O_TAILR) = ulPeriod; HWREG(_port_step[id]) = _pin_step[id]; //TimerEnable(g_ulTIMERBase[id], TIMER_A); HWREG(g_ulTIMERBase[id] + TIMER_O_CTL) |= TIMER_A & (TIMER_CTL_TAEN | TIMER_CTL_TBEN); } } } void timerISR0(void) { me[0]->ISR(); } void timerISR1(void) { me[1]->ISR(); } //void timerISR2(void) { me[2]->ISR(); } //void timerISR3(void) { me[3]->ISR(); } //void timerISR4(void) { me[4]->ISR(); } typedef void (*ISR_ptr_t)(void); //ISR_ptr_t timerISR_ptr[5] = { &timerISR0, &timerISR1, timerISR2, timerISR3, timerISR4 }; ISR_ptr_t timerISR_ptr[MAX_INST] = { timerISR0, timerISR1 }; void iAccelStepper::begin(uint8_t pin1, uint8_t pin2, uint8_t pin3) { // STEP DIR AccelStepper::begin(AccelStepper::DRIVER, pin1, pin2); // ENABLE AccelStepper::setEnablePin(pin3); AccelStepper::setPinsInverted(false, false, true); // specs of DRV8825 requires 2us, A3967 and A4988 requires atleast 1us step pulse // ulPeriod = clockCyclesPerMicrosecond() * 2; ulPeriod = 1; if(all_instances < MAX_INST) { id = all_instances; // Configure timer SysCtlPeripheralEnable(g_ulTIMERPeriph[id]); TimerConfigure(g_ulTIMERBase[id], TIMER_CFG_ONE_SHOT); //TimerIntEnable(g_ulTIMERBase[id], TIMER_TIMA_TIMEOUT); HWREG(g_ulTIMERBase[id] + TIMER_O_IMR) |= TIMER_TIMA_TIMEOUT; TimerIntRegister(g_ulTIMERBase[id], TIMER_A, timerISR_ptr[id]); me[id] = this; running = false; ++all_instances; _port_step[id] = (uint32_t)portBASERegister(digitalPinToPort(pin1)) + (GPIO_O_DATA + (digitalPinToBitMask(pin1) << 2)); _pin_step[id] = (uint8_t)digitalPinToBitMask(pin1); _port_dir[id] = (uint32_t)portBASERegister(digitalPinToPort(pin2)) + (GPIO_O_DATA + (digitalPinToBitMask(pin2) << 2)); _pin_dir[id] = (uint8_t)digitalPinToBitMask(pin2); direction[id] = false; _state[id] = false; } } void iAccelStepper::move(long relative) { moveTo(_currentPos + relative); } void iAccelStepper::moveTo(long absolute) { AccelStepper::moveTo(absolute); if(!running && (distanceToGo() != 0)) { running = true; computeNewSpeed(); if(direction[id] != _direction) { direction[id] = _direction; HWREG(_port_dir[id]) = _direction?_pin_dir[id]:0; } HWREG(_port_step[id]) = 0; _state[id] = false; //TimerLoadSet(g_ulTIMERBase[id], TIMER_A, _stepInterval - ulPeriod); HWREG(g_ulTIMERBase[id] + TIMER_O_TAILR) = _stepInterval - ulPeriod; //TimerEnable(g_ulTIMERBase[id], TIMER_A); HWREG(g_ulTIMERBase[id] + TIMER_O_CTL) |= TIMER_A & (TIMER_CTL_TAEN | TIMER_CTL_TBEN); } } Inheritance prerequisites remains as described in previous post. Remarks welcome. With kind regards, Szymon /EDIT: added github
  8. Progress: A summary of changes: instead of unipolar motor drivers, now I used a bipolar drivers very popular in RepRap projects, here A4988 (or DRV8825) 28byj-48 modified for bipolar cheap HC-05 for bluetooth SPP GPS module U-blox NEO-6m added RTC DS1307 to provide date/time reference even in the first seconds after power-on and 56 of NVRAM bytes added (optional) humidity and temperature sensor DSTH01 added a I2C socket to connect external temperature sensors to provide information about motors temperatures added PCF8574 for microstepping configuration of A4988 drivers added buzzer for audible indication added output for 12Vdc fan of main mirror - PWM controlled Nokia 5110 display replaced with a red back-light As the software is concerned, there were several improvements as well. The most important is that the motors are now driven by an interrupt driven AccelStepper With kind regards, Szymon
  9. Check with a digital probe an order of sequence the motor is excited. If improper, the rotor would shake instead of turning. The same would happen if the wiring is incorrect. You might also try swapping motor wires, if you are not sure what order they should be. What motor are you using, by the way? Yet another option is that the timing is incorrect: try lowering the motor speed and acceleration. s.
  10. What motor driver chip are you using? What AccelStepper::MotorInterfaceType did you specify? s.
  11. What specifically didn't work? Compilation error? Unexpected behaviour? S.
  12. I got it all up and running with 1307, just as I wrote: Vbus as supply (5V) and with 3.3V on pullup i2c resistors. PCF is not available in DIP, while DS1307 is. Thanks for the hint anyway. Addendum: Besides, the DS1307 features an NVRAM. Comes handy for the project I am working on right now: newtonian telescope controller: store mount specific configuration instead of compile-in.
  13. The first four looks like some web-mail referenced links. Just take a look at the beginning: https://mail.jbu.edu/owa/redir.aspx?C=f89ce17e5c8847cea19d0f2fb00cbfae&URL=http%3A%2F%2Fwww.ebay.com%2Fitm%2F10DOF-IMU-HMC5883L-ITG3205-BMA180-BMP085-Sensor-Module-For-MWC-Arduino-%2F321180164174%3Fpt%3DLH_DefaultDomain_0%26hash%3Ditem4ac7d4604e Great project by the way. s.
  14. Thank you Stendall. It helped a lot. In my case there was another issue caused by the following feature i overlooked: (page 6 of DS1307): Upon power-up, the device switches from battery to VCC when VCC is greater than VBAT +0.2V and recognizes inputs when VCC is greater than 1.25 x VBAT. The chip was responding correctly when powered from launchpad 3.3V bus, even though nominally it is 5V device, but played dead when 3V battery was connected to it at the same time. DS1307 is fine when powered from 5V, with SDA and SCL pulled up from 3.3V. s.
  15. It is indeed true for i2c-scanners as far as I can see in the code: uint8_t TwoWire::endTransmission(uint8_t sendStop) { uint8_t error = I2C_MASTER_ERR_NONE; if(TX_BUFFER_EMPTY) return 0; //Wait for any previous transaction to complete while(ROM_I2CMasterBusBusy(MASTER_BASE)); while(ROM_I2CMasterBusy(MASTER_BASE)); //Select which slave we are requesting data from //false indicates we are writing to the slave ROM_I2CMasterSlaveAddrSet(MASTER_BASE, txAddress, false); while(ROM_I2CMasterBusy(MASTER_BASE)); unsigned long cmd = RUN_BIT | START_BIT; error = sendTxData(cmd,txBuffer[txReadIndex]); txReadIndex = (txReadIndex + 1) % BUFFER_LENGTH; if(error) return error; while(!TX_BUFFER_EMPTY) { error = sendTxData(RUN_BIT,txBuffer[txReadIndex]); txReadIndex = (txReadIndex + 1) % BUFFER_LENGTH; if(error) return getError(error); } if(sendStop) { while(ROM_I2CMasterBusy(MASTER_BASE)); HWREG(MASTER_BASE + I2C_O_MCS) = STOP_BIT; while(ROM_I2CMasterBusy(MASTER_BASE)); currentState = IDLE; } else { currentState = MASTER_TX; } // indicate that we are done transmitting transmitting = 0; return error; } endTranmission returns null (line 5) in a typical scanner attempt to trigger a slave with beginTransmission and entail it with immediate endTransmission. Shouldn't there be an actual check for the ACK to give a status back of the device responding or not? s.
  16. Hi Stendall, Would you please explain how did you solve your problem with I2C? I guess I tried all suggested solutions in this (and other) threads, including: - checking with other modules - different combinations of initializations, setModule statements, and begin() - checking with lower Rpu (according to the philips document it should be approx 1kΩ My conclusion is that no matter which module I use I get always get 0 (null) back from endTransmission(), no matter if there is ACK or not. That makes the detection of I2C failed transaction wrong: i2csdetect erroneously detect a device under each scanned address: Scanning: ..................................................................................................................... 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 01: 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 02: 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 03: 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 04: 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 05: 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f 06: 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 07: 70 71 72 73 74 75 76 77 My logic analyzer is showing the following traffic during execution of i2cdetect: This is identical for each and every module I tried. I did not try though with another I2C master - such as AVR arduino or such. s. i2cdetect.txt
  17. I decided not to start another thread, because what I am about to present here is actually my attempt to port AccelStepper library to LM4F. Specifically my port makes use of the timer interrupts to schedule stepping, instead of using polled fashion execution of run() method. I used the AccelStepper source code revision 1.39 and I had to move around number of members from private to public: _stepInterval _direction _currentPos _targetPos _speed _pin[4] Modified AccelStepper can be used for inheritance. It is limited to the DRIVER variant, but can be easily extended with FULL4WIRE, HALF4WIRE and others. iAccelStepper.h: #ifndef iAccelStepper_h #define iAccelStepper_h #include <Energia.h> #include "AccelStepper.h" #include "driverlib/sysctl.h" //***************************************************************************** // // The list of Timer peripherals. // //***************************************************************************** static const unsigned long g_ulTIMERPeriph[3] = { #if defined(PART_TM4C1233H6PM) || defined(PART_LM4F120H5QR) // SYSCTL_PERIPH_TIMER0, // wiring_analog.c analogWrite() SYSCTL_PERIPH_TIMER1, SYSCTL_PERIPH_TIMER2, SYSCTL_PERIPH_TIMER3 // SYSCTL_PERIPH_TIMER4, // Tone.c // SYSCTL_PERIPH_TIMER5, // wiring.c - millis() micros() // SYSCTL_PERIPH_TIMER6, // SYSCTL_PERIPH_TIMER7 #else #error "**** No PART defined or unsupported PART ****" #endif }; static const unsigned long g_ulTIMERBase[3] = { #if defined(PART_TM4C1233H6PM) || defined(PART_LM4F120H5QR) // TIMER0_BASE, // wiring_analog.c analogWrite() TIMER1_BASE, TIMER2_BASE, TIMER3_BASE // TIMER4_BASE, // Tone.c // TIMER5_BASE, // wiring.c - millis() micros() // TIMER6_BASE, // TIMER7_BASE #else #error "**** No PART defined or unsupported PART ****" #endif }; class iAccelStepper : public AccelStepper { public: iAccelStepper() : AccelStepper() {}; void begin(uint8_t pin1 = 2, uint8_t pin2 = 3); void moveTo(long absolute); void move(long relative); boolean run(void) { return running; }; void ISR(void); private: boolean running; unsigned int id; }; #endif iAccelStepper.cpp: #include "iAccelStepper.h" #include "driverlib/timer.h" volatile boolean state[3]; static iAccelStepper* me[3]; static unsigned int all_instances; void iAccelStepper::ISR(void) { TimerIntClear(g_ulTIMERBase[id], TIMER_TIMA_TIMEOUT); if(state[id]) { if(_direction == DIRECTION_CW) // Clockwise ++_currentPos; else // Anticlockwise --_currentPos; // prepare for the next period computeNewSpeed(); digitalWrite(_pin[1], _direction); TimerLoadSet(g_ulTIMERBase[id], TIMER_A, 1); TimerEnable(g_ulTIMERBase[id], TIMER_A); } else { // switch off timer at the falling edge if(_stepInterval == 0) { TimerDisable(g_ulTIMERBase[id], TIMER_A); running = false; } else { TimerLoadSet(g_ulTIMERBase[id], TIMER_A, (80*_stepInterval)-1); TimerEnable(g_ulTIMERBase[id], TIMER_A); } } digitalWrite(_pin[0], state[id]); state[id] ^= 1; } void timerISR0(void) { me[0]->ISR(); } void timerISR1(void) { me[1]->ISR(); } void timerISR2(void) { me[2]->ISR(); } //void timerISR3(void) { me[3]->ISR(); } //void timerISR4(void) { me[4]->ISR(); } typedef void (*ISR_ptr_t)(void); //ISR_ptr_t timerISR_ptr[5] = { timerISR0, timerISR1, timerISR2, timerISR3, timerISR4 }; ISR_ptr_t timerISR_ptr[3] = { timerISR0, timerISR1, timerISR2 }; void iAccelStepper::begin(uint8_t pin1, uint8_t pin2) { // STEP DIR AccelStepper::begin(AccelStepper::DRIVER, pin1, pin2); if(all_instances < 3) { id = all_instances; // Configure timer SysCtlPeripheralEnable(g_ulTIMERPeriph[id]); TimerConfigure(g_ulTIMERBase[id], TIMER_CFG_ONE_SHOT); TimerIntEnable(g_ulTIMERBase[id], TIMER_TIMA_TIMEOUT); TimerIntRegister(g_ulTIMERBase[id], TIMER_A, timerISR_ptr[id]); me[id] = this; state[id] = false; running = false; ++all_instances; } } void iAccelStepper::move(long relative) { moveTo(_currentPos + relative); } void iAccelStepper::moveTo(long absolute) { AccelStepper::moveTo(absolute); if(!running && (distanceToGo() != 0)) { digitalWrite(_pin[1], _direction); computeNewSpeed(); state[id] = true; digitalWrite(_pin[0], state[id]); running = true; TimerLoadSet(g_ulTIMERBase[id], TIMER_A, 1); TimerEnable(g_ulTIMERBase[id], TIMER_A); } } Comments are welcome, especially on the usage of other timers: there are only 3 left as far as I can see. Szymon
  18. Hello again, The hardware can be easily described with pin assignment, as most of the connections are straight forward: Software on the other hand comprises of the following modules: GPS - NMEA stream is parsed by TinyGPS++ LCD facilitated by SPI Sidereal time calculation - header file holds the Sidereal time for midnight each day precalculated to optimize execution AxesLib with help of AccelStepper provides interface to drive the mount around in azimuth and altitude coordinates, but also during start-up performs homing and calibration of mount (play estimation), CoordsLib performs transformation from and to equatorial coordinates using Taki matrix transformation PS - interrupt driven ps/2 handler - configures mouse hardware to provide incremental position information - unfortunately does not provide high resolution when compared to stepper motor movement, stars is using brightest stars from hygxyz.h for the three star alignment procedure during start-up. After that star library and messier object library is used to identify interesting object in view, LX200 implements communication protocol with all commands utilized by Stellarium, and most of the commands of Autostar protocol (Meade) scopectrl.tar.bz2 With kind regards, Szymon
  19. When powered on, the mount moves to the first alignment star. Then, a user provides the correction vector: star just needs to be positioned in the middle of view in eyepiece. First star roughly corrects the misalignment in telescope orientation w.r.t. the north. Second star helps to correct also the leveling error. Third star would improve alignment even further. I did not (yet) implement any periodic error correction. The whole alignment procedure takes couple of minutes, and requires a user to center stars in an eyepiece with an attached joystick, and confirm with fire button. GPS resolves the time/date and location issue during start-up in unknown location. with kind regards, Szymon
  20. Hello everyone, There is a couple of similar projects available on the internet. Some of them base on Arduino and PIC performs very basic mount control without math intensive computation implemented in embedded controller. I decided to build my own with the following goals: ease of use by an inexperienced amateur astronomer (full automatic operation) precision and resolution of position last but not least: the price Final, or better say at the moment, design comprises of the following components: Stellaris LM4F launchpad central control unit, two ULN2003 unipolar stepper motor driver chips, two 28byj-48 stepper motors one moving in azimuth, and in elevation via gear train, communication module: Bluetooth serial module. It allows sending a coordinate set-point and provides position feedback to Stellarium, GPS module providing position and precise time reference - PPS gives 1us accuracy, Nokia 5110 display unit and joystick for standalone operation, now obsolete mouse (PS/2) modified to provide independent (incremental) position information Resolution that was reached is a single step of approx. 5". Given the size of Jupiter to range from 30" to 50", this positioning resolution makes the view comfortably stable in standard 60° FOV eyepiece at reasonably high magnification, without the need to adjust AZ/ALT continuously. During the development I made use of several opensource and projects available online, namely: AccelStepper for stepper control, TinyGPS++ for NMEA decoding, Arduino telescope controller was my inspiration and reference for Taki's matrix method for coordinates transformation, of course Energia as my IDE Upon power-up the mount is performing: homing acquisition of current location (longitude/latitude) and time via NMEA stream moves to 3 brightest (most convenient) stars in succession to perform 3 star alignment procedure - they are selected from the list of over 500 stars in built-in catalog (the brightest are used for the alignment, tough), once aligned the mount is in tracking mode: it tracks the view to counter the apparent movement of objects in the sky, waiting, either for the user to move to particular object - selected from the library of stars and Messier objects, or awaits connection via Bluetooth from a PC running Stellarium with a plugin and slews to selected object. search for the object that should be visible in the eyepiece and display important information on LCD - I compiled in 500 brightest stars from HYGXYZ and full Messier catalog. I have very little experience as amateur astronomer so far, so some of the objectives might have been not very obvious for me in the beginning. This project was also a good way to make use of my free time and gain experience in embedded system design. With kind regards, Szymon
  21. I had similar problem. Perhaps it only worked for me, but you might try the same, so we could verify and that would give some hints to the developers: Rename constructor to a method in AccelStepper.h and AccelStepper.cpp, for example: void AccelStepper::begin(uint8_t interface=AccelStepper::FULL4WIRE, uint8_t pin1=2, uint8_t pin2=3, uint8_t pin3=4, uint8_t pin4=5, bool enable=true) { // paste the original constructor method here } Make an empty default constructor for AccelStepper in AccelStepper.h: AccelStepper::AccelStapper() {} Use it in your code: AccelStepper mystepper; void setup() { mystepper.begin(AccelStepper::FULL4WIRE, coil1, coil2, coil3, coil4); } void loop() { mystepper.runSpeed(); } edit: steps_per_revolution replaced with AccelStepper::FULL4WIRE. with kind regards, Szymon
  22. Hi worstell, Thank you very much. I have taken the liberty of implementing that idea into my code. What came out is an 8 digit display driver using the very same number of pins as the 4 digit version I had started with. It looks OK, if you don't care about the flickering of some segments that supposed to be off. It is apparent that making the nodes floating still results in residual currents floating in unwanted branches. This is justified by REALLY simplistic and minimalistic hardware. My code allows to manipulate duty cycle for both displays separately - as you suggest it is possible to compensate for the brightness differences between the CA and CC displays. Szymon
  23. Hello fellow 43oh'ers ! I have coded a similar thing myself just recently to replace a hard-to-get saa1064 I2C display driver chip. My objectives were therefore a bit different, namely I wanted a full functional replacement. Circuit simplicity is a pro, as it requires barely a handful of current limiting resistors, display and an USI capable MSP with at least 12 gpios available. The code can be found in google code repository (url will follow). Feedback is more than welcome, as I am new into micro-controller programming. http://code.google.com/p/msp430-saa1064/ s.
×
×
  • Create New...