// Differential input to fixed point number +/-127 mVolts // echoed to the PWM with a gain of 10 // The PWM runs at 62,500 Hz for lower audio noise. // The ADC sampling and PWM update run at 7812 Hz. // The ADC input uses a UNION to avoid a multiply. // NOTE -- You MUST MOUNT the Aref jumper #include #include #include #include //I like these definitions #define begin { #define end } #define int2fix(a) (((int)(a))<<8) //Convert char to fix. a is a char #define float2fix(a) ((int)((a)*256.0)) //float to fix #define fix2int(a) ((signed char)((a)>>8)) //Convert fix to char. a is an int //Union avoids shifting when merging ADC output bytes union ADtype begin signed int vv ; // temp membrane voltage char Ain[2]; end AD ; signed int v ; // ADC voltage //============================================================= //read ADC 7812 scamples/sec // total time in isr must be less than 2048 cycles interrupt [TIM1_COMPA] void ADCread(void) begin // read the voltage x10, but // actual voltage = ADCH/128.0*Vcc/gain = ADCH>>8 since Vcc/10 = 1/2 // We want the voltage in the upper byte to be in millivolts // Convert to millivolts (ADC>>8)*1000, or very nearly ADC<<2 AD.Ain[0] = ADCL; AD.Ain[1] = ADCH; v = (AD.vv)<<2 ; // convert to millivolts in fixed 8:8 notation // start the next conversion ADCSR.6 = 1 ; // update PWM output // PWM is 0 to 5 volts in 256 counts // If we call 2.5 volt offset "zero" output (OCR0=128) // and we want a gain of 10 so that 100 mV input yields // 1 volt above zero out (3.5 volts) then we need to // scale v. Now for the PWM, 256/5=51.2 couts/volt output so if we // divide v by 2 and add 128 // (v/2)+128 we get approximately the right number // (within 2%). OCR0 = (fix2int(v)>>1) + 128 ; end //ISR //=============================================================== void main(void) begin //set up the A port //for analog inputs DDRA = 0 ; PORTA = 0; //set up the B.3 port for PWM output DDRB.3 = 1 ; //init the A to D converter // left adj /EXTERNAL Aref //!!!CONNECT Aref jumper!!!! // 10*(chan1 - chan0) ADMUX = 0b00101001; //enable ADC and set prescaler to 1/128*16MHz=125,000 //and clear interupt enable //and start a conversion ADCSR = 0b11000111; //turn on timer0 pwm with period= 256 cycles // (62,500 samples/sec) in fast PWM mode. TCNT0 = 0; TCCR0 = 0b01101001 ; //bit 4 inverts the PWM // timer 1 interrupt every 2048 cycles to update potential // and update OCR0 TCCR1B = 0b00001001 ; TCNT1 = 0; OCR1A = 2047; TIMSK = 0b00010000 ; #asm("sei") ; //init the UART UCSRB = 0x18; UBRRL = 103; printf("starting...\n\r"); // just spins and prints voltages while (1) begin printf("%d\n\r",fix2int(v)) ; delay_ms(200) ; end end