True RMS
True RMS
*
* Arduino autoranging AC/DC voltmeter.
* Voltage and frequency are printed on 1602 LCD screen.
* This is a free software with NO WARRANTY - Use it at your own risk!
* https://simple-circuit.com/
*
*************************************************************************/
// variables
byte ch_number;
const uint16_t res_table[4] = {2444, 244, 94, 47}, // voltage divider resistances
in tenths kOhms
total_res = 22444; // total resistance in tenths
kOhms
uint16_t current_res;
volatile byte per;
void setup(void)
{
pinMode(CH0, OUTPUT);
// pinMode(A3, INPUT);
pinMode(CH1, OUTPUT);
pinMode(CH2, OUTPUT);
pinMode(CH3, OUTPUT);
Serial.begin(9600);
lcd.backlight();
ch_number = 0;
ch_select(ch_number);
ADCSRA = (1 << ADEN) | (1 << ADIE); //ADEN =1 -> Enable ADC; 1 << ADIE : ADC
interupt Enable / cho phep ngat
// sei();
Serial.println("Cuối vòng setup:");
// main loop
void loop()
{
Serial.println("Đầu vòng lặp loop:");
bool dc_flag = 0; // DC voltage flag bit
int32_t sum = 0; // sum of all readings
uint16_t n = 0; // number of readings (samples)
if( micros() - current_m >= Time_Out ) { // if there's time out event ==>
voltage signal is DC
dc_flag = 1;
for (byte i = 0; i < 200; i++) {
ADCSRA |= 1 << ADSC; // start conversion
while(ADCSRA & 0x40); // wait for conversion complete
int16_t an = (int16_t)(ADCL | (uint16_t)ADCH << 8) - 511;
sum += an;
n++; // increment number of readings
delay(1);
}
}
// voltage calculation
float v;
if(dc_flag) // if voltage signal is DC
v = (4 * sum)/n; // calculate Arduino analog channel DC voltage in milli-
Volts
if( (v_abs < 220 && ch_number == 3) || (v_abs < 80 && ch_number == 2) || (v_abs <
8 && ch_number == 1) ) {
ch_number--;
ch_select(ch_number);
delay(10);
return;
}
char _buffer[8];
lcd.setCursor(0, 1);
if( v < 0)
lcd.print('-');
else
lcd.print(' ');
if(v_abs < 10)
sprintf( _buffer, "%01u.%02u", v_abs, abs((int16_t)(v * 100)) % 100 );
else if( v_abs < 100)
sprintf( _buffer, "%02u.%01u", v_abs, abs((int16_t)(v * 10)) % 10 );
else
sprintf( _buffer, "%03u ", v_abs );
lcd.print(_buffer);
if(dc_flag)
lcd.print("VDC ");
else {
lcd.print("VAC ");
// calculate signal frequency in Hz
uint32_t period_time = total_time/Periods;
float freq = 1000000.0/period_time;
sprintf( _buffer, "%02u.%02uHz", (uint16_t)freq % 100, (uint16_t)(freq * 100) %
100 );
lcd.print(_buffer);
}
void ch_select(byte n) {
switch(n) {
case 0:
digitalWrite(CH0, HIGH);
digitalWrite(CH1, LOW);
digitalWrite(CH2, LOW);
digitalWrite(CH3, LOW);
break;
case 1:
digitalWrite(CH0, LOW);
digitalWrite(CH1, HIGH);
digitalWrite(CH2, LOW);
digitalWrite(CH3, LOW);
break;
case 2:
digitalWrite(CH0, LOW);
digitalWrite(CH1, LOW);
digitalWrite(CH2, HIGH);
digitalWrite(CH3, LOW);
break;
case 3:
digitalWrite(CH0, LOW);
digitalWrite(CH1, LOW);
digitalWrite(CH2, LOW);
digitalWrite(CH3, HIGH);
}
current_res = res_table[n];
}
// end of code.