Make an analog-to-pulse converter to plug additional current clamp to Fluksometer

Currently I use three current clamps to measure the three phases of our mains lines with one Fluksometer, and an additional Fluksometer to measure the output of our PV installation with another current clamp. This is due to the fact that all our meters do provide no pulse output and I do not want to add an additional meter with an S0-output. So my idea was (and still is) to use the schematics of the Fluksometer collector board as a hint-provider to set up an analog-to-pulse converter.
For that it will be convenient to use an ATtiny13 that offers a 10bit-ADC and corresponding pulse-out ports equivalent to those used on the ATmega168 in the Fluksometer. The pulse-former's setup thus is pretty easy: Input current-clamp to ADC-port with 1uF and 1k91 to ground (as in the original) and output one port to an opto-coupler TIL111 (or something like that) forming an S0-port; adding a 5V-power supply and you are done with the electronics part.
Now the software part - pretty easy as well due to the availability of the AVR part of the Fluksometer's software - but wait, that is where I get stuck:
* Why is the software setting the ADC-Vref to Vbg that is 1.1V? The actual clamp output is 0-5V? How to avoid the overflow?
* Maybe already the answer: Why is there the 1k91-1% pull down resistor in the clamp's path? The 1uF capacitor I understand as voltage buffer...
May someone raise my smartness on this point? If so, I guess such a pulse-former would be a pretty nice and inexpensive enhancement to the Fluksometer enabling it to use up to two additional current clamps to measure "all you need".
Kind regards
Markus

icarus75's picture

Hi Markus,

That would indeed be a nice hack. You might even multiplex three analog (clamp) inputs to a single pulse output. That would allow you to hook up to 9 clamps on a single FLM.

As for the ADC Vref being Vbg: The current clamp output impedance will form a voltage divider in conjunction with the 1k91 pull-down. The latter will also force the input to 0V when no clamp is attached.

Cheers,
-Bart.

gebhardm's picture

Hi Bart,
but as the current clamp and the 1k91 resistor are in parallel, it would be a current divider (thus the voltage still be 0 to 5V)?! I am a bit puzzled... But as long as it works, I am fine; on the weekend I will start the software part on my small converter...
Kindly, Markus

gebhardm's picture

Addendum: As there are also current clamps that transform "just" the current to measure (say to 0 to 20mA) I would have understood the schematics as then the 1k91 resistors "makes" the voltage to measure through Ohm's law... In the case of the Fluksometer clamps I thought (maybe wrongly) this current to voltage conversion happens already in the clamp (thus 0 to 50A are mapped to 0 to 5V). Questions over questions on basic physics ;-)

gebhardm's picture

O.K., now I understood it :-) The clamps' measured impedance is around 6k9 Ohms - by the parallel 1k91 Ohm resistor this actually brings down the maximum voltage provided by the clamp to around 1,1V which is the Vbg. (5V/6k9 = 7,25E-4 A max current by clamp; 6k9 parallel to 1k91 is around 1k5 Ohms clamp resistance towards the ADC: R*I equals approx. 1,08V) and the world is right again...

icarus75's picture

It's good to know that the world is right again. :-)

gebhardm's picture

