+ Post New Thread
Page 1 of 2 1 2 LastLast
Results 1 to 20 of 36
  1. #1
    Advanced Member level 2
    Points: 3,310, Level: 13
    baileychic's Avatar
    Join Date
    Aug 2017
    Posts
    658
    Helped
    50 / 50
    Points
    3,310
    Level
    13

    ACS712-5A AC Current Reading - How to?

    ACS712-5A AC Current Reading - How to?

    I am referring Application 4 on Page 12 of the datasheet and also referring Pafe 13.

    Datasheet

    https://www.allegromicro.com/~/media...datasheet.ashx

    I am using exact 1N4448W diode mentioned in the Application 4.

    I don't want to use RF or R1.

    I amusing a 100nF for C1.

    I want to know how to get full scale reading of 0 to 5Amps.

    I am using PIC12F1840's ADC pin to read the output of the sensor interface circuit.

    I am using mikroC PRO PIC to write the code.

  2. #2
    Member level 3
    Points: 804, Level: 6

    Join Date
    Jun 2017
    Location
    near the sea
    Posts
    60
    Helped
    13 / 13
    Points
    804
    Level
    6

    Re: ACS712-5A AC Current Reading - How to?

    I am not sure what you are asking, I assume you know the nominal zero-current output voltage is VCC/2 (2.5V). The ACS712 is a 5V part as is the PIC, I don't see anything strange with the PIC's DAC so it should just work!
    The circuit is designed to only respond to positive peaks and it will ignore negative current, maybe that's your problem ?



  3. #3
    Advanced Member level 2
    Points: 3,310, Level: 13
    baileychic's Avatar
    Join Date
    Aug 2017
    Posts
    658
    Helped
    50 / 50
    Points
    3,310
    Level
    13

    Re: ACS712-5A AC Current Reading - How to?

    No, that is not my issue.

    I don't want to measure negative current.

    There is a Vf of the diode. How to compensate it to get 0 to 5Amps reading for 0 to 5Amps actual AC current?



    •   AltAdvertisement

        
       

  4. #4
    Super Moderator
    Points: 29,883, Level: 42
    andre_teprom's Avatar
    Join Date
    Nov 2006
    Location
    Brazil
    Posts
    8,917
    Helped
    1130 / 1130
    Points
    29,883
    Level
    42
    Blog Entries
    9

    Re: ACS712-5A AC Current Reading - How to?

    As clearly stated there, it is a transformerless circuit designed to do the same job of a current transformer, so it has the same issue regarding the rectifying output diode.
    --------------------------------------------------------------------------------------------------
    Part of the world that you live in, You are the part that you're giving ( Renaissance )


    1 members found this post helpful.

  5. #5
    Advanced Member level 2
    Points: 3,310, Level: 13
    baileychic's Avatar
    Join Date
    Aug 2017
    Posts
    658
    Helped
    50 / 50
    Points
    3,310
    Level
    13

    Re: ACS712-5A AC Current Reading - How to?

    I discarded application 4 as the compensation of diode Vf doesn't give correct and accurate readings.

    Instead, I just measured AC current continuously.

    Here is my code which works fine.

    Code:
    unsigned int max = 0;
    unsigned int old_max = 0;
    unsigned int min = 0;
    unsigned int old_min = 0;
    double volt = 0.0;
    double current = 0.0;
    char txt[23];
    
    void main() {
        OSCCON = 0b01101011;
        OSCTUNE = 0x00;
        
        CM1CON0 = 0x00;
        TRISA = 0xFC;
        PORTA = 0x00;
        LATA = 0x00;
        
        ANSELA = 0x10;
        ADCON1 = 0b11010000;
        
        UART1_Init(9600);
        Delay_ms(200);
        
        while(1) {
               max = 0;
               old_max = 0;
               while(1) {
                    max = (double)ADC_Read(3);
                    if(old_max < max)old_max = max;
                    else break;
               }
               
               min = 0;
               old_min = 1024;
               while(1) {
                    min = (double)ADC_Read(3);
                    if(old_min > min)old_min = min;
                    else break;
               }
               
               volt = (double)(old_max - old_min) * 5.0 / 1023.0;
               volt = (volt  / 2.0) * 0.707;
               current = volt * 1000.0 / 185.0;
               FloatToStr(current, txt);
               Ltrim(txt);
               strcat(txt," Amps\r\n");
               UART1_Write_Text(txt);
               Delay_ms(300);
        }
    }



  6. #6
    Super Moderator
    Points: 262,170, Level: 100
    Awards:
    1st Helpful Member

    Join Date
    Jan 2008
    Location
    Bochum, Germany
    Posts
    45,814
    Helped
    13931 / 13931
    Points
    262,170
    Level
    100

    Re: ACS712-5A AC Current Reading - How to?

    The code should work, but measuring peak-to-peak current magnitude is sensitive to waveform distortions and noise and in so far the least accurate way to measure AC current.



    •   AltAdvertisement

        
       

  7. #7
    Advanced Member level 2
    Points: 3,310, Level: 13
    baileychic's Avatar
    Join Date
    Aug 2017
    Posts
    658
    Helped
    50 / 50
    Points
    3,310
    Level
    13

    Re: ACS712-5A AC Current Reading - How to?

    @FvM

    Then what is the best way to measure the AC current using ACS712-05T sensor module?



  8. #8
    Super Moderator
    Points: 29,883, Level: 42
    andre_teprom's Avatar
    Join Date
    Nov 2006
    Location
    Brazil
    Posts
    8,917
    Helped
    1130 / 1130
    Points
    29,883
    Level
    42
    Blog Entries
    9

    Re: ACS712-5A AC Current Reading - How to?

    ...moreover, with the above code it is being hold the maximum peak-to-peak, not updating with further smaller values.

    what is the best way to measure the AC current using ACS712-05T sensor module?
    You should compute the average value (sum divided by amount of samples); if you had mentioned the A/C rms value you would have searched the web for the mean square formula, but I am afraid you will ask this, so there it is:

    Click image for larger version. 

