Calculate True RMS Value (2)


This program is an extension of the previous program. This program will calculate the true-RMS value of voltage at the input ADC0 and ADC1 as much as 10 times a second. Thus, data from both input sampling will be updated every 100ms. To make the appropriate updates 10 times per second, we use the timer 0. This timer is precision operated (like we operate the precision frequency generator) to schedule the sampling process so that all sampling process on both inputs will take place at intervals 100ms. Every 100ms portc2 will become high. This activity is regulated by timer0. High logic of that port will activy sampling subroutines. After the sampling process completed, portc2 will be low again.
To observe the accuracy sampling schedule, users can measure the output frequency of this port. This port emits a clock signal with frequency of 10Hz. During the sampling process, this port will be high. This high logic duration (tH) is the sampling period, i.e. 20ms. Users can check the accuracy of this port to determine the sampling duration.

Note that sampling duration must equel to the voltage period.
Clock signal duty cycle in this port describes the load time of the microcontroller. The higher clock signal duty cycle, the higher the load time of the microcontroller. If the duty cycle is low, we still can insert other subroutines to run on the sidelines of the overall sampling process. These subroutines will fill the remaining time until the hose is fully loaded, that is 100ms. In fact, although the duty cycle approaching 100% (microcontroller load time already high), we were still able to insert other subroutines to be executed when the CPU waiting for the completion of the ADC conversion.
In this program, the one period of voltage (50Hz) was sampled 64 times. This means, each of the input signal would be sampled with a frequency of 64X50Hz = 3200Hz. This program sampled two inputs. So, the total frequency of sampling is 2X3200 Hz = 6400Hz. This means that the sampling process should happen every 156.25 microseconds. The sampling period is set by a timer 1 had been made in precision. 


See also Measure true-RMS of Voltage and Current Grid


Download .asm and hex code.


How to extend this work forward?
We can display true-RMS value to the LCD, or send the data to a PC via the serial port.

We can also increase the sampling frequency or use full resolution of ADC.

Precision Frequency Generator


Frequency generator usually has certain accuracy. Analog frequency generator typically has a relatively low accuracy. Errors that arise sometimes still above 1%, while digital frequency generator typically has higher accuracy with the error below 0.05%.
Many applications of frequency generator are created using the AVR microcontroller to build AVR-based frequency generator. But most have low accuracy. AVR can be operated as frequency generator by using a timer. CTC (Clear Timer on Compare) mode is usually used for this purpose. Theoretically, the output frequency fOCn of a timer will fulfill the following equation.
Where N is the prescaler value and OCRn is the match compare register. These equations will yield values that are not high accuracy. For example, we use the timer 0 to generate the frequency of 10Hz. There are several options for the value of N and OCRn.
 
      N    OCRn (dec)    OCRn (hex)

      8    69119            10DFF
    64      8639              21BF
  256      2159                86F
1024        539                21B

By looking at OCRn value in the table above, the generation of these frequencies is only possible with prescaler equal to 64, or 256 or 1024 and must use 16-bit timer, which timer 1. This is a conventional way.
With a prescaler 64, or 256 or 1024, we can use 8-bit timer, which is
timer 0 or 2. This may occur in large applications where the timer 1 is used to trigger another subroutine. With 8-bit timer we just need to fill the low byte of OCRn to OCR0 or OCR2 register. Furthermore, we run the timer as many as M times, where M is the high byte of OCRn value.
For example, to generate a clock with a frequency of 10Hz, the prescaler value can be filled 64, the value OCR0 = BFh and timer 0 is repeated as many times 21h.
But after a try, sometimes inaccurate output frequency 10Hz could be occured. For that, we need to do calibration. The trick is to shift the value OCRn. By increasing the OCRn value, the frequency will be lower; and by decreasing the OCRn value, the frequency will be higher. Ideally, the increase or decrease the output frequency value is as small as possible. But the time for single-digit increase of TCNTn (t) cannot be small as possible. It depends to prescaler which is used as the following table.

      N    t (us)
      8       0,72
    64       5,79
  256     23,15
