Adafruit Industries, Essential service and business: NYC – Executive Order 202.6 - Read more. Accepting essential orders - here's how.
0

Capacitance Measurement
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

by mikewitt on Tue Mar 06, 2007 8:56 pm

I got it to program! :D But the code doesn't work :( But I expected that so it's ok. To solve the error thingy, reboot (I shoulda tried that earlier, but I don't like restarting my compter).

At least it's transmitting at 9600 baud like it should, but it's transmitting 0xFF. I'll figure it out later, for now I'm happy my compiler works again.
mikewitt
 
Posts: 111
Joined: Thu Jan 04, 2007 9:18 pm
Location: KB9YJY, Wilmette, IL

by mikewitt on Thu Mar 08, 2007 7:10 pm

More and more problems keep cropping up. The error wasn't caused by needing to reboot, it was caused by ripple current in the power supply (Make sure that the timing cap part of the 555 circuit is tied to ground). And the ATTiny13 doesn't seem to work the way it should, so I'm moving it over to an ATTiny2313 (unless someone wants to help me out with the problem: the for() loops aren't consistently using clock cycles)

In any case, I'm having bigger problems that I anticipated, so I don't know how long it'll be now before I have working code/schematics.
mikewitt
 
Posts: 111
Joined: Thu Jan 04, 2007 9:18 pm
Location: KB9YJY, Wilmette, IL

by adafruit on Thu Mar 08, 2007 10:08 pm

hey! over there! its the Learning Process :)

adafruit
 
Posts: 12151
Joined: Thu Apr 06, 2006 4:21 pm
Location: nyc

by mikewitt on Thu Mar 08, 2007 10:30 pm

Yeah, yeah.

I just got the USART on the ATTiny2313 (which the 13 doesn't have) to TX at 9600 baud, so I can pretty simply port it. Tomorrow night I'll hove code posted (hopefully :wink: )
mikewitt
 
Posts: 111
Joined: Thu Jan 04, 2007 9:18 pm
Location: KB9YJY, Wilmette, IL

by mikewitt on Sat Mar 10, 2007 10:18 am

I need help. Does anyone know why the program would continuously restart? I put the "while(1);" thing at the end of the int main function, but that only seems to keep it from restarting for about 1000 clock cycles, then it restarts from the beginning of the code. I've looked everywhere, but I can't figure out what I need to do to fix this.
mikewitt
 
Posts: 111
Joined: Thu Jan 04, 2007 9:18 pm
Location: KB9YJY, Wilmette, IL

by Olaf Marzocchi on Sat Mar 10, 2007 11:07 am

Could you post an URL always pointing to the latest version of the code?
I'm a total newbie, but I can give it a look.
Olaf Marzocchi
 
Posts: 73
Joined: Mon May 08, 2006 3:29 am

by mikewitt on Sat Mar 10, 2007 11:18 am

Here, this will be up to date:
http://witt.michael.googlepages.com/cap_src.zip

There are new files in there since the last time I uploaded, because I changed lots of things, and so I keep a copy every time I make a big change (Because I wish I had started doing that earlier, when I first got the USART to work, it worked perfectly, so I started adding in the other stuff, and it stopped working. Now I can't get it to work the way it did with that source, and I have no copy of that source.)
mikewitt
 
Posts: 111
Joined: Thu Jan 04, 2007 9:18 pm
Location: KB9YJY, Wilmette, IL

by mikewitt on Sat Mar 10, 2007 3:36 pm

I have an update on the project:

The 555 timer causes _LOTS_ of noise on Vcc, enough to mess with timings and signals to the point that they aren't useable. So there needs to be a filter cap between Vcc and ground. A .1uF (Labeled 104) cap works wonders for the circuit. Now that the code is working at the point it was before, I'm happy.

On another note, the noise caused by the 555 was what kept restarting the AVR, so that's solved.
mikewitt
 
Posts: 111
Joined: Thu Jan 04, 2007 9:18 pm
Location: KB9YJY, Wilmette, IL

by Olaf Marzocchi on Sat Mar 10, 2007 6:56 pm

Code: Select all | TOGGLE FULL SIZE
      //now we need to pass our info to the TX function
      for (time2 = 10000000; time2 >= 1; time2 /= 10);
      time2 = 8000000;
      while (time2--);
      timerCk = 1;


What's the meaning of this? does the for() cycle only waste clock cycles?
Olaf Marzocchi
 
Posts: 73
Joined: Mon May 08, 2006 3:29 am

by mikewitt on Sat Mar 10, 2007 7:04 pm

that's code that was there from the first revision. that line should read:

Code: Select all | TOGGLE FULL SIZE
for (time2 = 10000000; time2 >= 1; time2 /= 10) tx((((tFreq - (tFreq % time2)) % (time2 * 10)) / time2) + 0x30);


It is supposed to parse out each decimal number from the integer tFreq. the second part that is just a while loop _was_ meant to waste clock cycles, because I figured that slowing things down might help me debug (it didn't, only because the AVR continually restarted every ~100ms, and it was supposed to waste a second)
mikewitt
 
Posts: 111
Joined: Thu Jan 04, 2007 9:18 pm
Location: KB9YJY, Wilmette, IL

by mikewitt on Sun Mar 11, 2007 12:42 am

I've updated the archive, gotten the USART working, but there are still things that need to be done, like actually _getting_ the frequency of the INT1 source (I can't get it to work :( ).

Also, I'm using a C9014 NPN BJT to power the 555 now, instead of running it directly off of Vcc. It'll still work off of Vcc, but now I have a way of turning it off if I want to (and it's a good idea to when programming).
mikewitt
 
Posts: 111
Joined: Thu Jan 04, 2007 9:18 pm
Location: KB9YJY, Wilmette, IL

by Olaf Marzocchi on Sun Mar 11, 2007 5:32 am

Olaf Marzocchi
 
Posts: 73
Joined: Mon May 08, 2006 3:29 am

by mikewitt on Sun Mar 11, 2007 12:56 pm

Thanks for the link to that code. I got it running on my AVR, and it seems to work. Now I just need to convert the frequency into farads.

Here's the C code
Code: Select all | TOGGLE FULL SIZE
/*
Much of this code is written by stephen dredge,
retrieved March 11, 2007 from
http://www.avrfreaks.net/index.php?module=Freaks%20Academy&func=viewItem&item_id=86&item_type=project

everything else written by Michael Witt
*/
#include "defines.h"
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>
//#include <stdlib.h>

#define USEASM

//change these to suit crystal frequency
#define LCDDELAY   0x85      //delays 50uS with 3 cycle loop & 8MHz clock
#define TIMER1HIGH   0x86      //delay 1S with 7.9872 MHz crystal
#define TIMER1LOW   0x20      //and /256 prescale

volatile unsigned long int timerCk = 1;    //this will be our clock cycle counter
volatile unsigned char finishedCk;      //this will be our indicator if we're
                                 //done with counting clock cycles (inverse logic tho)

volatile unsigned char CaptureComplete, IntFlagA, IntFlagB, TimerCount;
volatile unsigned int OverflowA, OverflowB;

void USART_Transmit( unsigned char data )   {
   /* Wait for empty transmit buffer */
   while ( !( UCSRA & (1 << UDRE)) );
   
   /* Put data into buffer, sends the data */
   UDR = data;
};

#define BV(x)       (1 << x)
#define outp(x, y)    y = x

//8 bit Counter/Timer Prescaler Values
#define TMC8_STOP      0
#define TMC8_CK         BV(CS00)
#define TMC8_CK8      BV(CS01)
#define TMC8_CK64      (BV(CS00)+BV(CS01))
#define TMC8_CK256      BV(CS02)
#define TMC8_CK1024      (BV(CS02)+BV(CS00))
#define TMC8_EXTFAL      (BV(CS02)+BV(CS01))
#define TMC8_EXTRIS      (BV(CS02)+BV(CS01)+BV(CS00))

//16 bit Timer Counter Prescaler Values
#define TMC16_CK      BV(CS10)
#define TMC16_CK8      BV(CS11)
#define TMC16_CK64      (BV(CS10)+BV(CS11))
#define TMC16_CK256      BV(CS12)
#define TMC16_CK1024   (BV(CS12)+BV(CS10))

void StartCapture(void){
   OverflowA=0;
   TimerCount=0;
   CaptureComplete=0;
   outp(BV(TOV1)|BV(OCF1A)|BV(TOV0),TIMSK);   //Timer1 & Timer0 overflow,Timer1 Compare interrupts enabled 0xc2
   outp(TIMER1LOW,TCNT1H);                    //load timer1
   outp(TIMER1LOW,TCNT1L);                    //
   outp(0xff,OCR1H);                     //load compare registers to interrupt
   outp(0xff,OCR1L);                     //256 clocks before timer1 overflows
   outp(TMC16_CK256,TCCR1B);               //start timer1 CLK/256 250 ms delay
   
   outp(TMC8_EXTFAL,TCCR0B);               //start timer 1 counting external clock on falling edge

   //outp(TMC8_CK8,TCCR0B);                    //use this line instead to
                                    //test, instead of external count
                                    //crystal frequency/8 will be displayed if ok
};

void tx_int(unsigned long int data) {
   unsigned long int i = 0;
   for (i = 10000000; i >= 1; i /= 10) USART_Transmit((((data - (data % i)) % (i * 10)) / i) + 0x30);
};

void startTimer(void) {
   //this sub starts counting
   sei();
   while (finishedCk) timerCk++;
};

ISR(SIG_INTERRUPT1) {
   unsigned long int tFreq;
   if (finishedCk == 1) {
      tFreq = (F_CPU / 8) / timerCk;
      //USART_Transmit(ascii_command);
      //USART_Transmit(ascii_cls);
      for (timerCk = 0; timerCk <= 100000; timerCk++) nop();
      tx_int(PORTD);
      for (timerCk = 0; timerCk <= 500000; timerCk++) nop();
      timerCk = 1;
      sei();
      finishedCk = 0;
   } else {
      finishedCk = 1;
      timerCk = 1;
      startTimer();
   };
   sei();
};

//ISR( SIG_TIMER1_COMPA ) {sei();};
*/
#define inp(x) x
SIGNAL(SIG_OVERFLOW1) {
   outp(TIMER1HIGH, TCNT1H);                             //reload timer1
   outp(TIMER1LOW, TCNT1L);                             //reload timer1
   IntFlagA = TIFR;                                 //store timer interrupt flags
   TimerCount=inp(TCNT0);                              //store timer0 count
   IntFlagB=inp(TIFR);                                 //store timer interrupt flags
   OverflowB=OverflowA;                              //store timer0 overflow
   IntFlagA&=BV(TOV0);
   IntFlagB&=BV(TOV0);                                 //mask for timer0 overflow
   if(IntFlagA){OverflowB++; outp(BV(TOV0), TIFR);}         //overflow0 interrupt was pending so increment overflow and clear flag
   if((IntFlagB)&&(!(IntFlagA))&&(TimerCount<0x80))         //timer0 overflowed as we were reading it
      {OverflowB++; outp(BV(TOV0),TIFR);}                  //so increment overflow and clear flag
   TIMSK |= (1 << TOIE0);                                 //enable timer0 overflow interrupt
   CaptureComplete=1;                                 //signal we are done
}

#ifdef USEASM
SIGNAL(SIG_OVERFLOW0) __attribute__((signal,naked));      
#endif
SIGNAL(SIG_OVERFLOW0) {
#ifdef USEASM
asm volatile (   "push r24"               "\n\t"
            "push r25"               "\n\t"
            "in r24,__SREG__"         "\n\t"
            "push r24"               "\n\t"
            
            "lds r24,OverflowA"         "\n\t"
            "lds r25,(OverflowA)+1"      "\n\t"
            "adiw r24,1"            "\n\t"
            "sts (OverflowA)+1,r25"      "\n\t"
            "sts OverflowA,r24"         "\n\t"
            
            "sei"                  "\n\t"
            
            "pop r24"               "\n\t"
            "out __SREG__,r24"         "\n\t"
            "pop r25"               "\n\t"
            "pop r24"               "\n\t"
            "reti"                  "\n\t"
            ::);
#else
   OverflowA++;
#endif
}

#ifdef USEASM
SIGNAL(SIG_OUTPUT_COMPARE1A) __attribute__((signal,naked));
#endif
SIGNAL(SIG_OUTPUT_COMPARE1A)               //Timer1 compare interrupt handler disables T0 overflow int
{
#ifdef USEASM
asm volatile (   "push r24"               "\n\t"
            "push __tmp_reg__"         "\n\t"
            "in __tmp_reg__,__SREG__"   "\n\t"
            "push __tmp_reg__"         "\n\t"
            
            "ldi r24,lo8(-3)"         "\n\t"
            "in __tmp_reg__,57"         "\n\t"
            "and __tmp_reg__,r24"      "\n\t"
            "out 57,__tmp_reg__"      "\n\t"
            
            "pop __tmp_reg__"         "\n\t"
            "out __SREG__,__tmp_reg__"   "\n\t"
            "pop __tmp_reg__"         "\n\t"
            "pop r24"               "\n\t"
            "reti"                  "\n\t"
            ::);
#else
cbi (TIMSK,TOIE0);
#endif
}

int main(void) {
   unsigned long Frequency=0, Count=0, LastCount=0;
   unsigned long AvFrequencyA, AvFrequencyB=0;
   unsigned char IndexA=0, IndexB, IndexC=40, Hours=0, Mins=0, Secs=0;
   union{unsigned char Byte[4];unsigned long Long;}TempUnion;
   
   UBRRH = 0;
   UBRRL = 103;
   UCSRA = (0x00) | (0x01 << U2X);
   UCSRB = (0x01 << RXEN) | (0x01 << TXEN);
   UCSRC = (0x00 << USBS) | (0x03 << UCSZ0) | (0x00 << UMSEL) | (0x00 << UCPOL);
   
   DDRB = 0xFF;
   DDRD = 0x00;
   
   //TCCR1B = (1 << WGM12) | TIMER1_PRESCALE_64;
   //OCR1A = (uint16_t)10000;
   //TIMSK = (0 << OCIE1A);
   
   MCUCR |= 3 << ISC10;
   GIMSK |= 1 << INT1;
   CLKPR = 0x80;
   CLKPR = 0x00;
   
   PORTB = 0x01; // turn on the 555 circuit via a c9014 npn bjt
   
   //clear the screen (if there's anything on it)
   //USART_Transmit(ascii_command);
   //USART_Transmit(ascii_cls);
   sei();
   while(IndexA<80) eeprom_write_byte(IndexA++,0);
   IndexA=0;
   StartCapture();
   while (CaptureComplete == 0);
   CaptureComplete = 0;
      while(1){
      while(CaptureComplete == 0){
                                 //go into idle mode so when Timer1 overflows
         #ifdef USEASM               //we don't have to finish processing current
         //sbi(MCUCR, SE);               //instruction before we can execute int service
         //asm  (   "sleep"      "\n\t"      ::);
         #endif
      }
      CaptureComplete = 0;
      if(++Secs == 60){
         Secs = 0;
         if(++Mins==60){
            Mins=0;
            Hours++;
         }
      }
      Count = (((long)OverflowB * 0x0100) + (long)TimerCount);
      if (Count == LastCount) Frequency = 0;
      else if(Count > LastCount) Frequency = Count - LastCount;
      else Frequency = (0x01000000 - LastCount) + Count;
      LastCount = Count;
      if (IndexA==40)IndexA=0;
      TempUnion.Long=Frequency;
      eeprom_write_byte(IndexA,     TempUnion.Byte[0]);
      eeprom_write_byte(IndexA + 1, TempUnion.Byte[1]);
      eeprom_write_byte(IndexA + 2, TempUnion.Byte[2]);
      eeprom_write_byte(IndexA + 3, TempUnion.Byte[3]);
      IndexB=0;
      AvFrequencyA=0;
      while(IndexB<40) {
         eeprom_read_block(&TempUnion,IndexB,4);
         AvFrequencyA+=TempUnion.Long;
         IndexB+=4;
      }
      IndexA+=4;
      if (IndexA==40) {
         if (IndexC==80)IndexC=40;
         TempUnion.Long=AvFrequencyA;
         eeprom_write_byte(IndexC,     TempUnion.Byte[0]);
         eeprom_write_byte(IndexC + 1, TempUnion.Byte[1]);
         eeprom_write_byte(IndexC + 2, TempUnion.Byte[2]);
         eeprom_write_byte(IndexC + 3, TempUnion.Byte[3]);
         IndexB=40;
         AvFrequencyB=0;
         while(IndexB<80) {
            eeprom_read_block(&TempUnion,IndexB,4);
            AvFrequencyB+=TempUnion.Long;
            IndexB+=4;
         }
         IndexC+=4;
      }
      USART_Transmit(ascii_command);
      USART_Transmit(ascii_cls);
      double Farad = ((1/Frequency)/2000)*1000000000;
      tx_int(Frequency);
      USART_Transmit(' ');
      USART_Transmit('H');
      USART_Transmit('z');
      USART_Transmit(0xfe);
      USART_Transmit(0x80+64);
      //tx_int(AvFrequencyA);
      //tx_int(AvFrequencyB);
      tx_int(Farad);
      USART_Transmit(' ');
      USART_Transmit('p');
      USART_Transmit('F');
      /*
      ClearDisplay();            //display frequency
      LcdGotoXY(0,0);
      PutLongLCD(Frequency,0);
      PutStringLCD(" Hz");
      LcdGotoXY(0,1);
      PutLongLCD(AvFrequencyA,1);
      LcdGotoXY(LCD_WIDTH/2,1);
      PutLongLCD(AvFrequencyB,2);
               //display time
      LcdGotoXY(LCD_WIDTH/2,0);
      PutUnsignedCharLCD(Hours);
      if(Secs%2)WriteLcdData(':');
      else WriteLcdData(' ');
      PutUnsignedCharLCD(Mins);
      if(Secs%2)WriteLcdData(':');
      else WriteLcdData(' ');
      PutUnsignedCharLCD(Secs);
      */
   }
   //while (1); //USART_Transmit(ascii_a);
};


and defines.h:

Code: Select all | TOGGLE FULL SIZE
/*
(C) 2007 Mike Witt

This is just a header that contains _LOTS_ of defines
anyting I think of, I put in here

Right now:
true - 1
false - 0

ASCII chars, upper and lower, numbers, few special ones
   through ascii_blah

few si conversions (multiply)

sleep and nop -- asm commands

some prescalers from ladyada,
*/

#define ascii_A 65
#define ascii_B 66
#define ascii_C 67
#define ascii_D 68
#define ascii_E 69
#define ascii_F 70
#define ascii_G 71
#define ascii_H 72
#define ascii_I 73
#define ascii_J 74
#define ascii_K 75
#define ascii_L 76
#define ascii_M 77
#define ascii_N 78
#define ascii_O 79
#define ascii_P 80
#define ascii_Q 81
#define ascii_R 82
#define ascii_S 83
#define ascii_T 84
#define ascii_U 85
#define ascii_V 86
#define ascii_W 87
#define ascii_X 88
#define ascii_Y 89
#define ascii_Z 90
#define ascii_a 97
#define ascii_b 98
#define ascii_c 99
#define ascii_d 100
#define ascii_e 101
#define ascii_f 102
#define ascii_g 103
#define ascii_h 104
#define ascii_i 105
#define ascii_j 106
#define ascii_k 107
#define ascii_l 108
#define ascii_m 109
#define ascii_n 110
#define ascii_o 111
#define ascii_p 112
#define ascii_q 113
#define ascii_r 114
#define ascii_s 115
#define ascii_t 116
#define ascii_u 117
#define ascii_v 118
#define ascii_w 119
#define ascii_x 120
#define ascii_y 121
#define ascii_z 122
#define ascii_0 48
#define ascii_1 49
#define ascii_2 50
#define ascii_3 51
#define ascii_4 52
#define ascii_5 53
#define ascii_6 54
#define ascii_7 55
#define ascii_8 56
#define ascii_9 57
#define ascii_dot 46
#define ascii_spc 0x20
#define ascii_ctl 0x7C
#define ascii_command 0xFE
#define ascii_cls 0x01
#define si_convert_micro 1000000 //multiply by these to get answer
#define si_convert_pico  1000000000
#define si_convert_femto 1000000000000
#define true 1
#define false 0
#define nop()  __asm__ __volatile__ ("nop" ::)
#define sleep()  __asm__ __volatile__ ("sleep" ::)
#define sbi(x,y)  __asm__ __volatile__ ("sbi " x "," y ::)

//defines from minipov.c: by ladyada

#define TIMER1_PRESCALE_1 1
#define TIMER1_PRESCALE_8 2
#define TIMER1_PRESCALE_64 3
#define TIMER1_PRESCALE_256 4
#define TIMER1_PRESCALE_1024 5

#define HEX__(n) 0x##n##UL

#define B8__(x) ((x&0x0000000FLU)?1:0)  \
               +((x&0x000000F0LU)?2:0)  \
               +((x&0x00000F00LU)?4:0)  \
               +((x&0x0000F000LU)?8:0)  \
               +((x&0x000F0000LU)?16:0) \
               +((x&0x00F00000LU)?32:0) \
               +((x&0x0F000000LU)?64:0) \
               +((x&0xF0000000LU)?128:0)

#define B8(d) ((unsigned char)B8__(HEX__(d)))

#define NUM_ELEM(x) (sizeof (x) / sizeof (*(x)))


note that compiling it, there are lots of warnings. Don't worry about them, the code still works.
mikewitt
 
Posts: 111
Joined: Thu Jan 04, 2007 9:18 pm
Location: KB9YJY, Wilmette, IL

by mikewitt on Sun Mar 11, 2007 1:28 pm

IT WORKS!!!!!!!!!!!!!!!! It measures in femto farads (yes, 1/1000000000000 of a farad) and can measure down to about 500 fF (.5 pF)

Eventually it will be auto-ranging, but right now it works.

You can get it here:
http://witt.michael.googlepages.com/cap_src.zip

unzip it in the folder C:\cap_src
go to a command prompt, and type 'make all'
then 'make program-cap'

If you aren't using a dasa programmer on com2, open up Makefile use ctrl-f to find the word 'com2' change it to com1 if you're using com1, or lpt1 if you're using a type dt006 programmer in the parallel port. if you're using a parallel port one, also change the programmer type from dasa to dt006 (use ctrl-f to find dasa)

I'll post full schematics when I get around to making them (right now, I'm taking a break)
mikewitt
 
Posts: 111
Joined: Thu Jan 04, 2007 9:18 pm
Location: KB9YJY, Wilmette, IL

by Olaf Marzocchi on Sun Mar 11, 2007 1:35 pm

Which was the error in your code? that's important to avoid it in the future :-)
Olaf Marzocchi
 
Posts: 73
Joined: Mon May 08, 2006 3:29 am

Please be positive and constructive with your questions and comments.