Name:	rms.png 
Views:	0 
Size:	3.4 KB 
ID:	156601
    --------------------------------------------------------------------------------------------------
    Part of the world that you live in, You are the part that you're giving ( Renaissance )



  9. #9
    Advanced Member level 2
    Points: 3,310, Level: 13
    baileychic's Avatar
    Join Date
    Aug 2017
    Posts
    658
    Helped
    50 / 50
    Points
    3,310
    Level
    13

    Re: ACS712-5A AC Current Reading - How to?

    @andre_teprom

    Yes, that was what I was thinking but it is processor time consuming even with integer arithmetic.

    I need a faster method or how to speed up the processing of data in the array?


    Should I take say 10 samples in 10ms = 20 samples in 20ms (10 max samples and 10 min samples) in a max[10] and min[10] arrays and then find out

    max[0] - min[0] ... max[9] - min[9] which gives rawCurrentRaw[0]...rawCurrentRaw[9]

    rawCurrentSquared = rawCurrentRaw[0]^2.... rawCurrentRaw[9]^2

    and then

    rawCurrentRawSquaredMean = rawCurrentRawSquared / 10

    and then

    rawCurrent = sqrt(rawCurrentRawSquaredMean)

    ???

    But this is time consuming.

    I need to read 10 channels and I am using ADG731 analog MUX between 10x ACS712-05T/20T/30T combination.

    I need to trip individual load SSRs based on the channels current value. Each load channel will have a lower and upper threshold for current. If current for that channel is beyond the thresholds then SSR of that channel will be tripped in 3ms.



    •   AltAdvertisement

        
       

  10. #10
    Super Moderator
    Points: 79,262, Level: 68
    Achievements:
    7 years registered
    Awards:
    Most Frequent Poster 3rd Helpful Member

    Join Date
    Apr 2014
    Posts
    16,084
    Helped
    3644 / 3644
    Points
    79,262
    Level
    68

    Re: ACS712-5A AC Current Reading - How to?

    Hi,

    Fast code:
    What is the most time consuming with "RMS"? Usually the "square root" function.
    Then omit it.

    For example:
    If you want to compare an RMS value with 7 (let's omit the unit "Amperes" for now)
    Then "mathematically" square both sides:
    --> Compare the "average of squares" (without square root) against 7x7 = 49.

    Klaus
    Please don´t contact me via PM, because there is no time to respond to them. No friend requests. Thank you.



  11. #11
    Advanced Member level 2
    Points: 3,310, Level: 13
    baileychic's Avatar
    Join Date
    Aug 2017
    Posts
    658
    Helped
    50 / 50
    Points
    3,310
    Level
    13

    Re: ACS712-5A AC Current Reading - How to?

    @Klaus

    Okay, I will try them.

    For now, I am trying to get 1 channel working but all I get is 0.00 as readings for all the channels continuously.

    This is my code.

    Find the attached mikroC PRO PIC project + Proteus 8.9 SP2 simulation file + circuit as PDF file. I am only simulating in Proteus as of now.

    What needs to be fixed?

    Code C - [expand]
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    
    sbit Chip_Select           at LATC0_bit;
    sbit Chip_Select_Direction at TRISC0_bit;
     
    unsigned int adcVal = 0;
    unsigned int rawCurrentValue[8] = {0};
    unsigned int rawCurrentValueMax[8] = {0};
    unsigned int rawCurrentValueMin[8] = {1024};
    char i = 0;
    char j = 0;
    char txt[47];
    unsigned char flagReg = 0;
     
    sbit maxFlag at flagReg.B0;
    sbit minFlag at flagReg.B1;
     
    void Select_ADG731_Channel(unsigned char data_) {
         Chip_Select = 1;
         Delay_us(1);
         Chip_Select = 0;
         SPI1_Write(data_);
    }
     
    void interrupt() {
        if((ADIE_bit) && (ADIF_bit)) {
            ADIF_bit = 0;
            adcVal = (unsigned int)((unsigned int)(ADRESH << 8) + ADRESL);
     
            if(rawCurrentValueMax[i] <= adcVal)rawCurrentValueMax[i] = adcVal;
            else maxFlag = 1;
     
            if(rawCurrentValueMin[i] >= adcVal)rawCurrentValueMin[i] = adcVal;
            else minFlag = 1;
     
            if(!((maxFlag) && (minFlag))) {
                GO_DONE_bit = 1;
            }
        }
        
        LATD7_bit = ~LATD7_bit;
    }
     
    void main() {
        CM1CON0 = 0x00;
        CM2CON0 = 0x00;
        
        SLRCON = 0x00;
        
        ADCON1 = 0x00;
        ADCON2 = 0b10110101;
        
        ANSELA = 0x01;
        ANSELB = 0x00;
        ANSELC = 0x00;
        ANSELD = 0x00;
        ANSELE = 0x00;
     
        TRISA = 0x01;
        TRISB = 0x00;
        TRISC = 0xC0;
        TRISD = 0x00;
        TRISE = 0x00;
        
        PORTA = 0x00;
        PORTB = 0x00;
        PORTC = 0x00;
        PORTD = 0x00;
        PORTE = 0x00;
        
        LATA = 0x00;
        LATB = 0x00;
        LATC = 0x00;
        LATD = 0x00;
        LATE = 0x00;
        
        UART1_Init(9600);
     
        Chip_Select = 1;
        SPI1_Init_Advanced(_SPI_MASTER_OSC_DIV4, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_LOW, _SPI_LOW_2_HIGH);
        Delay_ms(100);
        
        ADC_Init_Advanced(_ADC_INTERNAL_REF);
        ADIE_bit = 1;
        UART1_Write_Text("Taking readings...\r\n\r\n");
        INTCON |= 0xC0;
        Select_ADG731_Channel(0);
        GO_DONE_bit = 1;
        
        while(1) {
             IntToStr(adcVal,txt);
             UART1_Write_Text(txt);
             
             if((maxFlag) && (minFlag)) {
                for(j = 0; j < 8; j++) {
                    rawCurrentValue[j] = rawCurrentValueMax[j] - rawCurrentValueMin[j];
                    sprintf(txt, "Channel [%d] = %5.2f Amps\r\n", j, (double)rawCurrentValue[j]);
                    UART1_Write_Text(txt);
                }
                
                UART1_Write_Text("\r\n");
                
                memset(rawCurrentValueMax, 0, sizeof(rawCurrentValueMax));
                memset(rawCurrentValueMin, 1024, sizeof(rawCurrentValueMin));
                
                maxFlag = 0;
                minFlag = 0;
                
                GO_DONE_bit = 1;
             }
        }
    }

    - - - Updated - - -

    Sorry, wrong file posted in the previous post.

    Consider the file attached here as the latest one. SPMM-Test-Rev-1.1.rar
    Last edited by baileychic; 21st November 2019 at 03:30.



  12. #12
    Advanced Member level 5
    Points: 11,958, Level: 26

    Join Date
    Aug 2015
    Location
    Melbourne
    Posts
    1,956
    Helped
    714 / 714
    Points
    11,958
    Level
    26

    Re: ACS712-5A AC Current Reading - How to?

    taking the peak in any 25mS period ( pk - pk divided by two ) should give accurate results for the peak current - a small RC filter on the signal before the A/D should get rid of the worst of the noise+spikes

    You can only assume rms = 0.707 * Vpk if the current is a good sine wave - often it is not

    for accuracy you need to sample at least 10 times per half cycle and compute the RMS as you go, i.e. the SQRT of the((added squared samples) / 10mS)

    for 10 samples in the half period ( 10mS ) for every half period - and then take a running average of say the last 100 half periods to get an update every second on the display or whatever

    EP



  13. #13
    Advanced Member level 2
    Points: 3,310, Level: 13
    baileychic's Avatar
    Join Date
    Aug 2017
    Posts
    658
    Helped
    50 / 50
    Points
    3,310
    Level
    13

    Re: ACS712-5A AC Current Reading - How to?

    I will update the display once per second only.

    The relays if needed to be tripped has to be within 3ms after getting the rawCurrentValues.

    I will try both pk-to-pk method and rms method with integer only calculations. Whichever works best with the hardware for different known loads, I will use that code.

    The current issue is not able to get a non-zero value for rawCurrentMax[] and rawCurrentMin[].

    Code:
    sbit Chip_Select           at LATC0_bit;
    sbit Chip_Select_Direction at TRISC0_bit;
    
    unsigned int adcVal = 0;
    unsigned int rawCurrentValue[8] = {0};
    unsigned int rawCurrentValueMax[8] = {0};
    unsigned int rawCurrentValueMin[8] = {1024};
    char i = 0;
    char j = 0;
    char txt[47];
    unsigned char flagReg = 0;
    
    sbit maxFlag at flagReg.B0;
    sbit minFlag at flagReg.B1;
    
    void Select_ADG731_Channel(unsigned char data_) {
         Chip_Select = 1;
         Delay_us(1);
         Chip_Select = 0;
         SPI1_Write(data_);
    }
    
    void interrupt() {
        if((ADIE_bit) && (ADIF_bit)) {
            ADIF_bit = 0;
            adcVal = (unsigned int)((unsigned int)(ADRESH << 8) + ADRESL);
    
            if(rawCurrentValueMax[i] <= adcVal)rawCurrentValueMax[i] = adcVal;
            else maxFlag = 1;
    
            if(rawCurrentValueMin[i] >= adcVal)rawCurrentValueMin[i] = adcVal;
            else minFlag = 1;
    
            if(!((maxFlag) && (minFlag))) {
                GO_DONE_bit = 1;
            }
        }
        
        LATD7_bit = ~LATD7_bit;
    }
    
    void main() {
        CM1CON0 = 0x00;
        CM2CON0 = 0x00;
        
        SLRCON = 0x00;
        
        ADCON1 = 0x00;
        ADCON2 = 0b10110101;
        
        ANSELA = 0x01;
        ANSELB = 0x00;
        ANSELC = 0x00;
        ANSELD = 0x00;
        ANSELE = 0x00;
    
        TRISA = 0x01;
        TRISB = 0x00;
        TRISC = 0xC0;
        TRISD = 0x00;
        TRISE = 0x00;
        
        PORTA = 0x00;
        PORTB = 0x00;
        PORTC = 0x00;
        PORTD = 0x00;
        PORTE = 0x00;
        
        LATA = 0x00;
        LATB = 0x00;
        LATC = 0x00;
        LATD = 0x00;
        LATE = 0x00;
        
        UART1_Init(9600);
    
        Chip_Select = 1;
        SPI1_Init_Advanced(_SPI_MASTER_OSC_DIV4, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_LOW, _SPI_LOW_2_HIGH);
        Delay_ms(100);
        
        ADC_Init_Advanced(_ADC_INTERNAL_REF);
        ADIE_bit = 1;
        UART1_Write_Text("Taking readings...\r\n\r\n");
        INTCON |= 0xC0;
        Select_ADG731_Channel(0);
        GO_DONE_bit = 1;
        
        while(1) {
             sprintf(txt, "adcVal = %d\r\n\r\n", adcVal);
             UART1_Write_Text(txt);
             
             if((maxFlag) && (minFlag)) {
                for(j = 0; j < 8; j++) {
                    rawCurrentValue[j] = rawCurrentValueMax[j] - rawCurrentValueMin[j];
                    sprintf(txt, "Channel [%d] = %5.2f Amps\r\n", j, (double)rawCurrentValue[j]);
                    UART1_Write_Text(txt);
                }
                
                UART1_Write_Text("\r\n");
                
                memset(rawCurrentValueMax, 0, sizeof(rawCurrentValueMax));
                memset(rawCurrentValueMin, 1024, sizeof(rawCurrentValueMin));
                
                maxFlag = 0;
                minFlag = 0;
                
                GO_DONE_bit = 1;
             }
        }
    }
    What is wrong?



  14. #14
    Advanced Member level 5
    Points: 11,958, Level: 26

    Join Date
    Aug 2015
    Location
    Melbourne
    Posts
    1,956
    Helped
    714 / 714
    Points
    11,958
    Level
    26

    Re: ACS712-5A AC Current Reading - How to?

    hello Ozzie, sorry reading code is not my long suit - I write the algorithms that are then coded by others ( less **** ups that way ) keep reading and I'm sure whatever is sticking/keeping zero in the variables / registers will shine thru ...



  15. #15
    Super Moderator
    Points: 79,262, Level: 68
    Achievements:
    7 years registered
    Awards:
    Most Frequent Poster 3rd Helpful Member

    Join Date
    Apr 2014
    Posts
    16,084
    Helped
    3644 / 3644
    Points
    79,262
    Level
    68

    Re: ACS712-5A AC Current Reading - How to?

    Hi,

    Should I take say 10 samples in 10ms = 20 samples in 20ms
    If current for that channel is beyond the thresholds then SSR of that channel will be tripped in 3ms.
    A rather curious requirement.
    The measurement may take 10ms ... or 20ms --> a bit more than 3ms tolerance
    The SSR switching time maybe is 10ms or longer --> longer than 3ms
    At 50Hz it takes 10ms from one peak to the other --> longer than 3ms
    ******
    A single peak value:
    Consider that some appliance nearby will cause some switching noise in mains... (let's say a refrigerator) ...it will cause some voltage noise and for sure some current noise. Mainly wired noise, but you also need to consider radiated noise.
    Additionally thunderstorms will cause noise...and other unexpected sources of noise.
    Thus you need to consider uncontrolled peaks in your measurement values.

    I'm designing industrial equippment ... using algorithms to detect overcurrent...then in case of overcurrent we have to switch OFF.
    In one plant there are chemical processes, switching OFF the power supply makes the production batch to be lost. A loss of 40,000Euro.
    You recognice that the company does not want "erroneous switch OFF".
    One industrial standard (algorithm) is via I^2t.. trip times that depend on the value of overcurrent.
    I've never seen an industrial requirement for "3ms".

    Now maybe you have very sensitive parts, that really require that fast switch OFF time .... then for sure you must not use an SSR, because it is much slower.
    I hope you understand my worries. In my eyes the requirements do not make sense.

    Klaus
    Please don´t contact me via PM, because there is no time to respond to them. No friend requests. Thank you.



  16. #16
    Advanced Member level 4
    Points: 8,249, Level: 21
    Achievements:
    7 years registered
    paulfjujo's Avatar
    Join Date
    Jun 2008
    Location
    France 01120
    Posts
    1,326
    Helped
    270 / 270
    Points
    8,249
    Level
    21

    Re: ACS712-5A AC Current Reading - How to?

    Quote Originally Posted by baileychic View Post
    I discarded application 4 as the compensation of diode Vf doesn't give correct and accurate readings.

    Instead, I just measured AC current continuously.

    Here is my code which works fine.

    Code:
    unsigned int max = 0;
    unsigned int old_max = 0;
    unsigned int min = 0;
    unsigned int old_min = 0;
    double volt = 0.0;
    double current = 0.0;
    char txt[23];
    
    void main() {
        OSCCON = 0b01101011;
        OSCTUNE = 0x00;
        
        CM1CON0 = 0x00;
        TRISA = 0xFC;
        PORTA = 0x00;
        LATA = 0x00;
        
        ANSELA = 0x10;
        ADCON1 = 0b11010000;
        
        UART1_Init(9600);
        Delay_ms(200);
        
        while(1) {
               max = 0;
               old_max = 0;
               while(1) {
                    max = (double)ADC_Read(3);
                    if(old_max < max)old_max = max;
                    else break;
               }
               
               min = 0;
               old_min = 1024;
               while(1) {
                    min = (double)ADC_Read(3);
                    if(old_min > min)old_min = min;
                    else break;
               }
               
               volt = (double)(old_max - old_min) * 5.0 / 1023.0;
               volt = (volt  / 2.0) * 0.707;
               current = volt * 1000.0 / 185.0;
               FloatToStr(current, txt);
               Ltrim(txt);
               strcat(txt," Amps\r\n");
               UART1_Write_Text(txt);
               Delay_ms(300);
        }
    }
    i am not sure your code gcould gives good result because
    Code:
    unsigned int max = 0;
    unsigned int old_max = 0;
    unsigned int min = 0;
    unsigned int old_min = 0;
    
    
    
    max = (double)ADC_Read(3);  ?
     
    min = (double)ADC_Read(3);  ?

    you must declare all variables in double format .
    Compiler can not tanspose a double into an int ...


    1 members found this post helpful.

  17. #17
    Advanced Member level 2
    Points: 3,310, Level: 13
    baileychic's Avatar
    Join Date
    Aug 2017
    Posts
    658
    Helped
    50 / 50
    Points
    3,310
    Level
    13

    Re: ACS712-5A AC Current Reading - How to?

    I tried to implement a non-interrupt based code for 8x channels and it somewhat works.

    There are some glitches that are some channels values fluctuate a little between two values and some random channels values go beyond the range like 6xx.xx Amps.

    This is the latest code and the project and its result screenshot are attached here.

    Code C - [expand]
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    
    sbit Chip_Select           at LATC0_bit;
    sbit Chip_Select_Direction at TRISC0_bit;
     
    unsigned int max[8] = {0};
    unsigned int old_max[8] = {0};
    unsigned int min[8] = {0};
    unsigned int old_min[8] = {0};
    double volt = 0.0;
    double current = 0.0;
    unsigned int i = 0;
    char txt[67];
     
    void Select_ADG731_Channel(unsigned char data_) {
         Chip_Select = 0;
         SPI1_Write(data_);
         Chip_Select = 1;
    }
     
    void Clear_Arrays() {
        memset(max, 0, sizeof(max));
        memset(min, 0, sizeof(min));
        memset(old_max, 0, sizeof(old_max));
        memset(old_min, 0, sizeof(old_min));
    }
     
    void main() {
        CM1CON0 = 0x00;
        CM2CON0 = 0x00;
     
        SLRCON = 0x00;
     
        ADCON0 = 0x00;
        ADCON1 = 0x00;
        ADCON2 = 0b10110101;
     
        ANSELA = 0x01;
        ANSELB = 0x00;
        ANSELC = 0x00;
        ANSELD = 0x00;
        ANSELE = 0x00;
     
        TRISA = 0xC1;
        TRISB = 0x00;
        TRISC = 0xC0;
        TRISD = 0x00;
        TRISE = 0x00;
     
        PORTA = 0x00;
        PORTB = 0x00;
        PORTC = 0x00;
        PORTD = 0x00;
        PORTE = 0x00;
     
        LATA = 0x00;
        LATB = 0x00;
        LATC = 0x00;
        LATD = 0x00;
        LATE = 0x00;
     
        UART1_Init(9600);
     
        Chip_Select = 1;
        Chip_Select_Direction = 0;
        SPI1_Init_Advanced(_SPI_MASTER_OSC_DIV16, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_LOW, _SPI_HIGH_2_LOW);
        Delay_ms(100);
        
        UART1_Write_Text("Taking readings...\r\n\r\n");
        Clear_Arrays();
     
        while(1) {
               i = 0;
               while(i < 8) {
                   Select_ADG731_Channel(i);
                   Delay_us(50);
                   
                   max[i] = 0;
                   old_max[i] = 0;
                   while(1) {
                        max[i] = ADC_Read(0);
                        Delay_us(10);
                        if(old_max[i] < max[i])old_max[i] = max[i];
                        else break;
                   }
                   
                   min[i] = 0;
                   old_min[i] = 1024;
                   while(1) {
                        min[i] = ADC_Read(0);
                        Delay_us(10);
                        if(old_min[i] > min[i])old_min[i] = min[i];
                        else break;
                   }
                   
                   i++;
               }
     
               for(i = 0; i < 8; i++) {
                   volt = (double)(old_max[i] - old_min[i]) * 5.0 / 1023.0;
                   volt = (volt / 2.0) * 0.707;
                   current = volt * 1000.0 / 185.0;
                   sprintf(txt, "Channel [%u] = %5.2f Amps\r\n", i, current);
                   UART1_Write_Text(txt);
               }
               
               UART1_Write_Text("\r\n");
               Clear_Arrays();
        }
    }



    •   AltAdvertisement

        
       

  18. #18
    Super Moderator
    Points: 79,262, Level: 68
    Achievements:
    7 years registered
    Awards:
    Most Frequent Poster 3rd Helpful Member

    Join Date
    Apr 2014
    Posts
    16,084
    Helped
    3644 / 3644
    Points
    79,262
    Level
    68

    Re: ACS712-5A AC Current Reading - How to?

    Hi,

    I tried to implement a non-interrupt based code
    I don´t understand why "non interrupt" solution.

    In my eyes this is a classical application for interrupt based processing.
    I personally like the interrupt solution, because I find it much easier to keep timings, it gives more precise results and it leaves maybe more than 80% of your processing power for the main loop.
    .. and I don´t find it difficult to implement.

    A solution with running average or biquad filtering means just a couple of MULTIPLY / ADD / SUBTRACT ... and the result will be reliable and stable. And you may get the "overcurrent" result after each conversion...(not after 8 conversions or after 10ms or after 20ms.. or whatever you decide)
    You do the processing of one channel while the conversion of the next channel is running.

    Klaus
    Please don´t contact me via PM, because there is no time to respond to them. No friend requests. Thank you.



  19. #19
    Advanced Member level 2
    Points: 3,310, Level: 13
    baileychic's Avatar
    Join Date
    Aug 2017
    Posts
    658
    Helped
    50 / 50
    Points
    3,310
    Level
    13

    Re: ACS712-5A AC Current Reading - How to?

    What should be the minimum delay between switching channels of ADG731?

    Currently, in the new code, I am using 1us.

    I am now trying to implement the code using interrupts and want to read 8x channels min in 10ms and max in 10ms.

    I am thinking about using only the ADC interrupt.

    I will first implement only the pk-to-pk method. If that works fine then I will implement the RMS method using interrupts.

    This way the reading + processing should not exceed 20ms + 10ms (64 MHz Oscillator) and I will be able to trip the faulty load line within 30ms of fault.



  20. #20
    Advanced Member level 5
    Points: 11,958, Level: 26

    Join Date
    Aug 2015
    Location
    Melbourne
    Posts
    1,956
    Helped
    714 / 714
    Points
    11,958
    Level
    26

    Re: ACS712-5A AC Current Reading - How to?

    sounds like a plan ...



--[[ ]]--