Friday, December 11, 2015

Nixie Clock: Programming

I was able to get some simple code running on the Nixie Clock that displays the time and flashes the separators once every two seconds. I initially tried to write my own code for interfacing with the DS32321, but I kept running into issues. The ATMega328 datasheet (for the I2C setup and status codes), the DS3231 datasheet (for register addresses), and this website were all indispensable when writing the code. In the interest of time, I decided to just use a library. It worked perfectly, and I was able to set and retrieve the time.

I now need to add fancier animations and more modes for showing the date, temperature, and timers.

Tuesday, December 8, 2015

Nixie Clock: Finally Ready for Programming

After several pass with the toothbrush, isopropyl alcohol, and the occasional use of the soldering iron, I finally got all the issues ironed out. It tool quite a while to clean off all the flux, and every time I had to re-solder a pin, I made sure to clean the flux off.

Here is a video showing all segments operating independently:

Thursday, December 3, 2015

Nixie Clock: Debugging

Well, as soon as I began programming, I ran into issues everywhere. Along with all the issue I listed yesterday, I realized that the flux I used, Kester SP-30, (which my dad for me a got for me a long time ago, but I never used it) was plumbing flux. And according to the data sheet, it is "too corrosive for electrical or electronics soldering applications." More searches turn up that not before long this flux will probably corrode all the SMD joints.

I decided to test my hypothesis that the flux residue was conductive and causing the numbers to light up randomly. I wrote up a simple program to cycle between all the digits one by one to see if there were any shorts between and pins. Interestingly, sometimes digits near the one that was actually powered would light up. As the number which was powered got closer to the numbers that weren't supposed to light, the ones no supposed to light up got brighter. There was definitely some sort of connection between multiple digits, and only thing I could think of was the residue.

I took out some isopropyl alcohol and cotton swaps to begin cleaning off the residue, hoping that the lighting up issues would go away and to see if I could minimize any future corrosion from the flux.I didn't have a brush handy so this took quite a long time, and in the end there were cotton fibers caught all over the place on pins and not all the flux in tight spaces were gone.

After cleaning up as much as I could, I tested the clock out again and it improved significantly. The last digit was no longer lighting up, and fewer digits were lighting up out of place. The reset line was now holding at 5V and didn't require the extra wire any more.

I will definitely need a brush to clean out all the flux residue. I hope this will solve all the issues so I can get back to programming.

Wednesday, December 2, 2015

Nixie Clock: Circuit Complete

I got the PCBs from OSHPark two days ago and finished assembling one board.

The assembled circuit.

Monday, November 23, 2015

Nixie Clock

I haven't done a project in while and decided I wanted to build another clock. I've always liked the look of Nixie tube clocks and decided to build one. This time I wanted to try using surface mount parts to keep the costs down.

For hardware, this clock uses six IN-14 Nixie tubes for the digits and two IN-3 tubes for the digit separators. An ATmega328 (I'm still not sure if I'm going to use an external crystal or not, but there is room for one on the PCB) is the main controller and a DS3231 RTC is used for time keeping.
Nixie tube with high voltage power supply in background.
Nixie tube testing.

Monday, August 24, 2015

Summer CNC Upgrades

I did a few upgrades on the CNC to make it more rigid, but the gantry still isn't rigid enough and has some wiggle. The y-axis pipes (longest axis) were replaced with 8020 beams and v-groove bearings. The z-axis was completely replaced with a metal one from eBay that is completely rigid. However, the gantry is just too weak and the left and right sides of it can move back and forth.

In general, however, the CNC is much better and I used it to cut out fins for other TARC teams' rockets.

The End of Summer

Well, summer break is coming to an end and the beginning of 11th grade is fast approaching. I did have some fun, even with all the SAT prep.

Just over a week ago I went to Fremont Peak State Park at San Juan Bautista, CA to do some astrophotography because the light pollution there is far lower than in the city.


A panorama of the Milky Way.

I also went to Hawaii.
Napali Coast
Waimea Canyon

Sunday, May 17, 2015

Controlling the WS2812B

I just got my 1 m, 60 WS2812 (or NeoPixel) strip form China and have been experimenting with patterns on them. My final goal is to wrap them around a circle or hexagon and have Fourier Transform bins mapped to the intensity of the LEDs. As a secondary function I plan to have the LEDs display a clock too.

The LEDs act like a shift register, just that the clock, data, and latch are all on one pin. The timing specification of the WS2812 (datasheet) is relatively straight forward. To save time, I've gone ahead and used the Adafruit NeoPixel library. I'll come back to try to implement the timing on my own when I'm done with this project, since this is for a class project and there is a deadline.

What I have noticed when using this sample code was that if I had too many computational cycles (e.g. I was looking up sin values from a lookup table) between each sendPixel, the data failed to properly clock out. I'm not sure if using a lookup takes longer than the maximum allowed time between bits, but something is causing the timing to be messed up. That's why using the Adafruit library is so handy; the data for all the pixels is stored in memory for easy adjustment of the colors and then clocked out with one command. This means one can compute and set the values first without worrying about it messing up timing. I could have also initialized an array for the first sample code to hold all the color data and clock it out, but I found it more convenient to use the Adafruit library. If I ever need to fully port my code to AVR C, I would go back to the first sample code.

Sunday, May 3, 2015

The DFT and Counting Cycles

I've spent the last few days implementing the Discrete Fourier Transform on a AVR microcontroller. I ran into several issues along the way and as a result learned a lot about AVR timers and the ADC.

I ran into the most trouble with the timers. I was too lazy to set up a ATmega328 on a breadboard and just decided to use an Arduino for testing purposes (and because it already has a serial communication library for relaying results). I wanted to use timer0 to trigger at 16 kHz and set when the ADC should sample. However, I didn't know that timer0 was used by the Arduino core. I spent several hours wondering my bins were only 30 Hz apart when they should have been 500 Hz apart (determined by using a Youtube hearing test video). I finally figured it out and switched over to timer2.

Now my bins were much wider, but they were still only ~300 Hz apart. I was somehow still not sampling at the right rate. I soon realized that the ADC conversion time was longer than the time between each sample. I had set the ADC prescaler to 128, and with a 16 MHz system clock and each ADC conversion taking 13 ADC clock cycles, each ADC conversion would have taken 1,664 system clock cycles. But with a 16 kHz sampling rate, there was only 1,000 system clock cycles between each sample. The 300 Hz bin spacing is now clearly explained, since (16,000,000 cycles/sec)/(1,664 cycles/sample) = 9,615 samples/sec. With 32 bins, the bins are 300 Hz apart at this sampling rate. I lowered the ADC prescaler to 8 and now the ADC conversion only takes 104 system clock cycles.

I thought I fixed everything until I realized that now my bins were nearly 2 kHz apart! The reduction in ADC conversion time must have caused this, but I couldn't figure how. Timer2 should have been regulating the sampling speed to 16 kHz. I looked back at the AVR timer tutorial and saw that in the tutorial CTC mode was set first, the compare value next, and finally the prescaler. I looked into the datasheet and realized that setting the prescaler started the timer. My code set the compare value last, after I set the prescaler. I moved the prescaler settings after the compare value was set and the bins were finally 500 Hz apart. Order does matter.

I'll be moving my code off of the Arduino platform and will likely be putting this into some sort of visualization project.

Code (I left out the lookup tables [I wrote a simple Java program to create them]):

void DFT(void){
    uint16_t angle = 0;
    for(uint16_t i=0; i<Nsize/2; i++){ //each bin
        Re[i] = 0; //reset from last time
        Im[i] = 0;
        for(uint16_t j=0; j<Nsize; j++){ //each sample in the bin
            angle = (uint16_t)pgm_read_word_near(&(angleTable[i*32+j]));
            Re[i] += samples[j]*(int16_t)pgm_read_word_near(&(cosTable[angle]));
            Im[i] += -samples[j]*(int16_t)pgm_read_word_near(&(sinTable[angle])); //negative unncessary (only for consistency with complex DFT)
        }
        //Re[i] /= Nsize;
        Re[i] = Re[i]/4096; //divide by 4096
        //Im[i] /= Nsize;
        Im[i] = Im[i]/4096;
    }
}

void timerInit(){
    TCNT2 = 0;
    TCCR2A = (1<<WGM21); //CTC
    OCR2A = 125; //for 16kHz sampling
    TCCR2B = (1<<CS21); //8x prescaler
}

void adc_init(){
    ADMUX = (1<<REFS0); 
    ADCSRA = (1<<ADEN)|(1<<ADPS1)|(1<<ADPS0); //enable; 2 MHz, 8 prescaler
}

uint16_t adc_read(void){
    ADCSRA |= (1<<ADSC);
    while(ADCSRA & (1<<ADSC)); //wait for A2D conversion
    return (ADC);
}

void setup(){
    Serial.begin(115200);
    timerInit();
    adc_init();
}

void loop(){
    for(int i = 0; i < Nsize; i++){
        while((TIFR2 & (1 <<OCF2A)) == 0); //wait for next time to sample
        samples[i] = (int16_t)adc_read();
        TIFR2 = 1<<OCF2A; //clears CTC flag by writing a one to it
    }
    
    DFT();
  
    uint16_t mag = 0;
    for(uint8_t j = 1;j<Nsize/2; j++){ //ignore first bin since it only contains the dc bias
        mag = sqrt(Re[j]*Re[j] + Im[j]*Im[j]);
        Serial.print(mag);
        if(j!=Nsize/2-1)    Serial.print(",");
    }
    Serial.println();
}

Helpful Links:
DFT Explanation
DFT on AVR Example
Hearing Test Video (for creating sine waves)
Data Visualization (I modified this to show the values of the DFT from the Arduino)
AVR Freak's Timer and ADC tutorials
ATmega328 Datasheet
Op-amp Circuit (for shifting an audio signal to 0-5 V)

Tuesday, April 14, 2015

AtlasMeter Testing Continued

I fixed the lost steps issue by taking inspiration from my CNC machine. Since they don't have infinite acceleration, CNC machines use trapezoidal velocity profiles to slowly ramp in and out of movements. My camera dolly also can't accelerate infinitely, so I applied a trapezoidal profile to the velocity of every camera move. After a bit of tweaking, I was no longer losing significant number of steps. I tested from 10 to 204 frames and every time the dolly moved the right distance. However, the dolly now travels a little slower (the move step function now takes a delay parameter and therefore takes more CPU time). I need to implement variable speed movement to save time in setting up the start and end positions of the dolly.

Friday, April 10, 2015

AtlasMeter Testing

After running the timelapse dolly several times, I've uncovered several bugs in the code and hardware (and fixed them). I added a screw to mount the camera (without the mount the camera slowly shifted around) and fixed some time display bugs. For some reason, the dolly consistently misses steps, and the more frames there are the more steps are dropped. At the end of a 240 frame run that was supposed to travel over the entire length of the dolly the camera was nearly a foot short of the set end position. I'll have to fiddle around and add some constant to the steps per frame to get the right distance.



I noticed that the camera moved slightly faster in the beginning than at the end and didn't have a very consistent speed  in the middle. There must be more steps dropping or some play in the belt. Also, I need to remember to not move the camera too much per frame or the video is choppy.

Wednesday, April 8, 2015

AtlasMove Rev.0 Complete

My timelapse dolly project, named AtlasMove, has finally become a functional prototype. I just finished programming a rudimentary menu system for setting up the timelapse parameters. I still need create clamps to hold the belt at each end of the slider to keep the belt taught.

Front side of the circuit board
Back side (a little messy)

Wednesday, February 11, 2015

Camera Dolly: Parts

All the parts I ordered for the motorized slider are coming in slowly. The motors from All Electronics are really nice. One annoying quirk about the stepper motor is the 2 mm female connector. Why it couldn't have been 2.54 mm, I'm not sure. In the end, I just bent a set of standard headers into the correct width. Interestingly, the gear motor had a 2 mm male header with far more pins than was needed for the encoder and motor power. On the back of the header was a 8 pin SOIC chip. Upon closer inspection, I found out that it was an I2C EEPROM (M24C02). I hooked up (poorly soldered) wires to read the EEPROM but found that it was empty (the entire thing was filled with 255 and 254). I wrote some data to it to verify that it was functional, and I was able to read my data back. I'll have to find a use for it later.

Pulley, belt, camera cable, motors, and linear slide
Stepper motor (and jerry-rigged connector)
Gear motor

EEPROM on gear motor header
(motor wires desoldered)

Saturday, February 7, 2015

Camera Shenanigans

I've recently been tinkering with DSLR cameras and timelapses. Seeing all the videos of timelapses and especially the "holy-grail" timelapses from day to night have gained my attention. I've been looking into the subject for quite a while now but only now am I really delving into the details. The timelapse controller I've been working on for a while is currently parked because I decided to get more acquainted with the basics of timelapse before getting into bulb ramping. I bought a simple timer remote and am experimenting with several scenarios. I've also shot one timelapse of the stars at night. To add motion to a timelapse, I've decided to also build a two-axis motorized dolly (linear motion and one rotational axis) using the 8020 slider that was supposed to go on the CNC. The parts are slowly arriving and I hope to build it up and test it soon.