Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Medições de tensão Vout com carga - sensor ACS712-30A com Arduino ATmega328 - Gustavo Murta 01/ago/2015
- // http://provideyourown.com/2012/secret-arduino-voltmeter-measure-battery-voltage/
- // https://code.google.com/p/tinkerit/wiki/SecretVoltmeter
- // https://github.com/openenergymonitor/EmonLib
- //--------------------------------------------------------------------------------------
- // Variable declaration for emon_calc procedure
- //--------------------------------------------------------------------------------------
- int sampleV; //sample_ holds the raw analog read value
- //int sampleI;
- double lastFilteredV,filteredV; //Filtered_ is the raw analog value minus the DC offset
- // double filteredI;
- double offsetV; //Low-pass filter output
- // double offsetI; //Low-pass filter output
- double phaseShiftedV; //Holds the calibrated phase shifted voltage.
- double sqV,sumV,sqI,sumI,instP,sumP; //sq = squared, sum = Sum, inst = instantaneous
- int startV; //Instantaneous voltage at start of sample window.
- boolean lastVCross, checkVCross; //Used to measure number of times threshold is crossed.
- long readVcc() {
- // Leitura da tensão de Referencia de 1.1V para calcular AVcc
- // Configura Referencia do ADC para Vcc
- ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
- delay(2); // Aguarda estabilização da Tensão Vref
- ADCSRA |= _BV(ADSC); // Inicia a conversão ADC
- while (bit_is_set(ADCSRA,ADSC)); // Começa a leitura
- uint8_t low = ADCL; // Lê primeiro o registrador ADCL e depois o ADCH
- uint8_t high = ADCH; // destrava os dois registradores
- long result = (high<<8) | low; // Formata o resultado
- // Conversor ADC do Arduino já calibrado
- // Primeiro ReadVcc = 1.1 * 1023 * 1000 > Vcc = 4957 mV
- // Com Multimetro Vcc = 5000 mV e Vref = 2500 mV
- // Com Arduino Vcc = 5000 mV e Vout = 2497 mV
- result = 1135061L / result; // Cálculo do Vcc (em mV) 1135061 = 1.109542*1023*1000
- return result; // Vcc em millivolts
- }
- unsigned int crossCount = 0; // Usado para determinar a quantidade de passagens por zero
- unsigned int numberOfSamples = 0; // Quantidade de amostragens
- unsigned int crossings = 20; // quantidade de semiciclos da senoide
- int timeout = 2000 ;
- define ADC_BITS 10
- define ADC_COUNTS (1<<ADC_BITS)
- //-------------------------------------------------------------------------------------------------------------------------
- // 1) Waits for the waveform to be close to 'zero' (mid-scale adc) part in sin curve.
- //-------------------------------------------------------------------------------------------------------------------------
- boolean st=false; //an indicator to exit the while loop
- unsigned long start = millis(); //millis()-start makes sure it doesnt get stuck in the loop if there is an error.
- while(st==false) //the while loop...
- {
- startV = analogRead(A2); //using the voltage waveform
- if ((startV < (ADC_COUNTS*0.55)) && (startV > (ADC_COUNTS*0.45))) st=true; //check its within range
- if ((millis()-start)>timeout) st = true;
- }
- //-------------------------------------------------------------------------------------------------------------------------
- // 2) Main measurement loop
- //-------------------------------------------------------------------------------------------------------------------------
- start = millis();
- while ((crossCount < crossings) && ((millis()-start)<timeout))
- {
- numberOfSamples++; // Incrementa o número de amostragens
- //lastFilteredV = filteredV; // Used for delay/phase compensation
- //-----------------------------------------------------------------------------
- // A) Medições de Tensões no pino A2 do Conversor ADC
- //-----------------------------------------------------------------------------
- sampleV = analogRead(A2); //Read in raw voltage signal
- //-----------------------------------------------------------------------------
- // B) Apply digital low pass filters to extract the 2.5 V or 1.65 V dc offset,
- // then subtract this - signal is now centred on 0 counts.
- //-----------------------------------------------------------------------------
- offsetV = offsetV + ((sampleV-offsetV)/1024);
- filteredV = sampleV - offsetV;
- //-----------------------------------------------------------------------------
- // C) Root-mean-square method voltage
- //-----------------------------------------------------------------------------
- sqV= filteredV * filteredV; //1) square voltage values
- sumV += sqV; //2) sum
- //-----------------------------------------------------------------------------
- // D) Phase calibration
- //-----------------------------------------------------------------------------
- //phaseShiftedV = lastFilteredV + PHASECAL * (filteredV - lastFilteredV);
- //-----------------------------------------------------------------------------
- // E) Instantaneous power calc
- //-----------------------------------------------------------------------------
- //instP = phaseShiftedV * filteredI; //Instantaneous Power
- //sumP +=instP; //Sum
- //-----------------------------------------------------------------------------
- // F) Find the number of times the voltage has crossed the initial voltage
- // - every 2 crosses we will have sampled 1 wavelength
- // - so this method allows us to sample an integer number of half wavelengths which increases accuracy
- //-----------------------------------------------------------------------------
- lastVCross = checkVCross;
- if (sampleV > startV) checkVCross = true;
- else checkVCross = false;
- if (numberOfSamples==1) lastVCross = checkVCross;
- if (lastVCross != checkVCross) crossCount++;
- }
- //-------------------------------------------------------------------------------------------------------------------------
- // 3) Post loop calculations
- //-------------------------------------------------------------------------------------------------------------------------
- //Calculation of the root of the mean of the voltage and current squared (rms)
- //Calibration coefficients applied.
- double V_RATIO = VCAL *((SupplyVoltage/1000.0) / (ADC_COUNTS));
- Vrms = V_RATIO * sqrt(sumV / numberOfSamples);
- //double I_RATIO = ICAL *((SupplyVoltage/1000.0) / (ADC_COUNTS));
- //Irms = I_RATIO * sqrt(sumI / numberOfSamples);
- //Calculation power values
- //realPower = V_RATIO * I_RATIO * sumP / numberOfSamples;
- //apparentPower = Vrms * Irms;
- //powerFactor=realPower / apparentPower;
- //Reset accumulators
- sumV = 0;
- //sumI = 0;
- //sumP = 0;
- //--------------------------------------------------------------------------------------
- }
- void setup() {
- Serial.begin(9600);
- }
- void loop() {
- long Vcc = (readVcc());
- Serial.print("Vcc = " );
- Serial.print(Vcc);
- Serial.println(" mV" );
- int Vin = analogRead(A2)+1 ; // leitura da tensão no pino A2 + LSB
- long Vout = (Vin * Vcc) / 1023;
- Serial.print("Vout = " );
- Serial.print( Vout ); // Vout do sensor ACS712-30A
- Serial.println(" mV" );
- Serial.println ();
- Serial.print('Vrms = ');
- Serial.print(Vrms);
- Serial.println(' mV ');
- delay(1000);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement