Project : ВольтАмперМетр Version : 1 Date : 23.12.2014 Author : MyComp Company : MyComp Comments: Два четырёх-разрядных индикатора с общим анодом для измерения на одном индикаторе напряжение в вольтах до (30.0), а на другом силу тока а амперах до (3.00). Датчик тока на 0,1 Ом.
Chip type : ATmega8L Program type : Application AVR Core Clock frequency: 4,000000 MHz Memory model : Small External RAM size : 0 Data Stack size : 256 *******************************************************/
#include <mega8.h> #include <delay.h> //Функции задержки #include <math.h> //Математические функции
// Declare your global variables here unsigned char chislo [8]; //Массив содержащий разложенные поразрядно отображаемое число bit flag_indikaciya = 1; //Отображение всех символов индикации завершено unsigned char tochka_volt = 10; //Номер разряда для отображения точки для вольт, если она равна 10, то точку не отображать unsigned char tochka_amper = 10; //Номер разряда для отображения точки для ампер, если она равна 10, то точку не отображать
flash unsigned char kooficient_millivolt = 30; //Коофициент для преобразования значения АЦП в миллиВольты flash float kooficient_milliamper = 3.125; //Коофициент для преобразования значения АЦП в миллиАмперы
//Массив содержащий изображения цифр от 0 до 9 и букв для индикации flash unsigned char simvol [16] = {0b11000000,/*0*/ 0b11111001,/*1*/ 0b10100100,/*2*/ 0b10110000,/*3*/ 0b10011001,/*4*/ 0b10010010,/*5*/ 0b10000010,/*6*/ 0b11111000,/*7*/ 0b10000000,/*8*/ 0b10010000,/*9*/ 0b11100011,/*u*/ 0b11101111,/*i*/ 0b11000001,/*U*/ 0b11001111,/*I*/ 0b10001100,/*P*/ 0b11111111 /* */};
#define FIRST_ADC_INPUT 0 #define LAST_ADC_INPUT 1 unsigned int adc_data[LAST_ADC_INPUT-FIRST_ADC_INPUT+1]; //Массив содержащий результаты АЦП с двух входов 0(U) и 1(I) // Voltage Reference: Int., cap. on AREF #define ADC_VREF_TYPE ((1<<REFS1) | (1<<REFS0) | (0<<ADLAR))
// Timer2 output compare interrupt service routine //Прерывание Таймера/счётчика Т2 каждые 480Гц для организации динамической индикации (переключения 8 разрядов) interrupt [TIM2_COMP] void timer2_comp_isr(void) { static unsigned char razryat = 0; //Переменная указывает номер разряда отображаемого числа
PORTD = simvol [15]; //Погасить цифры на дисплее switch (razryat) //Если номер разряда равен { case 0: PORTB = 0b00000001; break; //Подать питание на 0 разряд индикатора case 1: PORTB = 0b00000010; break; //Подать питание на 1 разряд индикатора case 2: PORTB = 0b00000100; break; //Подать питание на 2 разряд индикатора case 3: PORTB = 0b00001000; break; //Подать питание на 3 разряд индикатора case 4: PORTB = 0b00010000; break; //Подать питание на 4 разряд индикатора case 5: PORTB = 0b00100000; break; //Подать питание на 5 разряд индикатора case 6: PORTB = 0b01000000; break; //Подать питание на 6 разряд индикатора case 7: PORTB = 0b10000000; break; //Подать питание на 7 разряд индикатора //Иначе если номер разряда вышел за допустимые пределы default: razryat = 0; break; //Начальное значение переменной }
PORTD = simvol[ chislo[razryat] ]; //Отобразить одну из цифр на индикаторе и погасить точку
//Если точку для вольт или ампер разрешено отобразить в этом разряде, тогда if ((tochka_volt == razryat) ||(tochka_amper == razryat)) { PORTD.7 = 0; //Зажечь точку в разрешённом разряде }
razryat++; //Увеличить переменную на 1 if (razryat > 7) //Если были отображены все символы на индикаторе, тогда { razryat = 0; //Начальное значение переменной flag_indikaciya = 1; //Отображение всех символов индикации завершено }
}
// ADC interrupt service routine // with auto input scanning //Прерывание АЦП после каждого преобразования с автоматическим сканированием двух входов interrupt [ADC_INT] void adc_isr(void) { static unsigned char input_index=0; // Read the AD conversion result adc_data[input_index]=ADCW; // Select next ADC input if (++input_index > (LAST_ADC_INPUT-FIRST_ADC_INPUT)) input_index=0; ADMUX=(FIRST_ADC_INPUT | ADC_VREF_TYPE)+input_index; // Delay needed for the stabilization of the ADC input voltage delay_us(10); // Start the AD conversion ADCSRA|=(1<<ADSC); }
void main(void) //Главная функция программы { // Declare your local variables here unsigned int millivolt; //Измеренное напряжение в миллиВольтах unsigned int milliamper; //Округленная в меньшую сторону измеренная сила тока в миллиАмперах unsigned int temp_raschyot; //Переменная для расчёта float temp_milliamper; //Измеренная сила тока в миллиАмперах
// Analog Comparator initialization // Analog Comparator: Off // The Analog Comparator's positive input is // connected to the AIN0 pin // The Analog Comparator's negative input is // connected to the AIN1 pin ACSR=(1<<ACD) | (0<<ACBG) | (0<<ACO) | (0<<ACI) | (0<<ACIE) | (0<<ACIC) | (0<<ACIS1) | (0<<ACIS0);
// Global enable interrupts #asm("sei") //Разрешить прерывания
while (1) //Главный цикл программы { millivolt = adc_data[0] * kooficient_millivolt; //Узнать текущее напряжение в миллиВольтах temp_milliamper = adc_data[1] * kooficient_milliamper; //Узнать текущую силу тока в миллиАмперах milliamper = floor(temp_milliamper); //Округлить текущую силу тока в миллиАмперах в большую сторону
if (flag_indikaciya == 1) //Если отображение всех символов индикации завершено { tochka_volt = 10; //Запрещено отображение точки для Вольт
//Если миллиВольт больше либо равно 10000 и миньше либо равно 30600, тогда if ((millivolt >= 10000) && (millivolt <= 30600)) { temp_raschyot = millivolt / 100; chislo[0] = temp_raschyot % 10; //Узнаём, сколько сотен в числе temp_raschyot = millivolt / 1000; chislo[1] = temp_raschyot % 10; //Узнаём, сколько единиц тысяч в числе chislo[2] = millivolt / 10000; //Узнаём, сколько десятков тысяч в числе chislo[3] = 10; //Запишем /*u*/ tochka_volt = 1; //Разрешено отображение точки для Вольт в 1 разряде }
if ((millivolt >= 1000) && (millivolt < 10000)) //Если миллиВольт больше либо равно 1000 и меньше 10000, тогда { temp_raschyot = millivolt / 10; chislo[0] = temp_raschyot % 10; //Узнаём, сколько десятков в числе temp_raschyot = millivolt / 100; chislo[1] = temp_raschyot % 10; //Узнаём, сколько сотен в числе chislo[2] = millivolt / 1000; //Узнаём, сколько тысяч в числе chislo[3] = 10; //Запишем /*u*/ tochka_volt = 2; //Разрешено отображение точки для Вольт во 2 разряде }
if ((millivolt >= 100) && (millivolt < 1000)) //Если миллиВольт больше либо равно 100 и меньше 1000, тогда { temp_raschyot = millivolt / 10; chislo[0] = temp_raschyot % 10; //Узнаём, сколько десятков в числе chislo[1] = millivolt / 100; //Узнаем, сколько сотен в числе chislo[2] = 0; //Запишем 0 chislo[3] = 10; //Запишем /*u*/ tochka_volt = 2; //Разрешено отображение точки для Вольт во 2 разряде }
if (millivolt < 100) //Если миллиВольт меньше 100, тогда { chislo[0] = millivolt / 10; //Узнаём, сколько десятков в числе chislo[1] = 0; //Запишем 0 chislo[2] = 0; //Запишем 0 chislo[3] = 10; //Запишем /*u*/ tochka_volt = 2; //Разрешено отображение точки для Вольт во 2 разряде }
tochka_amper = 10; //Запрещено отображение точки для Ампер
//Если миллиАмпер больше либо равно 1000 и меньше либо равно 3100, тогда if ((milliamper >= 1000) && (milliamper <= 3100)) { temp_raschyot = milliamper / 10; chislo[4] = temp_raschyot % 10; //Узнаём, сколько десятков в числе temp_raschyot = milliamper / 100; chislo[5] = temp_raschyot % 10; //Узнаём, сколько сотен в числе chislo[6] = milliamper / 1000; //Узнаём, сколько тысяч в числе chislo[7] = 11; //Запишем /*i*/ tochka_amper = 6; //Разрешено отображение точки для Ампер в 6 разряде }
if ((milliamper >= 100) && (milliamper < 1000)) //Если миллиАмпер больше либо равно 100 и меньше 1000, тогда { temp_raschyot = milliamper / 10; chislo[4] = temp_raschyot % 10; //Узнаём, сколько десятков в числе chislo[5] = milliamper / 100; //Узнаем, сколько сотен в числе chislo[6] = 0; //Запишем 0 chislo[7] = 11; //Запишем /*i*/ tochka_amper = 6; //Разрешено отображение точки для Ампер в 6 разряде }
if (milliamper < 100) //Если миллиАмпер меньше 100, тогда { chislo[4] = milliamper / 10; //Узнаём, сколько десятков в числе chislo[5] = 0; //Запишем 0 chislo[6] = 0; //Запишем 0 chislo[7] = 11; //Запишем /*i*/ tochka_amper = 6; //Разрешено отображение точки для Ампер в 6 разряде }
flag_indikaciya = 0; //Отображение всех символов индикации не завершено }
delay_ms(500); //Задержка чтобы десятые и сотые доли Вольт и Ампер не менялись быстро } }
//Если миллиВольт больше либо равно 10000 и миньше либо равно 30600, тогда if ((millivolt >= 10000) && (millivolt <= 30600)) { temp_raschyot = millivolt / 100; chislo[0] = temp_raschyot % 10; //Узнаём, сколько сотен в числе temp_raschyot = millivolt / 1000; chislo[1] = temp_raschyot % 10; //Узнаём, сколько единиц тысяч в числе chislo[2] = millivolt / 10000; //Узнаём, сколько десятков тысяч в числе chislo[3] = 10; //Запишем /*u*/ tochka_volt = 1; //Разрешено отображение точки для Вольт в 1 разряде }
менять значение 30600 на 36000. Надпись U uP не отображается, но и напряжение выше 30,6В тоже не отображается - на индикаторе 30.6 при любом напряжении выше 30,6В.
Что надо поправить в коде, чтобы отображалось напряжение выше 30,6В, скажем, до 36В?
В программировании полный ноль. Памагытэмынэмэстные .
_________________ ... ардубино и наебиэкспресс убивают творчество в зародыше.
Есть некоторая, в пределах десятых вольта, нелинейность, или расхождение в показаниях, в сравнении с мультиметром. Или наш вольтметр точнее . Считаете, исправлений в коде достаточно, перерасчет мат.части не нужен?
Расчётная часть:Спойлер
http://radio-stv.ru/volt-ampermetr писал(а):
Прежде чем перейти к расчётной части, необходимо определиться что R1 = 27,5 Ком, R2 = 2,5 Ком, общее сопротивление резисторов R3, R4 и R5 равно 0,1 ом (назовём их Rш). Общее сопротивление резисторов R7 и R8 равно 7 Ком (назовём их Rоу). ADC – результат работы схемы АЦП (возвращает число от 0 до 1024). В качестве источника опорного напряжения для схемы АЦП микросхемы ATMEGA8L выбрано напряжение 2,56 Вольт. Разрядность АЦП выбрана 10 бит, то есть максимальное число которое вернёт схема АЦП равна 1024. Это число будет эквивалентом напряжения на входах АЦП. Например, если adc вернул 512, то это значит, что на вход АЦП мы подали половину опорного напряжения. Чтобы вычислить реальное измеряемое напряжение, нам нужно: Составить пропорцию Опорное напряжение (Вольт) – 1024 Искомое напряжение (Вольт) – adc У нас опорное напряжение = 2,56 В Искомое напряжение, В = (2,56 * adc) / 1024, или Искомое напряжение, В = 0,0025 * adc Для простоты переведём вольты в милливольты, умножив на 1000 Искомое напряжение, мВ = 0,0025 * adc * 1000, или Искомое напряжение, мВ = 2,5 * adc Далее нужно учесть коэффициент резисторного делителя напряжения R1 и R2 по формуле Кдел = (R1+R2) / R2. Подставив, получим Кдел = (27,5 + 2,5) / 2,5 = 12. Так как наш резисторный делитель уменьшает измеряемое напряжение в 12 раз, то для того чтобы это учесть нужно Искомое напряжение, мВ умножить на 12. Реальное измеряемое напряжение, мВ = 2,5 * adc * 12, или Реальное напряжение, мВ = 30 * adc Полученное число 30 и будет нашим коэффициентом который нужно занести в программу для перевода результата работы АЦП в реальное измеряемое напряжение в миллиВольтах.
_________________ ... ардубино и наебиэкспресс убивают творчество в зародыше.
Вся математика уже заложена в этот коэффициент. В мультиметре при измерении маленьких напряжений нужно переключать на диапазон -20V, иначе падает точность.
Качественное и безопасное устройство, работающее от аккумулятора, должно учитывать его физические и химические свойства, профили заряда и разряда, их изменение во времени и под влиянием различных условий, таких как температура и ток нагрузки. Мы расскажем о литий-ионных аккумуляторных батареях EVE и нескольких решениях от различных китайских компаний, рекомендуемых для разработок приложений с использованием этих АКБ. Представленные в статье китайские аналоги помогут заменить продукцию западных брендов с оптимизацией цены без потери качества.
//Если миллиАмпер больше либо равно 1000 и меньше либо равно 3100, тогда if ((milliamper >= 1000) && (milliamper <= 3100)) { temp_raschyot = milliamper / 10; chislo[4] = temp_raschyot % 10; //Узнаём, сколько десятков в числе temp_raschyot = milliamper / 100; chislo[5] = temp_raschyot % 10; //Узнаём, сколько сотен в числе chislo[6] = milliamper / 1000; //Узнаём, сколько тысяч в числе chislo[7] = 11; //Запишем /*i*/ tochka_amper = 6; //Разрешено отображение точки для Ампер в 6 разряде }
на большее значение ?
И почему в этой строке
Код:
if (millivolt > 36100) //Если миллиВольт больше 30600, тогда
вы меняли значение на 36100, а в этой
Код:
//Если миллиВольт больше либо равно 10000 и миньше либо равно 30600, тогда if ((millivolt >= 10000) && (millivolt <= 36600))
на 36600?
Спасибо .
_________________ ... ардубино и наебиэкспресс убивают творчество в зародыше.
Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре.
Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.
Я одного не понял: как без изменения входных цепей вы тут показания меняете? Было, как я понимаю, так: подали 30 вольт - увидели 30 вольт. А теперь как? Подали 30 вольт, увидели 36 вольт? Или я чего-то не понял?
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
Сейчас этот форум просматривают: Vladislav14 и гости: 17
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения