Hey, just wanted to say thanks to GioppY for this circuit. It helped me a lot. I built my own modeled after this one. I also rewrote the firmware, in C. I couldn't make heads or tails of the BASIC code. Ironic. Anyway, thought I would post my source in case anyone else was looking at this circuit.
Some pictures of my setup:http://www.mrkowasaki.com/cpgallery/...s.php?album=10
Code:/***************************************************************************\ * * * * * * * * * Description: Firmware for the PIC 12F675 micro controller. Monitors a * * 0-5v analog signal across pin GP0 and scales to the original input * * signal. * * * * * * NO WARRANTY, EXPRESS OR IMPLIED. YOUR MILEAGE MAY VARY. * * * * Software written by Demus * * Circuit designed by GioppY * * * * Compiler: mikroC DEMO version * * * * Notes: mikroC is very bloated. Any use of the math functions increased * * the ROM size over the 1K limit. This tiny little bit of software left * * only 17 bytes of free space. Virtually every part of the source was * * groomed for space concerns, hence the "strange" style of code. I used * * this circuit in conjunction with the Linksys MAX233 hack to monitor * * several solar powered wifi stations remotely. * * Enjoy. * * * * * \***************************************************************************/ // Miscellaneous debugging functions. Due to space constraints you're better // off embedding the function contents wherever you had planned on calling it // from. It saves a few call/ret instructions worth of space. void write_crlf () { Soft_Uart_Write (10); Soft_Uart_Write (13); } // Wrapper // Again, only useful for debugging. void uart_write_str (char *data) { while (*data) Soft_Uart_Write (*data++); } // This is where the real magic happens. Using some very basic // algebra and my own resistance measurements of the circuit // I was able to device a formula to obtain the battery voltage // to two decimal places without using any floating point math. // The PIC converts a 0-5V signal to a digital signal, a number // between 0 and 1023. Converting back to an analog voltage // representation is fairly easy and given by this formula: // (digital value/1024) * 5V = GP0 voltage // I then measured the voltage drop after the potentiometer, // and then right at the battery to determine the correct // ratio for MY circuit. It was 0.242 and leads way to this formula: // GP0 voltage / BAT voltage = 0.242 // With some simple math, these two formulas can be substituted into // each other and we arrive at: // (digital value/1024) * 5V = 0.242 BAT voltage // Convert the decimal to a fraction, solve for BAT and then multiply // both sides by 100. This gives you the two decimal precision without // having to deal with floating point numbers. The math libraries are too // big to use for this project. And I couldn't find any reasonable // way to output the float in anything but raw notation. void displayVoltage (unsigned long value) { unsigned long batCentiVolts; unsigned long a,b; // Simplified formula, technically we'll end up with centi-volts. batCentiVolts = value * 500000 / 247808; // The only issue with converting our number to a string this way is // that A must not contain less digits than the number we are processing. // Since we know exactly what range of numbers we will be dealing with // it's ok in the situation. a = 10000; // Maximum of 100V // Skip any leading digits while (batCentiVolts < a) a /= 10; // Strip off one digit at a time, and output to the serial console // This is pretty much long division. while (batCentiVolts) { // Determine quotient b = batCentiVolts / a; // Add value to base ASCII code for '0'. Soft_Uart_Write ((unsigned char) (b + 0x30)); // If we've just done the 3rd last digit, it means we // need to output the decimal. if (a==100) Soft_Uart_Write (0x2E); // '.' // Carry over the remainder and repeat batCentiVolts %= a; // Reduce the divisor a /= 10; } // Send a CR LF to keep the output nicely formatted Soft_Uart_Write (10); Soft_Uart_Write (13); } // It's very important to keep your oscillator calibration // Software UART is extremely unreliable otherwise. // For reference, the calibration is stored in the two bytes // of the ROM. void set_osc_cal(void) { asm { bsf STATUS, RP0 call 0x3ff movwf OSCCAL bcf STATUS, RP0 } } void init_ports () { CMCON = 7; // Turn off the comparators VRCON = 0; // Turn off CVref circuit WPU = 0; // Disable pull up IOCB = 0; TRISIO = (1<<0) | (1<<3); // Configure pins 0 and 3 as input ADCON0 = (1<<0) | (1<<7) ; // Enable ADC and select right justified results ANSEL = (1<<6) | (1<<4) | (1<<0); // Select analog processing for pin 0 set_osc_cal (); Soft_Uart_Init(GPIO, 2, 5, 9600, 0); // Setup UART (9600,N,1) } void main() { init_ports (); while (1) { // Infinite loop - Poll every two seconds displayVoltage (Adc_Read(0)); // Convert the analog signal to digital and send our results GPIO |= (1<<4); // Turn the LED on Delay_ms(1000); // Delay 1 second GPIO &= ~(1<<4); // Turn the LED off Delay_ms(1000); // Delay 1 second } }




Bookmarks