Ампер-Вольтметер с LED дисплеем
Добавлено: 30 янв 2020, 15:21
Всем привет. Не так давно мною были заказаны недорогие амперметры и вольтметры раздельного типа. Заказывал из разных мест. Хотел чтоб не париться применить их в моем лабораторном блоке питания в спаренном виде.. После установки и испытания я получил сильное удивление, вольтметры показывают разные значения а амперметры вообще в 2 раза разница. Я начал выяснять и провел кучу испытаний. Вольтметры можно было бы откалибровать и подобрать делитель, это не проблема, но меня удивила еще 1 проблема. Вольтметр при измерении напряжения изменяет только целую цифру и десятичную, а сотая вообще стоит на месте. Меня это не устроило. Начал испытывать амперметр. То что врет тоже ладно, можно откалибровать, но меня разочаровал тот факт что на разных пределах у него сильный разброс, при чем в разные стороны. Проанализировав все меня все это сильно разочаровала и я решил сделать свой модуль измерения. Ниже представлена его схема. Схему набросал это все хорошо но перешел к коду. Хотел обойтись быстрым кодом с применением готовых библиотек. Но испытав несколько разных, увидел какую белиберду они выводят решил не тратить время и набросать свой код. Данный модуль может измерять постоянное напряжение 0 - 30В с точьностью 30мв и постоянный ток от 0 до 20А с точностью приблизительно 10ма. Код не идеальный но полностью рабочий.
ссылка на видео https://youtu.be/1I-cLuBqV5Y
платы для лут но надо подправить
Код: Выделить всё
#define LED_A 2 //2 PD2
#define LED_B 4 //4 PD4
#define LED_C 2 //10 PB2
#define LED_D 2 //16 PC2
#define LED_E 3 //17 PC3
#define LED_F 3 //3 PD3
#define LED_G 3 //11 PB3
#define LED_H 1 //9 PB1
#define LED_K1 7 //7 PD7
#define LED_K2 6 //6 PD6
#define LED_K3 5 //5 PD5
#include <stdio.h>
#include <stdlib.h>
#define LED_A1 0 //8 PB0
#define LED_A2 5 //A5 PC5
#define LED_A3 4 //A4 PC4
int Vinput;
int Iinput;
int U, I;
byte radix = 10; //система счисления
byte buf0[4]; //результат
byte buf1[4]; //результат
bool flag_U, flag_I;
byte flag_ind;
enum {
CH_U = 3, CH_I = 1};
//String value_string;
double Urms = 0, Irms = 0;
double Utemp = 0, Itemp = 0;
int Umoment = 0, Imoment = 0, N = 0;
byte Channel = CH_U, count = 0;
void setup() {
// put your setup code here, to run once:
DDRD = 0b11111101;
DDRB = 0b11111111;
DDRC = 0b11111100;
autoadcsetup();
}
void loop() {
}
//==============================================================================================
//////////<< AUTOADCSETUP >>////////////////////////////////////////////////////////////////////
//==============================================================================================
void autoadcsetup(){
//set TMR1.
/*normal mode, prescaler 16
16MHz / 64 / 61 = 4098 Hz 0.04% to 4096Hz*/
TCCR1B = (0 << CS12) | (1 << CS11)|(0 << CS10);//устанавливаем частоту предделителя
OCR1AL = 207; //99;//199+1 //записываем число в регистр с ним и будем сравнивать
OCR1AH = 7;
TIMSK1 = (1<<OCIE1A); //разрешаем прерывание по совпадению при сравнении с регистром OCR1AL
//set ADC.
ADMUX = (1 << REFS0); //устанавливаем в качестве опорника напряжение питания AVCC with external capacitor at AREF pin
ADCSRA = (1 << ADEN) | (1 << ADSC) | (0 << ADATE) | (1 << ADIE) | (1 << ADPS2) | (0 << ADPS1) | (1 << ADPS0);//Bit 7 – ADEN: ADC Enable, Bit 6 – ADSC: ADC Start Conversion,
//Bit 5 – ADATE: ADC Auto Trigger Enable, Bit 3 – ADIE: ADC Interrupt Enable,
//Bits 2:0 – ADPSn: ADC Prescaler Select 16
ADCSRB = (0<< ADTS2) | (0<<ADTS1) | (0<<ADTS0); //Bits 2:0 – ADTSn: ADC Auto Trigger Source [n = 2:0] 000 Free Running mode
}
//==============================================================================================
//////////<< TIMER1_COMPA_vect >>///////////////////////////////////////////////////////////////
//==============================================================================================
ISR(TIMER1_COMPA_vect){
TCNT1 = 0; //сброс счетчика TMR1
ADCSRA |=(1<<ADSC); //Перезапуск преобразования ADC
if(count == 12) count = 0;
else count++;
ind(count);
}
//==============================================================================================
//////////<< ADC_vect >>////////////////////////////////////////////////////////////////////////
//==============================================================================================
ISR(ADC_vect){
if (Channel == CH_U){
Umoment = ADCL;
Umoment += (ADCH<<8);
Utemp = Utemp + Umoment;
Channel = CH_I;//switch channel
ADMUX |=(1<<MUX0); //to I
}
else{
Imoment = ADCL;//cacl I RMS
Imoment += (ADCH<<8);
Imoment = Imoment - 512;
Itemp = Itemp + Imoment;
Channel = CH_U;//switch channel
ADMUX &=~(1<<MUX0); //to U
N++;
}
if (N == 999){
//calc final result
Urms = ((Utemp) / 500);
Irms = ((Itemp) / 500+1); //185//100
N = 0;
Utemp = 0;
Itemp = 0;
U = (((Urms * 5.00) * 6.00) / 1023.00) * 100.00;
I = ((((Irms * 5.00) / 1023.00)) * 500.00);
int k = U / 1000;
if(k != 0) flag_U = 1;
else flag_U = 0;
k = I / 1000;
if(k != 0) flag_I = 1;
else flag_I = 0;
buf0[0] = U / 1000;
buf0[1] = (U % 1000) / 100;
buf0[2] = (U % 100) / 10;
buf0[3] = U % 10;
if(buf0[0] == 0) {buf0[0] = buf0[1]; buf0[1] = buf0[2]; buf0[2] = buf0[3];}
buf1[0] = I / 1000;
buf1[1] = (I % 1000) / 100;
buf1[2] = (I % 100) / 10;
buf1[3] = I % 10;
if(buf1[0] == 0) {buf1[0] = buf1[1]; buf1[1] = buf1[2]; buf1[2] = buf1[3];}
}
}
//==============================================================================================
//////////<< ADC_vect_END >>////////////////////////////////////////////////////////////////////////
//==============================================================================================
void ind(byte var){
PORTD &= ~(1<<LED_K1);
PORTD &= ~(1<<LED_K2);
PORTD &= ~(1<<LED_K3);
PORTB &= ~(1<<LED_A1);
PORTC &= ~(1<<LED_A2);
PORTC &= ~(1<<LED_A3);
switch (var) {
case 0:
PORTB &= ~(1<<LED_H);
switch (flag_U) {
case 0:
PORTB |= (1<<LED_H);
break;
}
Simvol(buf0[0]);
PORTD |= (1<<LED_K1);
break;
case 1:
PORTB &= ~(1<<LED_H);
switch (flag_U) {
case 1:
PORTB |= (1<<LED_H);
break;
}
Simvol(buf0[1]);
PORTD |= (1<<LED_K2);
break;
case 2:
PORTB &= ~(1<<LED_H);
Simvol(buf0[2]);
PORTD |= (1<<LED_K3);
break;
case 3:
PORTB &= ~(1<<LED_H);
switch (flag_I) {
case 0:
PORTB |= (1<<LED_H);
break;
}
Simvol(buf1[0]);
PORTB |= (1<<LED_A1);;
break;
case 4:
PORTB &= ~(1<<LED_H);
switch (flag_I) {
case 1:
PORTB |= (1<<LED_H);
break;
}
Simvol(buf1[1]);
PORTC |= (1<<LED_A2);
break;
case 5:
PORTB &= ~(1<<LED_H);
Simvol(buf1[2]);
PORTC |= (1<<LED_A3);
break;
}
}
void Simvol(byte var){
switch (var) {
case 0:
led_SIGM();
PORTD |= 1<<LED_A;
PORTD |= 1<<LED_B;
PORTB |= 1<<LED_C;
PORTC |= 1<<LED_D;
PORTC |= 1<<LED_E;
PORTD |= 1<<LED_F;
break;
case 1:
led_SIGM();
PORTD |= 1<<LED_B;
PORTB |= 1<<LED_C;
break;
case 2:
led_SIGM();
PORTD |= 1<<LED_A;
PORTD |= 1<<LED_B;
PORTC |= 1<<LED_D;
PORTC |= 1<<LED_E;
PORTB |= 1<<LED_G;
break;
case 3:
led_SIGM();
PORTD |= 1<<LED_A;
PORTD |= 1<<LED_B;
PORTB |= 1<<LED_C;
PORTC |= 1<<LED_D;
PORTB |= 1<<LED_G;
break;
case 4:
led_SIGM();
PORTD |= 1<<LED_B;
PORTB |= 1<<LED_C;
PORTD |= 1<<LED_F;
PORTB |= 1<<LED_G;
break;
case 5:
led_SIGM();
PORTD |= 1<<LED_A;
PORTB |= 1<<LED_C;
PORTC |= 1<<LED_D;
PORTD |= 1<<LED_F;
PORTB |= 1<<LED_G;
break;
case 6:
led_SIGM();
PORTD |= 1<<LED_A;
PORTB |= 1<<LED_C;
PORTC |= 1<<LED_D;
PORTC |= 1<<LED_E;
PORTD |= 1<<LED_F;
PORTB |= 1<<LED_G;
break;
case 7:
led_SIGM();
PORTD |= 1<<LED_A;
PORTD |= 1<<LED_B;
PORTB |= 1<<LED_C;
break;
case 8:
PORTD |= 1<<LED_A;
PORTD |= 1<<LED_B;
PORTB |= 1<<LED_C;
PORTC |= 1<<LED_D;
PORTC |= 1<<LED_E;
PORTD |= 1<<LED_F;
PORTB |= 1<<LED_G;
break;
case 9:
led_SIGM();
PORTD |= 1<<LED_A;
PORTD |= 1<<LED_B;
PORTB |= 1<<LED_C;
PORTC |= 1<<LED_D;
PORTD |= 1<<LED_F;
PORTB |= 1<<LED_G;
break;
}
}
void led_SIGM(){
PORTD &= ~(1<<LED_A);
PORTD &= ~(1<<LED_B);
PORTB &= ~(1<<LED_C);
PORTC &= ~(1<<LED_D);
PORTC &= ~(1<<LED_E);
PORTD &= ~(1<<LED_F);
PORTB &= ~(1<<LED_G);
}
ссылка на видео https://youtu.be/1I-cLuBqV5Y
платы для лут но надо подправить