Опубликовано 2013-05-03 15:02:21 автором Ruslan

# Digital Power Meter

I immediately bought the other day bicycle motor-wheel . It has long dreamed of , and here it is, in all its glory !

The DC motor , valve , 48V , 500vat . The Chinese have promised an efficiency of about 85 % , which is not bad for such a moschnosti.K it was complete controller 800 watts, the throttle and brakes. The battery pack - 4 pieces , 12c , 9a/chasov and charger to them acquired separately .

I gathered all this stuff on my old mountain is great

First impressions of the electric drive train just beyond words ! Maximum torque right from the start ( accelerate faster than 50cc scooter ) , the maximum speed of 45 km / h.

Break in this whole thing , I wanted to tie it to some kind of feature, that realties to indicate the cost of energy. Then he asked for a digital power meter.

In the previous article we learned how to measure the voltage voltage and current. To measure the power consumption should be multiplied by the current voltage : W = B * A. In fact, the power meter - is ammeter and voltmeter in a single device . Let us join the scheme ammeter and voltmeter as described in previous articles, and obtain the circuit power meter :

Power meter is built on the microcontroller atmega8, which is deserved status of people . Current, voltage and power output to the display Lcd- 16x2.

Resistors R8, R9 built a voltage divider with a division factor 11 , a voltage reference is made in a regulated and TL431 zener voltage is set to 5.12 volt.Tok is measured by measuring the voltage drop across the shunt R2, further shunt voltage is amplified by the operational amplifier Lm358 and the input of the ADC adc0.

The program is written CodeVisionAVR

```# include <mega8.h>
# include <delay.h>
# include <stdio.h>  // library which contains the function sprintf

// Alphanumeric LCD Module functions
# asm
. equ __ lcd_port = 0x12; PORTD
# endasm
# include <lcd.h>

{
// Delay needed for the stabilization of the ADC input voltage
delay_us ( 10 );
// Wait for the AD conversion to complete
while ((ADCSRA & 0x10) == 0 );
}

void main (void)
{
char buffer [ 32 ] ;  // variable which will form the string for output to lcd
unsigned long int u;  // variable to store the voltage in millivolts
unsigned long int a;  // variable to store the current
unsigned long int w;  // variable to store the values of power consumption
PORTB = 0x00;
DDRB = 0x00;

// Port C initialization
PORTC = 0x00;
DDRC = 0x00;

// Port D initialization
PORTD = 0x00;
DDRD = 0x00;

// Timer / Counter 0 initialization
TCCR0 = 0x00;
TCNT0 = 0x00;

// Timer / Counter 1 initialization
TCCR1A = 0x00;
TCCR1B = 0x00;
TCNT1H = 0x00;
TCNT1L = 0x00;
ICR1H = 0x00;
ICR1L = 0x00;
OCR1AH = 0x00;
OCR1AL = 0x00;
OCR1BH = 0x00;
OCR1BL = 0x00;

// Timer / Counter 2 initialization
ASSR = 0x00;
TCCR2 = 0x00;
TCNT2 = 0x00;
OCR2 = 0x00;

// External Interrupt (s) initialization
MCUCR = 0x00;

// Timer (s) / Counter (s) Interrupt (s) initialization
TIMSK = 0x00;

// Analog Comparator initialization
ACSR = 0x80;
SFIOR = 0x00;

// ADC Clock frequency: 500,000 kHz
// ADC Voltage Reference: AREF pin

// LCD module initialization
lcd_init ( 16 );

while (1 )
{
/*
1. Measure current
The current flowing through the shunt , vichislyaetsya by Ohm's law : I = U / R
R = 0,1 Ohm , a U ( voltage drop across the shunt ) will be measured .
Since the ADC have a 10-bit , the maximum number that the function will return read_adc, ()
will be equal to 1024, this number is equivalent to the input voltage adc0.
For example, if read_adc () returned 512 then it means that the input adc0 E filed half a reference voltage
To calculate the actual stress , we need to make a proportion :
reference voltage - 1024
the desired voltage - a
We reference voltage = 5.12
The required voltage = 5.12 * a/1024, or Seeking voltage = 0,005 * a
For simplicity translate volts in millivolts by multiplying by 1000
The required voltage = 0,005 * a * 1000
Everything is good here , but we do not take into account the coefficient of op amp
calculated by the formula : Gain = 1 + R1/R2. Substituting , we get :
Gain = (1 + 4) = 5
The actual voltage = 0,005 * a * 1000/5 , we get just a
2.  Measure voltage
Next measure the voltage across the resistor divider
We form a proportion , as described above, and we get :
The required voltage = 0,005 * u * 1000
We must also take into account the coefficient of the resistor voltage divider
We it is Kdel = (R1 + R2) / R2. Substituting , we get :
Kdel = (10 +1 ) / 1 = 11
The actual voltage = 0,005 * u * 1000 * 11
*/

u = 55 * u;  // calculate the voltage in millivolts
a = a * 10  // calculate the current value according to Ohm's law : I = U / R = a/100 * 1000 = a * 10 miliamperah
w = a * u;  // calculate the power consumption
sprintf (buffer, "I =% u,% u U =% u,% u W =% u,% lu",
a/1000,  // The whole honor current
(a% 1000) / 10  // The fractional part of the current
u/1000,  // integer part of voltage
(u% 1000) / 10  // The fractional part of the voltage
w/1000000,  // Integer part of the power
(w% 1000000) / 10000
)  // Form a line to output
lcd_clear ();  // clean the screen before displaying
lcd_puts (buffer);  // deduce the formation of the string to display
delay_ms ( 100),  // make the delay

};
} ```

Order to function sprintf could work with variables of type long int, required further customization. For CodeVision AVR: Project-> Configure-> C compiler-> (S) printf Features-> Select the item "long, width, precision".

The project is in the Proteus and the source code of the program in the archive Watmeter.rar

Комментарии - (8)

• Виктор говорит:
Скажите, а почему мигает индикатор? Я думал что мигает только в протеусе, собрал в железе, то же самое.. ((
Здравствуйте. Мигает потому что частота обновления слишком маленькая, нужно увеличить частоту работы мк, до 4 мегагерц
• Виктор говорит:
А как сделать чтобы показания так не прыгали? Я пытаюсь измерять напругу от транса через диодный мост и кондеры. Но прыжки нереальные. Как устаканить контроллр?