Advertisement
lekobh

RMS rev2

Aug 2nd, 2015
276
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.28 KB | None | 0 0
  1. // Medição da Tensão Vcc do Arduino ATmega328 - Gustavo Murta 01/ago/2015 - REV2 LekoBH
  2. // http://provideyourown.com/2012/secret-arduino-voltmeter-measure-battery-voltage/
  3. // https://code.google.com/p/tinkerit/wiki/SecretVoltmeter
  4.  
  5. //Para definir o tipo do sensor descomente o sensor que ira ser usado e deixe comentado os outros.
  6.  #define ACS712x05B // Usar para sensor 5 Amperes
  7.  //#define ACS712x20A // Usar para sensor 20 Amperes
  8.  //#define ACS712x30A // Usar para sensor 30 Amperes
  9.  
  10.  long VCC = 0.00;
  11.  float VCCR = 0.00;
  12.  void setup() {
  13.   Serial.begin(9600);
  14.  
  15. }
  16. void loop() {
  17.   VCC= readVcc();
  18.   Serial.print("Vcc= " );
  19.   Serial.print( VCC, DEC );
  20.   Serial.println(" mV" );
  21.  
  22.  
  23.   float leitura = captura();
  24.   Serial.print(", VRMS= " );
  25.   Serial.print( leitura, 2 );
  26.   Serial.print(" V" );  
  27.   float corrente = converteI(leitura);
  28.   Serial.print(", IRMS= " );
  29.   Serial.print( corrente, 2 );
  30.   Serial.print(" A"  );  
  31. }
  32.  
  33.  
  34. //--------------------------------------------------------------------------------------------
  35. //Calcula o valor real de VCC com base no valor da referencia de 1.1V retorno em milivolts
  36. //--------------------------------------------------------------------------------------------
  37. long readVcc() {
  38.   // Lê o valor da referencia de  1.1V comparado com o AVcc
  39.   // Coloca a referência em VCC e mede o valor da referencia interna de 1.1V
  40.   #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  41.     ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  42.   #elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
  43.     ADMUX = _BV(MUX5) | _BV(MUX0);
  44.   #elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
  45.     ADMUX = _BV(MUX3) | _BV(MUX2);
  46.   #else
  47.     ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  48.   #endif  
  49.  
  50.   unsigned int media = 0;
  51.   delay(2);                                       // Espera estabilizar a referência
  52.  
  53.        //despresa a primeira leitura
  54.        ADCSRA |= _BV(ADSC);                       // Inicia conversão
  55.        while (bit_is_set(ADCSRA,ADSC));           // Aguarda o termino da conversão descarta valor
  56.  
  57.   for (int i = 0; i<100; i++) {                   //loop para usar uma media dos valores
  58.        ADCSRA |= _BV(ADSC);                       // Inicia conversão
  59.        while (bit_is_set(ADCSRA,ADSC));           // Aguarda o termino da conversão
  60.  
  61.        uint8_t low  = ADCL;                        // Tem que ler primeiro o Low - ele trava o valor de ADCH  
  62.        uint8_t high = ADCH;                        // Destrava os dois
  63.  
  64.        long result = (high<<8) | low;              // pega valor do conversor
  65.        media += result;                            // soma todos os valores
  66.      }
  67.  
  68.   long result = 112530000L / media;                // Calcula Vcc (V); 1125300 = 1.1*1023**1000*100(amostras)
  69.   return result;                                   // Vcc in millivolts
  70. }
  71.  
  72. //--------------------------------------------------------------------------------------------
  73. //Recebe o valor em tensao e corrige ele como se fosse em 5.00V
  74. //Recebe um valor entre 0 a VCC real (ex.: 5.38V) e converte para a faixa de 0 a 5.00v
  75. //--------------------------------------------------------------------------------------------
  76. float scalaACS (long valor, float vcc) {
  77.  
  78.   //float tensao = float(valor * (vcc / 1023.00));    //converte paea tensao
  79.   //float Viout = float ((5.00/vcc)*tensao);         // retorna o valor do acs como ajustado para 5v
  80.   float Viout = float(valor * (5.00 / 1023.00));          
  81.  
  82.   return Viout;                                    // retorna o valor equivalente VIout para 5 V em millivolts
  83. }
  84.  
  85. //--------------------------------------------------------------------------------------------
  86. //Recebe o valor em tensao e converte para corrente
  87. //Garantir antes de usar que os valores ja foram ajustados como se fosse 5.00V
  88. //--------------------------------------------------------------------------------------------
  89. float converteI (float valor) {
  90.   #if defined (ACS712x05B)
  91.     float Sens = 0.185; //v por A;
  92.   #elif defined (ACS712x20A)
  93.     float Sens = 0.104; //v por A;
  94.   #elif defined (ACS712x30A)
  95.     float Sens = 0.069; //v por A;
  96.   #else
  97.     int Sens = 0;
  98.   #endif  
  99.  
  100.   float Iout = valor/Sens;               // retorna o valor do acs como ajustado para 5v
  101.   return Iout;                                     // retorna o valor equivalente VIout para 5 V em millivolts
  102. }
  103.  
  104. //--------------------------------------------------------------------------------------------
  105. //Aguarda passagem por zero (TRAVA)
  106. //Melhora a chance de uma boa captura de dados
  107. //--------------------------------------------------------------------------------------------
  108. void passagem () {
  109.  boolean st=false;                                //an indicator to exit the while loop
  110.  unsigned long start = millis();                  //Guarda tempo para timeout segurança.
  111.  while(st==false)                                 //the while loop...
  112.   {
  113.     int startV = analogRead(A0);                  //le o valor de A0
  114.      if ((startV < (1024*0.55)) && (startV > (1024*0.45))) st=true;  //testa se esta proximo de zero
  115.      if ((millis()-start)>200) st = true;         // se passou mais de 200ms deixa seguir TIMEOUT
  116.   }
  117. }
  118.  
  119. //--------------------------------------------------------------------------------------------
  120. //Captura os Dados "supondo algo proximo à 10KSPS"
  121. //Captura n amostras rapidamente e depois trata os dados
  122. //--------------------------------------------------------------------------------------------
  123. float captura () {
  124. #define amost 500                                        //define o numero de amostras
  125.   VCC= readVcc();
  126.   float VCCR = VCC/1000.000;
  127.  // VCC = VCCR;
  128.   int amostras[amost];                                   //cria o buffer de dados para guardar os dados
  129.   passagem ();                                           //espera um momento baum para iniciar a captura ou time out
  130.   for (int i = 0; i<amost; i++) {                        //loop guardar os valores sem interferencias ou delays
  131.     amostras[i] = analogRead(A0);
  132.   }
  133.   // Inicializa as variaveis locais
  134.   long int mediacap = 0;
  135.   int maximo = 0;
  136.   int minimo = 1023;
  137.   int borda = 0;
  138.  
  139.   //loop calcular max e min e achar a ultima passagem pelo valor inicial
  140.   for (int i = 0; i<amost; i++) {  
  141.    
  142.       maximo = max(maximo, amostras[i]);
  143.       minimo = min(minimo, amostras[i]);
  144.       if ( ((amostras[i] > amostras[0]) && (amostras[i+1] <= amostras[0])) || ((amostras[i] < amostras[0]) && (amostras[i+1] >= amostras[0]))){
  145.             if (i < amost-2) borda = i;
  146.          }
  147.   }
  148.   float vpp = scalaACS((maximo-minimo), VCCR);                          //Calcula tensao pico a pico ajustada baseado no VCC real
  149.   //Serial.print(" vccR =" );
  150.   //Serial.println( VCCR, 3 );    
  151.   //Serial.print(", vpp =" );
  152.   //Serial.println( vpp );    
  153.    
  154.   //loop calcular valor médio dentro da janela correta
  155.   for (int i = 0; i<borda; i++) {                                     //loop ate o valor da ultima borda (passagem por zero)
  156.        mediacap += amostras[i];                                       //Soma todos os valoras da janela
  157.   }
  158.   mediacap = mediacap/(borda);                                       //Calculo da media dos valores  
  159.   float vmediacap = scalaACS(mediacap, VCCR);                         // Ajuste o valor baseado no VCC real
  160.   //Serial.print(", vmediacap=" );
  161.   //Serial.println( vmediacap );    
  162.    
  163.   //loop calcular valor RMS ALTERNADO dentro da janela correta
  164.   float rms = 0.00;
  165.   for (int i = 0; i<borda; i++) {                                    //loop ate o valor da ultima borda (passagem por zero)
  166.       float vrms = float(scalaACS(amostras[i], VCCR)-vmediacap);      // Ajuste o valor de cada amostra baseado no VCC real
  167.       rms += (vrms*vrms);
  168.       }
  169.   rms =  sqrt(rms/borda); //Calcula o valor RMS Alternado
  170.  
  171.  
  172.   float vrms =rms + (vmediacap-2.500);// Alternado + continuo TRUE RMS
  173.   //Serial.print(", vrms=" );
  174.   //Serial.println( vrms );    
  175.    
  176.   float vmulti = float((vpp/2)* 0.707); //tensao alternada medida na saida do ACS
  177.   Serial.print("Vmultimetro = " );
  178.   Serial.print( vmulti );  
  179.  
  180.   return vrms; // retorna o valor rms alternado + continuo
  181.  }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement