Ампер-Вольтметер с LED дисплеем

Показывайте и делитесь своими замечательными проектами здесь! Мы любим картинки!
Ответить
Sergey2055
Сообщения: 50
Зарегистрирован: 04 июл 2017, 13:43

Ампер-Вольтметер с LED дисплеем

Сообщение Sergey2055 » 30 янв 2020, 15:21

Всем привет. Не так давно мною были заказаны недорогие амперметры и вольтметры раздельного типа. Заказывал из разных мест. Хотел чтоб не париться применить их в моем лабораторном блоке питания в спаренном виде.. После установки и испытания я получил сильное удивление, вольтметры показывают разные значения а амперметры вообще в 2 раза разница. Я начал выяснять и провел кучу испытаний. Вольтметры можно было бы откалибровать и подобрать делитель, это не проблема, но меня удивила еще 1 проблема. Вольтметр при измерении напряжения изменяет только целую цифру и десятичную, а сотая вообще стоит на месте. Меня это не устроило. Начал испытывать амперметр. То что врет тоже ладно, можно откалибровать, но меня разочаровал тот факт что на разных пределах у него сильный разброс, при чем в разные стороны. Проанализировав все меня все это сильно разочаровала и я решил сделать свой модуль измерения. Ниже представлена его схема. Схему набросал это все хорошо но перешел к коду. Хотел обойтись быстрым кодом с применением готовых библиотек. Но испытав несколько разных, увидел какую белиберду они выводят решил не тратить время и набросать свой код. Данный модуль может измерять постоянное напряжение 0 - 30В с точьностью 30мв и постоянный ток от 0 до 20А с точностью приблизительно 10ма. Код не идеальный но полностью рабочий.

Код: Выделить всё

#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);
}

document.jpg
document.jpg (122.71 КБ) 2554 просмотра
ссылка на видео https://youtu.be/1I-cLuBqV5Y

платы для лут но надо подправить
плата индикации 3 (2).zip
(29.24 КБ) 75 скачиваний
Вложения
20200130_181839.jpg
20200130_181839.jpg (747.69 КБ) 2554 просмотра
20200130_163532.jpg
20200130_163532.jpg (413.71 КБ) 2554 просмотра

Ответить