Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Medição da Tensão Vcc do Arduino ATmega328 - Gustavo Murta 01/ago/2015 - REV2 LekoBH
- // http://provideyourown.com/2012/secret-arduino-voltmeter-measure-battery-voltage/
- // https://code.google.com/p/tinkerit/wiki/SecretVoltmeter
- //Para definir o tipo do sensor descomente o sensor que ira ser usado e deixe comentado os outros.
- #define ACS712x05B // Usar para sensor 5 Amperes
- //#define ACS712x20A // Usar para sensor 20 Amperes
- //#define ACS712x30A // Usar para sensor 30 Amperes
- long VCC = 0.00;
- float VCCR = 0.00;
- void setup() {
- Serial.begin(9600);
- }
- void loop() {
- VCC= readVcc();
- Serial.print("Vcc= " );
- Serial.print( VCC, DEC );
- Serial.println(" mV" );
- float leitura = captura();
- Serial.print(", VRMS= " );
- Serial.print( leitura, 2 );
- Serial.print(" V" );
- float corrente = converteI(leitura);
- Serial.print(", IRMS= " );
- Serial.print( corrente, 2 );
- Serial.print(" A" );
- }
- //--------------------------------------------------------------------------------------------
- //Calcula o valor real de VCC com base no valor da referencia de 1.1V retorno em milivolts
- //--------------------------------------------------------------------------------------------
- long readVcc() {
- // Lê o valor da referencia de 1.1V comparado com o AVcc
- // Coloca a referência em VCC e mede o valor da referencia interna de 1.1V
- #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
- ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
- #elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
- ADMUX = _BV(MUX5) | _BV(MUX0);
- #elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
- ADMUX = _BV(MUX3) | _BV(MUX2);
- #else
- ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
- #endif
- unsigned int media = 0;
- delay(2); // Espera estabilizar a referência
- //despresa a primeira leitura
- ADCSRA |= _BV(ADSC); // Inicia conversão
- while (bit_is_set(ADCSRA,ADSC)); // Aguarda o termino da conversão descarta valor
- for (int i = 0; i<100; i++) { //loop para usar uma media dos valores
- ADCSRA |= _BV(ADSC); // Inicia conversão
- while (bit_is_set(ADCSRA,ADSC)); // Aguarda o termino da conversão
- uint8_t low = ADCL; // Tem que ler primeiro o Low - ele trava o valor de ADCH
- uint8_t high = ADCH; // Destrava os dois
- long result = (high<<8) | low; // pega valor do conversor
- media += result; // soma todos os valores
- }
- long result = 112530000L / media; // Calcula Vcc (V); 1125300 = 1.1*1023**1000*100(amostras)
- return result; // Vcc in millivolts
- }
- //--------------------------------------------------------------------------------------------
- //Recebe o valor em tensao e corrige ele como se fosse em 5.00V
- //Recebe um valor entre 0 a VCC real (ex.: 5.38V) e converte para a faixa de 0 a 5.00v
- //--------------------------------------------------------------------------------------------
- float scalaACS (long valor, float vcc) {
- //float tensao = float(valor * (vcc / 1023.00)); //converte paea tensao
- //float Viout = float ((5.00/vcc)*tensao); // retorna o valor do acs como ajustado para 5v
- float Viout = float(valor * (5.00 / 1023.00));
- return Viout; // retorna o valor equivalente VIout para 5 V em millivolts
- }
- //--------------------------------------------------------------------------------------------
- //Recebe o valor em tensao e converte para corrente
- //Garantir antes de usar que os valores ja foram ajustados como se fosse 5.00V
- //--------------------------------------------------------------------------------------------
- float converteI (float valor) {
- #if defined (ACS712x05B)
- float Sens = 0.185; //v por A;
- #elif defined (ACS712x20A)
- float Sens = 0.104; //v por A;
- #elif defined (ACS712x30A)
- float Sens = 0.069; //v por A;
- #else
- int Sens = 0;
- #endif
- float Iout = valor/Sens; // retorna o valor do acs como ajustado para 5v
- return Iout; // retorna o valor equivalente VIout para 5 V em millivolts
- }
- //--------------------------------------------------------------------------------------------
- //Aguarda passagem por zero (TRAVA)
- //Melhora a chance de uma boa captura de dados
- //--------------------------------------------------------------------------------------------
- void passagem () {
- boolean st=false; //an indicator to exit the while loop
- unsigned long start = millis(); //Guarda tempo para timeout segurança.
- while(st==false) //the while loop...
- {
- int startV = analogRead(A0); //le o valor de A0
- if ((startV < (1024*0.55)) && (startV > (1024*0.45))) st=true; //testa se esta proximo de zero
- if ((millis()-start)>200) st = true; // se passou mais de 200ms deixa seguir TIMEOUT
- }
- }
- //--------------------------------------------------------------------------------------------
- //Captura os Dados "supondo algo proximo à 10KSPS"
- //Captura n amostras rapidamente e depois trata os dados
- //--------------------------------------------------------------------------------------------
- float captura () {
- #define amost 500 //define o numero de amostras
- VCC= readVcc();
- float VCCR = VCC/1000.000;
- // VCC = VCCR;
- int amostras[amost]; //cria o buffer de dados para guardar os dados
- passagem (); //espera um momento baum para iniciar a captura ou time out
- for (int i = 0; i<amost; i++) { //loop guardar os valores sem interferencias ou delays
- amostras[i] = analogRead(A0);
- }
- // Inicializa as variaveis locais
- long int mediacap = 0;
- int maximo = 0;
- int minimo = 1023;
- int borda = 0;
- //loop calcular max e min e achar a ultima passagem pelo valor inicial
- for (int i = 0; i<amost; i++) {
- maximo = max(maximo, amostras[i]);
- minimo = min(minimo, amostras[i]);
- if ( ((amostras[i] > amostras[0]) && (amostras[i+1] <= amostras[0])) || ((amostras[i] < amostras[0]) && (amostras[i+1] >= amostras[0]))){
- if (i < amost-2) borda = i;
- }
- }
- float vpp = scalaACS((maximo-minimo), VCCR); //Calcula tensao pico a pico ajustada baseado no VCC real
- //Serial.print(" vccR =" );
- //Serial.println( VCCR, 3 );
- //Serial.print(", vpp =" );
- //Serial.println( vpp );
- //loop calcular valor médio dentro da janela correta
- for (int i = 0; i<borda; i++) { //loop ate o valor da ultima borda (passagem por zero)
- mediacap += amostras[i]; //Soma todos os valoras da janela
- }
- mediacap = mediacap/(borda); //Calculo da media dos valores
- float vmediacap = scalaACS(mediacap, VCCR); // Ajuste o valor baseado no VCC real
- //Serial.print(", vmediacap=" );
- //Serial.println( vmediacap );
- //loop calcular valor RMS ALTERNADO dentro da janela correta
- float rms = 0.00;
- for (int i = 0; i<borda; i++) { //loop ate o valor da ultima borda (passagem por zero)
- float vrms = float(scalaACS(amostras[i], VCCR)-vmediacap); // Ajuste o valor de cada amostra baseado no VCC real
- rms += (vrms*vrms);
- }
- rms = sqrt(rms/borda); //Calcula o valor RMS Alternado
- float vrms =rms + (vmediacap-2.500);// Alternado + continuo TRUE RMS
- //Serial.print(", vrms=" );
- //Serial.println( vrms );
- float vmulti = float((vpp/2)* 0.707); //tensao alternada medida na saida do ACS
- Serial.print("Vmultimetro = " );
- Serial.print( vmulti );
- return vrms; // retorna o valor rms alternado + continuo
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement