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