1024     92,59

To fix it, shift the OCRn
value on the last count. Another example, for the generation of 5Hz frequency, we can operate the timer 0 with CTC mode and prescaler=64. In theory OCR0 value = 255. After the timer 0 count as much as 67 times, the value OCR0 changed to 128. With the simulation in AVR Studio, we get the output frequency to 5.0003 Hz. The value of these can be calibrated by decreasing the value of OCR0 be 127 so that the value of output frequency is 5.0000 Hz. Output frequency will have a maximum error of 0.01%. 

Download .asm and hex code


Does the error still can be reduced? Of course we still can!
We still use the prescaler = 64. With prescaler = 8, the error rate can be reduced.
But for now it might not need to do ....



What this routine can be applied for?


We have applied it for:
- To fix sampling periode for True RMS Calculation.
- To fix the periode of interval of sending data via serial port.

Data Logger to PC via Serial Port


A data logger is an electronic device that is used to record the value measured over time. It is simply plug into a serial port on your PC. By connecting suitable sensors, data logger can be used as acquisition products that can be used to measure temperature, pressure, relative humidity, light, resistance, current, power, speed, vibration... in fact, anything that you need to measure. The output data from data logger is a periodic stream in simple text or hexadecimal with customized data format we need. Simply capture the data to a text file and then import it into Excel to produce tables and charts over time. 
If the data sent to the PC is a text data, you can use HyperTerminal to receive the data. Some control characters like tabs and carriage returns can be used here. For this purpose, the data which is usually a binary or hexadecimal numbers must be converted into ASCII format. Here you can use the binary / hexadecimal to ASCII data converter .
In order to obtain higher transmission speeds, the data sent should still use binary or hexadecimal format. To receive this data, we should use receiver that can receive binary or hexadecimal data. We can make this program with programming tools such as Delphi, Visual Basic or Visual C. If necessary, the program can convert binary / hex to ASCII.
In the application we build, data from microcontroller ATmega8535 was sent to the PC using a serial transmission. This data is fed to PC via serial port. Data emited from TXD pin (PD1) of microcontroller. In the future, we must also be able to receive data from the PC. Such data can be received through the RXD pin (PD0) microcontroller. Of data to and from the microcontroller using TTL level, while data from and to the PC serial port using RS-232 level. To interface between the microcontroller and a serial port, we can use the CMOS / TTL - RS-232 converter, for example is MAX-232.
We can determine the speed of data to be sent. Here we use the speed of 9600bps. Because a single ASCII characters using 8-bit data format, then we can send about 1000 ASCII characters per second. The speed of data and data length can be changed. In this application, the microcontroller is operated at a clock frequency of 11.0592 MHz. On this frequency, some variation in the data transmission speeds will have 0% error.
The data that we send do not have to be continuous. Here, we will send data every 100ms. Data that we send are ASCII characters that located at memory location pointed to by the index_start until index_end constant. Such data will be sent 10 times per second. This data transfer speed is usually quite adequate for a data logger. However, if necessary, we can increase the speed.
In some applications like data logger, it may take time high accuracy in data transmission speed. A precision data logger can send appropriate data 10 times per second which means exactly 100 times per 10 seconds or right 36 000 times per hour. We can make the data transmission speed precisly. We can use 8-bit timer for this purpose. This is similar to building a precision frequency generator. Further discussion of this matter, you can click here.
This application can be combined with other applications that shown in this blog. By integrating the application with a True RMS meter, we can build a True RMS meter with data logger to a PC. By integrating these applications with the phase difference meter, we can build the phase difference meter with data logger to a PC. And
by integrating these applications with the compass tracker, we can build the compass tracker with data logger to a PC.

32-bit Square Root

This subroutine will calculate a square value of 32-bit value at r5:r4:r3:r2. Result is 16-bit at r17:r16 and will be rounded to nearest integer (0.5 rounds up).
Cycles include call & return: 271 - 316.

R17:R16 = sqrt(R5:R4:R3:R2)

sqrt32:    
    push  R18
    push  R19
    ldi   R19,0xc0
    clr   R18              
    ldi   R17,0x40
    sub   R16,R16

_sq32_1:   
    brcs  _sq32_2          
    cp    R4,R16
    cpc   R5,R17
    brcs  _sq32_3

_sq32_2:   
    sub   R4,R16
    sbc   R5,R17           
    or    R16,R18
    or    R17,R19

_sq32_3:   
    lsr   R19
    ror   R18             
    eor   R17,R19
    eor   R16,R18
    rol   R2
    rol   R3
    rol   R4
    rol   R5
    sbrs  R2,0             
    rjmp  _sq32_1          
    brcs  _sq32_4          
    cp    R16,R4
    cpc   R17,R5
    brcc  _sq32_5          

_sq32_4:   
    sbc   R3,R19           
    sbc   R4,R16
    sbc   R5,R17
    inc   R16  

_sq32_5:   
    lsl   R3               
    rol   R4
    rol   R5
    brcs  _sq32_6          
    cp    R16,R4
    cpc   R17,R5

_sq32_6:   
    adc   R16,R19
    adc   R17,R19     
    pop   R19
    pop   R18

    ret

The Purpose of This Blog

     The aim of this blog was to exchange our experiences in make use of microcontroller to facilitate our life. We used the 8051 and AVR microcontroller family. Your involvement was really hoped in giving the comment, the suggestion, the question and criticism for the development of applications that has we got up. This blog contain basic application. Several applications could be united with the other application to form the implement microcontroller-based digital measurement, such as: AC/DC Digital Voltmeter, True RMS Voltmeter, Apparent and True Power meter, Power Factor Meter, etc. All of them can use LCD to display the output value, and have data logger to log data to PC via serial port.
All of the application presented in this blog has been tested with best of my knowledge to make it error-free, but no warranty they are no mistake if they applied in the different environment, like quality of each component. Please send report to me if you find any error.
We also had several versions of each application presented in blog this. They had several differences, like: the clock speed, accuracy, sampling period, memory location and so on. Each of their variation could be have different schematic diagram. 

Most of our applications using assembler programming language. The language is much faster than the C language Assembler language also would have a hex code that is much smaller, so it can be executed by the AVR microcontroller, which mostly have SRAM just below 4 kbytes.
     All of the application is tested with best of my knowledge to make it error-free, but no warranty they are no mistake. Try it at your own risk!


Further Information

     What we show here is an overview of our application. More detailed explanation of this application which includes detailed specifications, result and accuracy, usability, electronic scheme, and program listings are also available. We also have several analyses of them. If you need it, please send a written request via the email below. Also please mention your profession and your goals using the application. 

freddykurniawan@yahoo.com.

Multiply 16-bit by 16-bit

This subroutine will multiply 16-bit value at r23:r22 with 16-bit value at r21:r20. Result is 16-bit at r17:r16.

    (r23:r22)
    (r21:r20)
    -----------X
    (r17:r16)   


r17:r16 = r23:r22 * r21:r20
Register usage: r0, r1


mul16by16:
    mul r22, r20 ; al * bl
    movw r17:r16, r1:r0
    mul r23, r20 ; ah * bl
    add r17, r0
    mul r21, r22 ; bh * al
    add r17, r0
ret

16-bit Square Root

This subroutine will calculate a square value of 16-bit value at r3:r2. Result is 16-bit at r17:r16 and will be rounded to nearest integer (0.5 rounds up). The value at R3:R2 will be changed.
Cycles include call & return: 95 - 102.

R17:R16 = sqrt(R3:R2)
sqrt16:

    ldi   R17,0xc0     
    ldi   R16,0x40     
    clc                
sqrt16_1:
    brcs  sqrt16_2     
    cp    R3,R16       
    brcs  sqrt16_3     
sqrt16_2:
    sub   R3,R16       
    or    R16,R17      
sqrt16_3:
    lsr   R17          
    lsl   R2
    rol   R3           
    eor   R16,R17      
    andi  R17,0xfe     
    brne  sqrt16_1    
    brcs  sqrt16_4    
    cp    R16,R3      
    brcc  sqrt16_5    
sqrt16_4:
    sbc   R2,R17          
    sbc   R3,R16          
    inc   R16             
sqrt16_5:
    lsl   R2              
    rol   R3               
    brcs  sqrt16_6         
    cp    R16,R3           
sqrt16_6:
    adc   R16,R17          
    ret

Divide 32-bit by 32-bit

This subroutine will divide 32-bit value at r19:r18:r17:R16 with 32-bit value at r23:r22:r21:R20. Result is 32-bit at

r19:r18:r17:R16 and remainder is at r19:r18:r17:R16.
This routine uses r27:r26:r25:r24 as temporary registers.

    (r19:r18:r17:R16)
    (r23:r22:r21:R20)
    -----------------:
    (r19:r18:r17:R16)    remainder: (r23:r22:r21:R20)


div32by32:
    clr    r25
    tst    r23
    breq    udi10
    ldi    r24, 8
udi1:    lsl    r16
    rol    r17
    rol    r18
    rol    r19
    rol    r25
    cp    r17, r20
    cpc    r18, r21
    cpc    r19, r22
    cpc    r25, r23
    brcs    udi2
    sub    r17, r20
    sbc    r18, r21
    sbc    r19, r22
    sbc    r25, r23
    inc    r16
udi2:    dec    r24
    brne    udi1
    mov    r20, r17
    clr    r17
    mov    r21, r18
    clr    r18
    mov    r22, r19
    clr    r19
    mov    r23, r25
    ret

udi10:    tst    r22
    breq    udi20
    ldi    r24, 16
udi11:    lsl    r16
    rol    r17
    rol    r18
    rol    r19
    rol    r25
    brcs    udi12
    cp    r18, r20
    cpc    r19, r21
    cpc    r25, r22
    brcs    udi13
udi12:    sub    r18, r20
    sbc    r19, r21
    sbc    r25, r22
    inc    r16
udi13:    dec    r24
    brne    udi11
    mov    r20, r18
    clr    r18
    mov    r21, r19
    clr    r19
    mov    r22, r25
    ret

udi20:    tst    r21
    breq    udi30
    ldi    r24, 24
udi21:    lsl    r16
    rol    r17
    rol    r18
    rol    r19
    rol    r25
    brcs    udi22
    cp    r19, r20
    cpc    r25, r21
    brcs    udi23
udi22:    sub    r19, r20
    sbc    r25, r21
    inc    r16
udi23:    dec    r24
    brne    udi21
    mov    r20, r19
    clr    r19
    mov    r21, r25
    ret

udi30:    ldi    r24, 32
udi31:    lsl    r16
    rol    r17
    rol    r18
    rol    r19
    rol    r25
    brcs    udi32
    cp    r25, r20
    brcs    udi33
udi32:    sub    r25, r20
    inc    r16
udi33:    dec    r24
    brne    udi31
    mov    r20, r25           
    ret

Calculate True RMS Value

The RMS (Root Mean Square) value of a set of values (or a continuous-time waveform) is the square root of the arithmetic mean (average) of the squares of the original values (or the square of the function that defines the continuous waveform). The RMS over all time of a periodic function is equal to the RMS of one period of the function. The RMS value of a continuous function or signal can be approximated by taking the RMS of a series of equally spaced samples. Additionally, the RMS value of various waveforms can also be determined without calculus.
Measuring the true RMS value of a waveform is not easy. Inexpensive AC voltmeters simply rectify the waveform (by passing it through a diode, for example), measure an average value of the rectified waveform, and apply a correction factor (assuming a sine wave). Such meters, therefore, are only accurate for sinusoidal waveforms. They do NOT accurately measure any other waveform shape. So-called “True” RMS meters in the past have depended on some sort of power measurement to derive the correct RMS value. Now that calculation power is so much more economically available, meters can analyze a waveform’s shape and actually mathematically calculate the correct RMS value. In general, if an AC meter does not explicitly say it gives a “true” RMS reading, you can assume that it is accurate only for a sinusoidal waveform.
To calculate true RMS, we must do the following equation.




That equation can be used for any periodic waveform, such as a sinusoidal or saw tooth waveform, allowing us to calculate the mean power delivered into a specified load. To do that, we must follow several steps.
1. Take the waveform and divide it into a “large” number of individual increments.
2. For each sample, square the voltage value.
3. Sum these squared values over all samples and then calculate their mean value.
4. Take the square root of this mean.
It is also possible to calculate the RMS power of a signal. By analogy with RMS voltage and RMS current, RMS power is the square root of the mean of the square of the power over some specified time period. This quantity, which would be expressed in units of watts (RMS), has no physical significance. However, the term "RMS power" is sometimes used in the audio industry as a synonym for "mean power" or "average power".
 


This application use ATmega8535 AVR microcontroller to sample two lines voltage that fed to channel 0 and 1 of its ADC. We use 3.2 kHz of frequency sampling generated by timer 1. So, at 50Hz power line input, we get 64 samples per period. Each sample saved at SRAM then multiplied and summed. After we calculate the mean, then a special routine will calculate the square root to find the RMS value of each voltage.

The maximum voltage can be applied to ADC input is 2.5 Vpp with +2.5 VDC offset. For 2.5 V DC or -2.5 V DC input, the output display must show the 2.50 value. To do this, we multiply the result by 100/512. So to calibrate the calculation, the above equation can be changed to:



The rms value of v0 and v1 in 8-bit hexadecimal and 3-character ASCII (X.XX volt) format are stored in following location:
Hexadecimal ASCII
v0 v0_rms v0_rms_ASCII
v1 v1_rms v1_rms_ASCII

The 1*64 elements array represents v0 during one period is stored at v0_data_index_start to v0_data_index_start+64; and the 1*64 elements array represents v0 during one period is stored at from v1_data_index_start to v1_data_index_start+64. They can be sent to PC via serial port (USART). From them, we can build a graph represents two voltages in one period like a PC-oscilloscope that show two channels waveform.
Please fetch them carefully, and make sure all data have been updated.

Note:
The result has 0.78% accuracy, so we must be care about the least significant digit; the result is suggested less than 2.25 digit format.


See also Measure true-RMS of Voltage and Current Grid
 
Download .asm and hex code


What’s next?

You can make a precise period of sampling and schedule when it happen...

What shall we do to make it more accurate? We can make it more accurate by making the sampling interval more precision (like making precision frequency generator).
We could increase the sampling frequency or increase the data length of data from 8-bit to 10 or 12 bit.

click here for more information

Divide 24-bit by 24-bit

This subroutine will divide 24-bit value at r20:r19:r18 with 24-bit value at r23:r22:r21. Result is 24-bit at r20:r19:r18 and remainder is 24-bit at r2:r1:r0.

    (r20:r19:r18)
    (r23:r22:r21)
    -------------:
    (r20:r19:r18)    remainder: (r2:r1:r0)

div24by24:
    clr     r0       
    clr     r1   
    clr     r2       
    ldi     r16,24       
    lsl     r18   
    rol     r19   
    rol     r20       
    rol     r0       
    rol     r1   
    rol     r2       
    cp      r0,r21   
    cpc     r1,r22   
    cpc     r2,r23   
    brcs    PC+5       
    inc     r18       
    sub     r0,r21   
    sbc     r1,r22   
    sbc     r2,r23   
    dec     r16   
    brne    PC-15       
    ret

Divide 16-bit by 16-bit

This subroutine will divide 16-bit value at r19:r18 with 16-bit value at r21:r20. Result is 16-bit at r19:r18 and remainder is 16-bit at r1:r0.

    (r19:r18)
    (r21:r20)
    --------- :
    (r19:r18)    mod    (r1:r0)

div16by16:
    mov     r19,r3
    mov     r18,r2       
    ldi     r22,0x0d   
    ldi     r21,0x80   
    rcall   div16by16   
    mov     r18,r2       
    mov     r19,r3       
    mov     r20,r4       

    clr     r0       
    clr     r1   
    ldi     r16,16   
    lsl     r18       
    rol     r19       
    rol     r0       
    rol     r1       
    cp      r0,r21   
    cpc     r1,r22   
    brcs    PC+4       
    inc     r18   
    sub     r0,r21   
    sbc     r1,r22   
    dec     r16       
    brne    PC-11       
    ret

Multiply 16-bit by 8-bit

This subroutine will multiply 16-bit value at r19:r18 with 8-bit value at r20. Result is 24-bit at r4:r3:r2.

  (r19:r18)
      (r20)
 ---------- X
 (r4:r3:r2)

mul16by8:
    mul     r18,r20
    mov     r2,R0
    mov     r3,R1
    mul     r19,r20
    mov     r4,R1
    add     r3,R0
    brcc    NoInc
    inc     r4
NoInc:
    ret

Divide 16-bit by 8-bit

This subroutine will divide 16-bit value at r1:r0 with 8-bit value at r3. Result is 16-bit at r5:r4.
     (r1:r0)
        (r3)
    --------- :
     (r5:r4)

div16by8:
div8:
    clr     r2
    clr     r5 
    clr     r4 
    inc     r4 
div8a:
    clc     
    rol     r0
    rol     r1
    rol     r2
    brcs    div8b
    cp      r2,r3
    brcs    div8c 
div8b:
    sub     r2,r3
    sec     
    rjmp    div8d 
div8c:
    clc     
div8d:
    rol     r4 
    rol     r5
    brcc    div8a 
    ret

Calculate Phase Difference between Voltage and Current


When capacitors or inductors are involved in an AC circuit, the current and voltage do not peak at the same time. The fraction of a period difference between the peaks expressed in degrees is said to be the phase difference. The phase difference is <= 90 degrees. It is customary to use the angle by which the voltage leads the current. This leads to a positive phase for inductive circuits since current lags the voltage in an inductive circuit. The phase is negative for a capacitive circuit since the current leads the voltage.
This application was effectively used for 50Hz or 60Hz power line. This use  Zero Cross Detector to detect the rising edge of voltage and current. The square wave represent the voltage fed to INT0 (port D pin 2) and the square wave represent the current fed to ICP1 (port D pin 6). When the first of rising edge of the first wave at INT0 occurs, timer 1 will active. This timer starts to count the period of the wave. When the rising edge of the wave at ICP1 occurs, the Input Capture Unit of microcontroller actives and saves the value of ICR1 register. And, when the next rising edge of the wave at INT0 occurs, it will stop the Timer 1. This will followed by running a special routine to measure the frequency of the voltage and the phase different between voltage and current.
This application can measure the frequency of signal (act as frequency meter), measure duration between two clock pulses (act as period meter), and measure phase difference between voltage and current. The results were saved in a specific memory location that will be described below. You can send them to LCD display or to PC while data logger. The development of this application to specific purpose application is become new really enabled and has been done.

The frequency of the signal in hexadecimal format can be read at the location referred by Frequency_voltage. This 2-byte value will represent the frequency multiplied by ten. The frequency in ASCII format can be read at the location referred by Frequency_voltage_ASCII. This 3-character represents the frequency in XX.X Hz format.
The phase difference angle between voltage and current in hexadecimal format can be read at the location referred by Phase_different_angle. The phase difference angle in ASCII format can be read at the location referred by Phase_different_angle_ASCII. This 3-character represents the frequency in degree.
In the future, from this application, we can build an AVR-microcontroller-based power factor measurement.



What’s next? You can send the data to PC like data logger....