Jump to content

sq7bti

Members
  • Content Count

    24
  • Joined

  • Last visited

  • Days Won

    5

sq7bti last won the day on January 23 2016

sq7bti had the most liked content!

About sq7bti

  • Rank
    Member
  • Birthday 09/05/1975

Profile Information

  • Gender
    Not Telling
  • Location
    Eindhoven, The Netherlands
  • Github
    https://github.com/sq7bti

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  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.
×
×
  • Create New...