After some testing, please find in the following the hack's corresponding code for "own convenience"...

  1. /**************************************************************************
  2. Impulsformer - device to transform a voltage delivered from a current clamp
  3. to an S0-output with 1000 pulses per kilo-Watt-hour
  4.  
  5. Uses an ATTiny13 - written by Markus Gebhard, April 2012
  6.  
  7. Default oscillator setting 9,6MHz with prescaling by 8 to 1,2MHz
  8.  
  9. Use ADC3/PB3 as analog input
  10. Use PB2 as pulse output with optocoupler active low
  11.  
  12. Code under GPL
  13. **************************************************************************/
  14.  
  15. #ifndef F_CPU
  16. #define F_CPU 1200000   // 1,2MHz = 9,6MHz/8
  17. #endif
  18.  
  19. #include <avr/io.h>
  20. #include <avr/interrupt.h>
  21. #include <util/delay.h>
  22.  
  23. #define GRID_V  230;    // Standard voltage of power grid in Germany
  24. #define CLAMP_A 50;             // Max current that the current clamp transforms
  25.  
  26. #define PULSEPORT PORTB // the port on which the pulses are given
  27. #define PULSEDDR  DDRB  // direction of pulso port
  28. #define PULSE_1   PB2   // first pulse output port (there might be more)
  29. #define N_KWH     1000  // Number of pulses per kWh
  30.  
  31. // global variables
  32. uint32_t meterconst, pulseconst, energy;
  33. uint16_t lastADC;
  34.  
  35. // initialize the Pulse output port
  36. void init_Output( void )
  37. {
  38.         // set output port(s) as output
  39.         PULSEDDR |= (1<<PULSE_1);
  40.         // set level on output port high
  41.         PULSEPORT |= (1<<PULSE_1);
  42. }
  43.  
  44. // initialize the analog-digital-converter
  45. void init_ADC( void )
  46. {
  47.         // Disable unused digital input buffers for noise reduction
  48.         DIDR0  = (1<<ADC0D) | (1<<ADC1D) | (1<<ADC2D) | (1<<ADC3D);
  49.         // prescaler clk/4 => 300kHz sampling frequency
  50.         ADCSRA = (1<<ADPS1);
  51.         // Vref = Vbg (1.1V), right adjust (default), select ADC3 as input
  52.         ADMUX  = (1<<REFS0) | (1<<MUX0) | (1<<MUX1);
  53.         // enable ADC and start first ADC conversion (25 cycl = 83,33usec)
  54.         ADCSRA |= (1<<ADEN) | (1<<ADSC);
  55.         _delay_ms(1);
  56.         // start second conversion to initialize lastADC for proper "integration"
  57.         ADCSRA |= (1<<ADSC);
  58.         while (ADCSRA & (1<<ADSC));
  59.         lastADC = ADC;
  60. }
  61.  
  62. // initialize timer for continuous AD conversions and defined time base
  63. void init_Timer( void )
  64. {
  65.         // set prescaling to /8 => 1 cycl = 6,67usec
  66.         TCCR0B = (1<<CS01);
  67.         // set CTC mode
  68.         TCCR0A = (1<<WGM01);
  69.         // set top of CTC 150 * 6,67usec = 1ms
  70.         OCR0A = 0x96;
  71.         // set timer interrupt
  72.         TIMSK0 = (1<<OCIE0A);
  73. }
  74.  
  75. void send_pulse(unsigned char port)
  76. {
  77.         // active on low
  78.         PULSEPORT &= ~(1<<port);
  79.         // use delay compliant to S0-specification
  80.         _delay_ms(30);
  81.         // deactivate again
  82.         PULSEPORT |= (1<<port);
  83. }
  84.  
  85. // Interrupt on timer compare match to measure and integrate power
  86. ISR(TIM0_COMPA_vect)
  87. {
  88.         uint16_t actADC;
  89.         while (ADCSRA & (1<<ADSC));
  90.         actADC = ADC;
  91.         // discrete integration via Trapezoid Sums I(f)a|b ~ ((b-a)/2)*(f(a)+f(b))
  92.         energy += meterconst * (lastADC + actADC);
  93.         lastADC = actADC;
  94.         // start next conversion
  95.         ADCSRA |= (1<<ADSC);
  96. }
  97.  
  98. int main( void )
  99. {
  100.         init_ADC();
  101.         init_Timer();
  102.         init_Output();
  103.         // calculate metering constant for measuring intervalls
  104.         // (T/2) * (GRID_V * CLAMP_A / 1024); T = 1ms
  105.         meterconst = GRID_V;
  106.         meterconst *= CLAMP_A;
  107.         meterconst /= 2048U;
  108.         // set energy limit to send a pulse kWh -> 1000 W * 60 min * 60 sec * 1000 ms
  109.         pulseconst = 3600000000U;       // kWh in Wms
  110.         pulseconst /= N_KWH;            // distributed to n impulses per kWh
  111.         // enable interrupts
  112.         sei();
  113.         // main loop
  114.         while (1)
  115.         {
  116.                 if (energy >= pulseconst)
  117.                 {
  118.                         send_pulse(PULSE_1);
  119.                         energy -= pulseconst;
  120.                 }
  121.                 _delay_ms(1);  // without this delay it doesn't work
  122.         }
  123.         return (0);
  124. }

icarus75's picture

Hi Markus,

1/ Does this mean you have a working prototype?
2/ Might be more appropriate to upload your code to Github (or some other repo) and link to it from here.

Cheers,
Bart.

gebhardm's picture

Hi Bart,
at 1) yes, I have a working prototyp (but yet didn't have time to actually plug it into my fluksometer, will do so this evening or during the weekend and by that also provide compare measures between the S0 and the clamp variant)
at 2) yes, sounds appropriate and I will try to do so; doing so, I will also add the corresponding eagle files and a picture of the prototype.
Time, o time, where are thou?
Best regards
Markus

gebhardm's picture

Getting used to github - now the "correct" link to my repository (above link now is invlaid): https://github.com/gebhardm/energyhacks
I will add also a little hack for a temperature control that switches a circular pump for warm water, sometime...
Have fun, Markus

icarus75's picture

Hi Markus,

Feel free to join us for EC1205 in Offenburg next week.

Cheers,
Bart.

bazzle's picture

I just wish I understood what you have done :(
I assume from what I have seen on the GTI hub page you have written a software program to go into the FLM?
If I copy that into mine will my CC ports now be Digital ports?

Im sure alot of users have no idea what you have done but would like to be able to convert a port over simply.
Maybe the easiest way is to wait for a 'new' Flukso with more digital ports or purchase a new 2nd Flukso to use for gas and water etc?

Bazzle

gebhardm's picture

@Bazzle: No, no, no - this is a little hardware hack that uses another microcontroller to convert clamp data (as the FLM) to pulses that then can be input to the FLM's pulse ports; so there is no hack on the FLM yet. (see the Impulsformer.jpg that has a clamp, power and an FLM pulse port attached to the wires...)
With respect to the 'new' FLM I at least did not have the time yet to start the software change... Meanwhile anyone a little bit firm with microcontrollers may be able to copy my little hack...
Best regards
Markus