balistik

Atmega8 2 ШИМ и прерывание по таймеру для чтения DS18B20

18 сообщений в этой теме

balistik    0

Всем доброго времени суток. Я реальный нуб в ATMEGA. Могу более-менее понять чужой код и из кусков сделать целое. Вопрос такой: реально ли на ATMEGA8 сделать 2 ШИМ (таймер 1 и2) и внутреннее прерывание (по таймеру 0) для чтения данных с DS18B20 на 8Мгц чтобы еще осталось на опрос кнопок и небольшую логику? Я выложу пример кода. По отдельность: ШИМ, прерывания, логика, запись в ЕПРОМ работает. Собираю все вместе - не работает. Пробовал в Протеусе, тоже глючит, да и протеус тормозит. Может кто чего подскажет.

//#define F_CPU 8000000UL // устанавливаем рабочую частоту контроллера
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/eeprom.h>
#include "ds18x20.h"
#include "onewire.h"


#define MAXSENSORS 1

unsigned int tempint = 0; // переменная для целого значения температуры
unsigned int subzero = 0; // переменная отрицательных значений температуры
unsigned int clock = 0; //задержка для опроса датчика температуры
unsigned int termo_error = 0; //флаг ошибки термодатчика
unsigned char regim, R1_SHIBER, R1_VENT, R2_SHIBER, R2_VENT, R3_SHIBER, R3_VENT; //переменные режимов работы
volatile char press = 0, pr = 0, pr1 = 0, set = 0; //дополнительные переменные для кнопок

#define SHIBER_PB	1 //шибер подачи топлива
#define SHIBER_PWM	OCR1A
#define VENT_PB	2 //вентилятор подачи воздуха
#define VENT_PWM	OCR1B

#define LED1_ON PORTD |= _BV(PD3) // светодиод режим 1
#define LED1_OFF PORTD &= ~_BV(PD3)
#define LED2_ON PORTD |= _BV(PD4) // светодиод режим 2
#define LED2_OFF PORTD &= ~_BV(PD4)
#define LED3_ON PORTD |= _BV(PD6) // светодиод режим 3
#define LED3_OFF PORTD &= ~_BV(PD6)
#define LED4_ON PORTD |= _BV(PD7) // светодиод 4 программирование
#define LED4_OFF PORTD &= ~_BV(PD7)

#define BUT_M PIND & (1 << PD1)  // кнопка MENU
#define BUT_U PIND & (1 << PD2)  // кнопка UP
#define BUT_D PIND & (1 << PD0)  // кнопка DOWN

unsigned char eep1 EEMEM; // режим работы
unsigned char eep2 EEMEM; // режим 1 ШИМ вентилятор
unsigned char eep3 EEMEM; //режим 1 ШИМ шибер
unsigned char eep4 EEMEM; // режим 2 ШИМ вентилятор
unsigned char eep5 EEMEM; //  режим 2 ШИМ шибер
unsigned char eep6 EEMEM; // режим 3 ШИМ вентилятор
unsigned char eep7 EEMEM; // режим 3 ШИМ шибер
unsigned char eep8 EEMEM; // флаг первого запуска


uint8_t Temperature, szero; //-255
uint8_t nSensors, j;
uint8_t cel_frac_bits;
uint8_t gSensorIDs[MAXSENSORS][OW_ROMCODE_SIZE];

uint8_t search_sensors(void) // поиск DS18B20
{
	uint8_t i;
	uint8_t id[OW_ROMCODE_SIZE];
	uint8_t diff, nSensors;

	nSensors = 0;

	for( diff = OW_SEARCH_FIRST;
		diff != OW_LAST_DEVICE && nSensors < MAXSENSORS ; )
	{
		DS18X20_find_sensor( &diff, &id[0] );

		if( diff == OW_PRESENCE_ERR ) {
			Temperature = 255;
			szero = 1;
			break;
		}
		if( diff == OW_DATA_ERR ) {
			Temperature = 255;
			szero = 1;
			break;
		}
		for (i=0; i<OW_ROMCODE_SIZE; i++)
			gSensorIDs[nSensors][i]=id[i];

		nSensors++;
	}

	return nSensors;
}


void get_temp(int sensor){ // получаем температуру с датчиков


		DS18X20_start_meas(DS18X20_POWER_EXTERN, NULL);
		DS18X20_start_meas(DS18X20_POWER_EXTERN, NULL);

		j = gSensorIDs[0][sensor]; // family-code for conversion-routine

		if (DS18X20_read_meas_single(j, &szero, &Temperature, &cel_frac_bits) != DS18X20_OK) { //если не прочиталось то -255
			Temperature = 255;
			szero = 1;
		}
			if (DS18X20_read_meas_single(j, &szero, &Temperature, &cel_frac_bits) != DS18X20_OK) { //если не прочиталось то -255
			Temperature = 255;
			szero = 1;
		}

		tempint=(int)Temperature;
		subzero=(int)szero;
}


void pin_init(void) { //инициализация портов ШИМ
    DDRB |= (1<<SHIBER_PB) | (1<<VENT_PB);
    PORTB &= ~((1<<SHIBER_PB) | (1<<VENT_PB));
}


void timer0_init(void) { //инициализация таймера для термодатчика 
TCCR0 |= (1<<CS00); 
TIMSK |= ( 1 << TOIE0); 
TCNT0 = 0xFF; 
}

void timer1_init(void) { //инициализация таймера ШИМ шибера
   TCCR1A |= (1 << COM1A1) | (1 << COM1B1) | (1 << WGM11);
    TCCR1B |= (1 << WGM13) | (1 << WGM12) | (1 << CS10);
    TCNT1 = 0x00;
    ICR1 = 0xFF;
    OCR1A = 0x00;
    OCR1B = 0x00;
}

void timer2_init(void) { //инициализация таймера ШИМ вентилятора
    TCCR2 |= (1 << COM21) | (1 << WGM21) | (1 << WGM20) | (1 << CS20);
    TCNT2 = 0x00;
    OCR2 = 0x00;
}

ISR(TIMER0_OVF_vect){ //прерывание таймера 0 для термодатчика

if (clock != 4294967295){_delay_us(50);clock++;}else{get_temp(0);clock=0;}

}

	 
//***************** обработка нажатия кнопок **********************
void buttons(){ 

	if(~BUT_U){if(set == 0)pr++; // кнопка UP
		
		if(pr == 10){ // долгое нажатие
			
		}
		
	_delay_ms(100);

	}else{
		if(pr >= 1 && pr < 10){ // короткое нажатие
		regim++;
		if (regim>3){regim=0;}
		eeprom_write_byte(&eep1, regim); // сохранение настройки в eeprom
		set = 0;
		pr = 0;
		}
		pr = 0;
	}


	if(~BUT_D){if(set == 0)pr1++; // кнопка DOWN

	if(pr1 == 10){ // длинное нажатие
	
		}
	_delay_ms(100);

	}else{

	if(pr1 >= 1 && pr1 < 10){ // короткое нажатие.
			//set = 20;
			regim--;
		if (regim<0){regim=3;}
		eeprom_write_byte(&eep1, regim); // сохранение настройки в eeprom	
		_delay_ms(100);
			set = 0;
			pr1 = 0;
		}
		pr1 = 0;
	}




	if(~BUT_M){ // кнопка MENU
	
		press++;  

		if(press == 1 && set != 0){set++;} // переход по настройкам
		if(press >= 100 && set == 0){set = 1; _delay_ms(200);} // ход в настройки
		
		if(set == 1) eeprom_write_byte(&eep2, R1_VENT);
		if(set == 2) eeprom_write_byte(&eep3, R1_SHIBER);
		if(set == 3) eeprom_write_byte(&eep4, R2_VENT);
		if(set == 4) eeprom_write_byte(&eep5, R2_SHIBER);	
		if(set == 5) eeprom_write_byte(&eep6, R3_VENT);
		if(set == 6) eeprom_write_byte(&eep7, R3_SHIBER);

		
		if(set > 6){ _delay_ms(100); set = 0; press = 0;} // если включена настройка даты,
	

	}else{
		if(set == 0 && press >= 1){ // если не вошли в настройки
		regim++;
		if (regim>3){regim=0;}
		eeprom_write_byte(&eep1, regim); // сохранение настройки в eeprom
		}

		press = 0;
	}
}
//*****************режим настроек********************

void settings(){ 
//визуальное подтверждение настроек
if(press >= 1 && set == 1) {
LED1_ON;
LED2_OFF;
LED3_OFF;
LED4_ON;
SHIBER_PWM = R1_VENT;} //ШИМ шибер 0-255
if(press >= 1 && set == 2) {
LED1_ON;
LED2_OFF;
LED3_OFF;
LED4_ON;
VENT_PWM = R1_SHIBER;} //ШИМ вентилятор 0-255
if(press >= 1 && set == 3) {
LED1_OFF;
LED2_ON;
LED3_OFF;
LED4_ON;
SHIBER_PWM = R2_VENT;} //ШИМ шибер 0-255
if(press >= 1 && set == 4) {
LED1_OFF;
LED2_ON;
LED3_OFF;
LED4_ON;
VENT_PWM = R2_SHIBER;} //ШИМ вентилятор 0-255
if(press >= 1 && set == 5) {
LED1_OFF;
LED2_OFF;
LED3_ON;
LED4_ON;
SHIBER_PWM = R3_VENT;} //ШИМ шибер 0-255
if(press >= 1 && set == 6) {
LED1_OFF;
LED2_OFF;
LED3_ON;
LED4_ON;
VENT_PWM = R3_SHIBER;} //ШИМ вентилятор 0-255


switch(set) // включена настройка
	{
	case 1: // настройка R1_VENT
		if(~BUT_U){R1_VENT++; if(R1_VENT > 254) R1_VENT = 0; _delay_ms(100);}
		if(~BUT_D){R1_VENT--; if((~BUT_D) && R1_VENT == 0) R1_VENT = 254; _delay_ms(100);}
	break;

	case 2: // настройка R1_SHIBER
		if(~BUT_U){R1_SHIBER++; if(R1_SHIBER > 254) R1_SHIBER = 0; _delay_ms(100);}
		if(~BUT_D){R1_SHIBER--; if((~BUT_D) && R1_SHIBER == 0) R1_SHIBER = 254; _delay_ms(100);}
	break;

	case 3: // настройка R2_VENT
	if(~BUT_U){R2_VENT++; if(R2_VENT > 254) R2_VENT = 0; _delay_ms(100);}
		if(~BUT_D){R2_VENT--; if((~BUT_D) && R2_VENT == 0) R2_VENT = 254; _delay_ms(100);}
	break;

	case 4: // настройка R2_SHIBER
		if(~BUT_U){R2_SHIBER++; if(R2_SHIBER > 254) R2_SHIBER = 0; _delay_ms(100);}
		if(~BUT_D){R2_SHIBER--; if((~BUT_D) && R2_SHIBER == 0) R2_SHIBER = 254; _delay_ms(100);}
	break;

	case 5: // настройка R3_VENT
	if(~BUT_U){R3_VENT++; if(R3_VENT > 254) R3_VENT = 0; _delay_ms(100);}
		if(~BUT_D){R3_VENT--; if((~BUT_D) && R3_VENT == 0) R3_VENT = 254; _delay_ms(100);}
	break;

	case 6: // настройка R3_SHIBER
		if(~BUT_U){R3_SHIBER++; if(R3_SHIBER > 254) R3_SHIBER = 0; _delay_ms(100);}
		if(~BUT_D){R3_SHIBER--; if((~BUT_D) && R3_SHIBER == 0) R3_SHIBER = 254; _delay_ms(100);}
	break;	
	}
}



int main(){

	/*******************************настройка переферии******************************/	
	cli();
 	ow_set_bus(&PIND, &PORTD, &DDRD, PD5); // иництализация протокола 1-wire
	nSensors = search_sensors(); // поиск датчиков DS18B20
	DS18X20_start_meas(DS18X20_POWER_EXTERN, NULL); //включаем преобразование температуры
	pin_init();
	//timer0_init();
 	timer1_init();
 	timer2_init();
	_delay_ms(5);
	if(eeprom_read_byte(&eep8) != 1){ // читаем eeprom, если там мусор (первый запуск), пишем свои данные
		eeprom_write_byte(&eep1, 0); // режим работы
		eeprom_write_byte(&eep2, 150); // режим 1 ШИМ вентилятор
		eeprom_write_byte(&eep3, 100); //режим 1 ШИМ шибер
		eeprom_write_byte(&eep4, 200); //режим 2 ШИМ вентилятор
		eeprom_write_byte(&eep5, 150);  //режим 2 ШИМ шибер
		eeprom_write_byte(&eep6, 230); //режим 3 ШИМ вентилятор
		eeprom_write_byte(&eep7, 200); //режим 3 ШИМ шибер
		eeprom_write_byte(&eep8, 1); // флаг первого запуска
	
	}
	//читаем настройки из памяти
	regim = eeprom_read_byte(&eep1); // читаем режим работы из eeprom
	R1_VENT = eeprom_read_byte(&eep2); // читаем режим 1 ШИМ вентилятор из eeprom
	R1_SHIBER = eeprom_read_byte(&eep3); //читаем режим 1 ШИМ шибер
	R2_VENT = eeprom_read_byte(&eep4); //читаем режим 2 ШИМ вентилятор
	R1_SHIBER = eeprom_read_byte(&eep5); //читаем режим 2 ШИМ шибер
	R3_VENT = eeprom_read_byte(&eep6); //читаем режим 3 ШИМ вентилятор
	R1_SHIBER = eeprom_read_byte(&eep7); 	//читаем режим 3 ШИМ шибер
	sei();
	_delay_ms(5);
/**********************************инициализация ШИМ*************************************/

	while(1){

//if (tempint=255) {LED1_ON;LED2_OFF;LED3_ON;termo_error=1;} else {termo_error=0;}//выводим код ошибки датчика темппературы 

buttons();//обработик нажатия кнопок

if (termo_error == 0){//блокировка по термодатчику
if(set == 0) { //нормальный режим работы
	if (regim == 0){ //режим работы 0
	LED1_OFF;
	LED2_OFF;
	LED3_OFF;
	LED4_OFF;
	SHIBER_PWM = 0; //ШИМ шибер 0-255
	VENT_PWM = 0; //ШИМ вентилятор 0-255
	}

	if (regim == 1){ //режим работы 1
	LED1_ON;
	LED2_OFF;
	LED3_OFF;
	LED4_OFF;
	VENT_PWM = R1_VENT; //ШИМ вентилятор 0-255
		if (tempint >=40) { //блокировка по температуре
		SHIBER_PWM = 0; //ШИМ шибер 0-255
		}else{
		SHIBER_PWM = R1_SHIBER; //ШИМ шибер 0-255
		}
	}

	if (regim == 2){ //режим работы 2
	LED1_OFF;
	LED2_ON;
	LED3_OFF;
	LED4_OFF;
	VENT_PWM = R2_VENT; //ШИМ вентилятор 0-255
		if (tempint >=60) { //блокировка по температуре
		SHIBER_PWM = 0; //ШИМ шибер 0-255
		}else{
		SHIBER_PWM = R2_SHIBER; //ШИМ шибер 0-255
		}
	}

	if (regim == 3){ //режим работы 3
	LED1_OFF;
	LED2_OFF;
	LED3_ON;
	LED4_OFF;
	VENT_PWM = R3_VENT; //ШИМ вентилятор 0-255
		if (tempint >=80) { //блокировка по температуре
		SHIBER_PWM = 0; //ШИМ шибер 0-255
		}else{
		SHIBER_PWM = R3_SHIBER; //ШИМ шибер 0-255
		}
	}
}
}else{
SHIBER_PWM=0;
VENT_PWM=0;
}
	if(set != 0) settings();//вход в настройки
} 

	//return 0;
}


 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Быстрый заказ печатных плат

Полный цикл производства PCB по низким ценам!

  • x
    мм
Заказать Получить купон на $5.00
Alexeyslav    615

Я бы в такой конструкции применил бы аналоговый датчик температуры - LM135 и фильтрацию результатов по "окну" с ним гораздо меньше проблем. Обращение с DS18B20 требует точного измерения времени импульса, а возникающие прерывания в процессе измерения всё портят, поэтому у вас имеются глюки. Попробуйте на время считывания/записи данных с датчика запрещать прерывания.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
IMXO    1 171
В 23 Август 2017 г. в 19:15, balistik сказал:

unsigned int clock = 0; //задержка для опроса датчика температуры

 

В 23 Август 2017 г. в 19:15, balistik сказал:

ISR(TIMER0_OVF_vect){ //прерывание таймера 0 для термодатчика

if (clock != 4294967295){_delay_us(50);clock++;}else{get_temp(0);clock=0;} }

что это за бред написан?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
ARV    306

Внутри обработчика прерывания таймера не следует опрашивать датчик. Опрос, как было сказано ранее, процедура длительная и чувствительная к задержкам. Длительные процедуры логично выполнять в основном цикле. Поэтому в обработчике прерывания таймера следует устанавливать какой-то флаг, а в главном цикле этот флаг опрашивать и, если он установлен, работать с датчиком и сбрасывать флаг.

Разумеется, процедура опроса датчика должна запрещать прерывания в критичные моменты - это не долго длится...

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
IMXO    1 171
12 минуты назад, ARV сказал:

Внутри обработчика прерывания таймера не следует опрашивать датчик.

его как раз и следует опрашивать в прерывании по одному байту , только уж точно не библиотеками

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
balistik    0

Спасибо. Отказался от цифрового датчика. Перешел на аналоговый LM. Все вроде работает. Протеус тормозит. Приходится комментировать часть кода, потом отлаживать оставшуюся. По поводу огромного числа - это просто крик души был. Блин. Надо бросать протеус и делать прототип.  Т.к. работу с еепром он тоже нормально не может симулировать.

Может кто посмотрит, что не так может быть с работой с еепром.

#define F_CPU 8000000L // óñòàíàâëèâàåì ðàáî÷óþ ÷àñòîòó êîíòðîëëåðà
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/eeprom.h>


unsigned int temp_ADC; //àíàëîãîâàÿ ïåðåìåííàÿ äàò÷èêà òåìïåðàòóðû
volatile //ìàêñèìóì 1024 ïðè íàïðÿæåíèè 5Â
//0 ãðàäóñîâ Öåëüñèÿ = 376
//100 ãðàäóñîâ Öåëüñèÿ = 451
volatile unsigned int tempint=0; // ïåðåìåííàÿ äëÿ öåëîãî çíà÷åíèÿ òåìïåðàòóðû
volatile unsigned int termo_error = 0; //ôëàã îøèáêè òåðìîäàò÷èêà
volatile unsigned char regim=0, R1_SHIBER=0, R1_VENT=0, R2_SHIBER=0, R2_VENT=0, R3_SHIBER=0, R3_VENT=0; //ïåðåìåííûå ðåæèìîâ ðàáîòû
volatile char press = 0, pr = 0, pr1 = 0, set = 0; //äîïîëíèòåëüíûå ïåðåìåííûå äëÿ êíîïîê

#define SHIBER_PB	1 //øèáåð ïîäà÷è òîïëèâà
#define SHIBER_PWM	OCR1A
#define VENT_PB	2 //âåíòèëÿòîð ïîäà÷è âîçäóõà
#define VENT_PWM	OCR1B


#define LED1_ON PORTD |= _BV(PD3) // ñâåòîäèîä ðåæèì 1
#define LED1_OFF PORTD &= ~_BV(PD3)
#define LED2_ON PORTD |= _BV(PD4) // ñâåòîäèîä ðåæèì 2
#define LED2_OFF PORTD &= ~_BV(PD4)
#define LED3_ON PORTD |= _BV(PD6) // ñâåòîäèîä ðåæèì 3
#define LED3_OFF PORTD &= ~_BV(PD6)
#define LED4_ON PORTD |= _BV(PD7) // ñâåòîäèîä 4 ïðîãðàììèðîâàíèå
#define LED4_OFF PORTD &= ~_BV(PD7)

#define BUT_M PIND & (1 << PD1)  // êíîïêà MENU
#define BUT_U PIND & (1 << PD2)  // êíîïêà UP
#define BUT_D PIND & (1 << PD0)  // êíîïêà DOWN

unsigned char eep1 EEMEM; // ðåæèì ðàáîòû
unsigned char eep2 EEMEM; // ðåæèì 1 ØÈÌ øèáåð
unsigned char eep3 EEMEM; //ðåæèì 1 ØÈÌ âåíòèëÿòîð
unsigned char eep4 EEMEM; // ðåæèì 2 ØÈÌ øèáåð
unsigned char eep5 EEMEM; //  ðåæèì 2 ØÈÌ âåíòèëÿòîð
unsigned char eep6 EEMEM; // ðåæèì 3 ØÈÌ øèáåð
unsigned char eep7 EEMEM; // ðåæèì 3 ØÈÌ âåíòèëÿòîð
unsigned char eep8 EEMEM; // ôëàã ïåðâîãî çàïóñêà


ISR (ADC_vect)//Ïðåðûâàíèÿ àíàëîãîâîãî âõîäà
{ 
	temp_ADC = ADCW;
	ADCSR |= (1<<ADSC);//çàíîâî âêëþ÷àåì àíàëîãîâûé âõîä
}



void pin_init(void) { //èíèöèàëèçàöèÿ ïîðòîâ ØÈÌ
    DDRB |= (1<<SHIBER_PB) | (1<<VENT_PB);
    PORTB &= ~((1<<SHIBER_PB) | (1<<VENT_PB));
}


void timer1_init(void) { //èíèöèàëèçàöèÿ òàéìåðà ØÈÌ 
   TCCR1A |= (1 << COM1A1) | (1 << COM1B1) | (1 << WGM11);
   TCCR1B |= (1 << WGM13) | (1 << WGM12) | (1 << CS10);
   TCNT1 = 0x00;
   ICR1 = 0xFF;
   OCR1A = 0x00;
   OCR1B = 0x00;
}

//***************** îáðàáîòêà íàæàòèÿ êíîïîê **********************
void buttons(){ 

	if(~BUT_U){if(set == 0)pr++;// êíîïêà UP
	//ðåæèì ðàáîòû +1 è âêëþ÷åíèå
	if(pr >= 1 && pr < 10){ 
			set = 20;
			regim++;
		if (regim>3){regim=3;}
		eeprom_write_byte(&eep1, regim); // ñîõðàíåíèå íàñòðîéêè â eeprom
		_delay_ms(200);
			set = 0;
			pr = 0;
		}
	}

	if(~BUT_D){if(set == 0)pr1++;// êíîïêà DOWN
	//ðåæèì ðàáîòû -1 è äî âûêëþ÷åíèÿ
	if(pr1 >= 1 && pr1 < 10){ 
			set = 20;
			regim--;
		//if (regim<1){regim=1;}
		eeprom_write_byte(&eep1, regim); // ñîõðàíåíèå íàñòðîéêè â eeprom
		_delay_ms(200);
			set = 0;
			pr1 = 0;
		}
	}

	if(~BUT_M){ // êíîïêà MENU
	//ïåðåõîä â íàñòðîéêè
		press++;  
	asm("cli");
		if(press >= 1 && set != 0){set++;} // ïåðåõîä ïî íàñòðîéêàì
		if(press <10 && set == 0){set = 1; _delay_ms(200);} // õîä â íàñòðîéêè
		
		if(set == 1) eeprom_write_byte(&eep2, R1_SHIBER);
		if(set == 2) eeprom_write_byte(&eep3, R1_VENT);
		if(set == 3) eeprom_write_byte(&eep4, R2_SHIBER);
		if(set == 4) eeprom_write_byte(&eep5, R2_VENT);	
		if(set == 5) eeprom_write_byte(&eep6, R3_SHIBER);
		if(set == 6) eeprom_write_byte(&eep7, R3_VENT);
	
		if(set == 8){ _delay_ms(100); set = 0; press = 0;} // âûõîäèì èç íàñòðîåê
		_delay_ms(200);
	asm("sei");			
	}

}
//*****************ðåæèì íàñòðîåê********************

void settings(){ 
//âèçóàëüíîå ïîäòâåðæäåíèå íàñòðîåê
if(set == 1) {
LED1_ON;
LED2_OFF;
LED3_OFF;
LED4_ON;
VENT_PWM = 0;
SHIBER_PWM = R1_SHIBER;} //ØÈÌ øèáåð 0-255
if(set == 2) {
LED1_ON;
LED2_OFF;
LED3_OFF;
LED4_ON;
SHIBER_PWM = 0;
VENT_PWM = R1_VENT;} //ØÈÌ âåíòèëÿòîð 0-255
if(set == 3) {
LED1_OFF;
LED2_ON;
LED3_OFF;
LED4_ON;
VENT_PWM = 0;;
SHIBER_PWM = R2_SHIBER;} //ØÈÌ øèáåð 0-255
if(set == 4) {
LED1_OFF;
LED2_ON;
LED3_OFF;
LED4_ON;
SHIBER_PWM =0;
VENT_PWM = R2_VENT;} //ØÈÌ âåíòèëÿòîð 0-255
if(set == 5) {
LED1_OFF;
LED2_OFF;
LED3_ON;
LED4_ON;
VENT_PWM = 0;
SHIBER_PWM = R3_SHIBER;} //ØÈÌ øèáåð 0-255
if(set == 6) {
LED1_OFF;
LED2_OFF;
LED3_ON;
LED4_ON;
SHIBER_PWM = 0;
VENT_PWM = R3_VENT;} //ØÈÌ âåíòèëÿòîð 0-255
if(set == 7) {
if (tempint>40){LED1_ON;}else{LED1_OFF;}
if (tempint>60){LED2_ON;}else{LED2_OFF;}
if (tempint>80){LED3_ON;}else{LED3_OFF;}} //êîíòðîëü äàò÷èêà òåìïåðàòóðû


switch(set) // âêëþ÷åíà íàñòðîéêà
	{
	case 1: // íàñòðîéêà R1_SHIBER
		if(~BUT_U){R1_SHIBER++; if(R1_SHIBER > 254) R1_SHIBER = 255; _delay_ms(100);}
		if(~BUT_D){R1_SHIBER--; if((~BUT_D) && R1_SHIBER == 0) R1_SHIBER = 0; _delay_ms(100);}
	break;

	case 2: // íàñòðîéêà R1_VENT
		if(~BUT_U){R1_VENT++; if(R1_VENT > 254) R1_VENT = 255; _delay_ms(100);}
		if(~BUT_D){R1_VENT--; if((~BUT_D) && R1_VENT == 0) R1_VENT = 0; _delay_ms(100);}
	break;

	case 3: // íàñòðîéêà R2_SHIBER
	if(~BUT_U){R2_SHIBER++; if(R2_SHIBER > 254) R2_SHIBER = 255; _delay_ms(100);}
		if(~BUT_D){R2_SHIBER--; if((~BUT_D) && R2_SHIBER == 0) R2_SHIBER = 0; _delay_ms(100);}
	break;

	case 4: // íàñòðîéêà R2_VENT
		if(~BUT_U){R2_VENT++; if(R2_VENT > 254) R2_VENT = 255; _delay_ms(100);}
		if(~BUT_D){R2_VENT--; if((~BUT_D) && R2_VENT == 0) R2_VENT = 0; _delay_ms(100);}
	break;

	case 5: // íàñòðîéêà R3_SHIBER
	if(~BUT_U){R3_SHIBER++; if(R3_SHIBER > 254) R3_SHIBER = 255; _delay_ms(100);}
		if(~BUT_D){R3_SHIBER--; if((~BUT_D) && R3_SHIBER == 0) R3_SHIBER = 0; _delay_ms(100);}
	break;

	case 6: // íàñòðîéêà R3_VENT
		if(~BUT_U){R3_VENT++; if(R3_VENT > 254) R3_VENT = 255; _delay_ms(100);}
		if(~BUT_D){R3_VENT--; if((~BUT_D) && R3_VENT == 0) R3_VENT = 0; _delay_ms(100);}
	break;	
	}
}


int main(){

	/*******************************íàñòðîéêà ïåðåôåðèè******************************/	
	asm("cli");
	if(eeprom_read_byte(&eep8) != 1){ // ÷èòàåì eeprom, åñëè òàì ìóñîð (ïåðâûé çàïóñê), ïèøåì ñâîè äàííûå
		eeprom_write_byte(&eep1, 0); // ðåæèì ðàáîòû
		eeprom_write_byte(&eep2, 150); // ðåæèì 1 ØÈÌ SHIBER
		eeprom_write_byte(&eep3, 100); //ðåæèì 1 ØÈÌ VENT
		eeprom_write_byte(&eep4, 200); //ðåæèì 2 ØÈÌ SHIBER
		eeprom_write_byte(&eep5, 150);  //ðåæèì 2 ØÈÌ VENT
		eeprom_write_byte(&eep6, 230); //ðåæèì 3 ØÈÌ SHIBER
		eeprom_write_byte(&eep7, 200); //ðåæèì 3 ØÈÌ VENT
		eeprom_write_byte(&eep8, 1); // ôëàã ïåðâîãî çàïóñêà
	
	}
	//÷èòàåì íàñòðîéêè èç ïàìÿòè
	regim = eeprom_read_byte(&eep1); // ÷èòàåì ðåæèì ðàáîòû èç eeprom
	R1_SHIBER = eeprom_read_byte(&eep2); // ÷èòàåì ðåæèì 1 ØÈÌ âåíòèëÿòîð èç eeprom
	R1_VENT = eeprom_read_byte(&eep3); //÷èòàåì ðåæèì 1 ØÈÌ øèáåð
	R2_SHIBER = eeprom_read_byte(&eep4); //÷èòàåì ðåæèì 2 ØÈÌ âåíòèëÿòîð
	R2_VENT = eeprom_read_byte(&eep5); //÷èòàåì ðåæèì 2 ØÈÌ øèáåð
	R3_SHIBER = eeprom_read_byte(&eep6); //÷èòàåì ðåæèì 3 ØÈÌ âåíòèëÿòîð
	R3_VENT = eeprom_read_byte(&eep7); 	//÷èòàåì ðåæèì 3 ØÈÌ øèáåð

	_delay_ms(100);

	pin_init();
 	timer1_init();

	ADMUX |= (1<<REFS0);//íàñòðàèâàåì àíàëîãîâûé âõîä íà ïîðò (PC0)
	//îïîðíîå íàïðÿæåíèå 5Â ïèòàíèÿ êîíòðîëëåðà
	ADCSRA |= (1<<ADEN) | (1<<ADSC) | (1<<ADIE) | (1<<ADPS1) | (1<<ADPS0);	                                                                        
	asm("sei");

	_delay_ms(100);

/**********************************èíèöèàëèçàöèÿ *************************************/

	while(1){

buttons();//îáðàáîòèê íàæàòèÿ êíîïîê

//âûâîäèì êîä îøèáêè äàò÷èêà òåìïïåðàòóðû
if (temp_ADC>1000){LED1_ON;LED2_OFF;LED3_ON;termo_error=1;} else {termo_error=0;}

//äåëàåì ðàñ÷åò òåìïåðàòóðû îò äàò÷èêà
tempint=((((((float)temp_ADC)*5)/1024)*100)-273);

if (termo_error == 0){//áëîêèðîâêà ïî òåðìîäàò÷èêó
if(set == 0) { //íîðìàëüíûé ðåæèì ðàáîòû
	if (regim == 0){ //ðåæèì ðàáîòû 0
	LED1_OFF;
	LED2_OFF;
	LED3_OFF;
	LED4_OFF;
	SHIBER_PWM = 0; //ØÈÌ øèáåð 0-255
	_delay_ms(20);
	VENT_PWM = 0; //ØÈÌ âåíòèëÿòîð 0-255
	}

	if (regim == 1){ //ðåæèì ðàáîòû 1
	LED1_ON;
	LED2_OFF;
	LED3_OFF;
	LED4_OFF;
	VENT_PWM = R1_VENT; //ØÈÌ âåíòèëÿòîð 0-255
	_delay_ms(20);
		if (tempint>40) { //áëîêèðîâêà ïî òåìïåðàòóðå
		SHIBER_PWM = 0; //ØÈÌ øèáåð 0-255
		}else{SHIBER_PWM = R1_SHIBER;} //ØÈÌ øèáåð 0-255
	}

	if (regim == 2){ //ðåæèì ðàáîòû 2
	LED1_OFF;
	LED2_ON;
	LED3_OFF;
	LED4_OFF;
	VENT_PWM = R2_VENT; //ØÈÌ âåíòèëÿòîð 0-255
	_delay_ms(20);
	if (tempint>60) { //áëîêèðîâêà ïî òåìïåðàòóðå
		SHIBER_PWM = 0; //ØÈÌ øèáåð 0-255
		}else{SHIBER_PWM = R2_SHIBER;} //ØÈÌ øèáåð 0-255
	}

	if (regim == 3){ //ðåæèì ðàáîòû 3
	LED1_OFF;
	LED2_OFF;
	LED3_ON;
	LED4_OFF;
	VENT_PWM = R3_VENT; //ØÈÌ âåíòèëÿòîð 0-255
	_delay_ms(20);
	if (tempint>80) { //áëîêèðîâêà ïî òåìïåðàòóðå
	SHIBER_PWM = 0; //ØÈÌ øèáåð 0-255
	}else{SHIBER_PWM = R3_SHIBER;} //ØÈÌ øèáåð 0-255
	}
}
}else{
SHIBER_PWM = 0;
_delay_ms(20);
VENT_PWM = 0;
}

	
	if(set != 0){settings();} //âõîä â íàñòðîéêè
} 

	return 0;
}


 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
IMXO    1 171
Только что, balistik сказал:

 Т.к. работу с еепром он тоже нормально не может симулировать.

это золотым рукам обычно всегда что то мешает.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
dasZebra    29
В 23.08.2017 в 19:56, Alexeyslav сказал:

DS18B20

работу с ним нужно разбить на две операции: сначала быстро плюнуть в него командой на замер темепературы и уйти дальше дела делать, а потом, смустя сколько то там времени (есно без этой delay) послать ему команду, получить данные. Все в главном цикле. Все очень быстро и совершенно не  тормозит и не нагружает. Никаких прерываний, кроме инкрементирования системного счетчика времени.

ps.

вобще использовать delay можно только в загрузочном куске main, до главного цикла. В цикле delay только при отладке или совсем уж калечных девайсах....

Изменено пользователем dasZebra

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
IMXO    1 171
7 минут назад, dasZebra сказал:

сначала быстро плюнуть в него командой на замер темепературы и уйти дальше дела делать

6 минут назад, dasZebra сказал:

Все очень быстро и совершенно не  тормозит и не нагружает.

бабушке расскажешь...  команда "замер температуры" длится минимум 10мс = критический участок= запрет прерываний= ошибка системного таймера +/-10мс

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
ARV    306
20 часов назад, IMXO сказал:

его как раз и следует опрашивать в прерывании по одному байту , только уж точно не библиотеками

Вы предлагаете вариант, требующий неслабых навыков в программировании, и говорите так, будто лучше этого варианта и быть не может. Я не согласен. Проще, чем опрашивать датчик в основном цикле при помощи уже готовой библиотечки, ничего не придумать. Всего -навсего надо убедиться, что в начале тайм-слота чтения и записи на 17-65 мкс запрещаются прерывания (в нормальной библиотечке это должно быть уже сделано).

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Alexeyslav    615
Цитата

"замер температуры" длится минимум 10мс

Это где такие сказки рассказывают? Длится-то оно длится, но процесс происходит внутри термометра и на контроллер никак не влияет - пока выполняется команда измерения температуры контроллер может заниматься своими делами, а потом просто прочитать значение хоть через две минуты. Надо только обеспечить термометру минимальное время на измерение(чем больше точность тем дольше) перед тем как давать любую команду, в т.ч. и на чтение иначе процесс будет прерван.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Alexeyslav    615
Цитата

говорите так, будто лучше этого варианта и быть не может.

Лучше варианта и не может быть. Но... не всем под силу. Всякие там библиотеки, будь даже трижды проверенные, содержат в себе целые поля граблей на которые наступаешь в тех или иных условиях. Но увы... вечные компромиссы между временем разработки и качеством кода.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
IMXO    1 171
5 часов назад, Alexeyslav сказал:

Это где такие сказки рассказывают?

не поверишь в даташите....

мастер для команды "конвертирование температуры"

передает сброс 480мкс + пауза 1-20мкс , ответ слейва 480мкс+пауза 1-20мкс итого грубо 1мс...

далее 64бита индификационого кода + 8 бит команды , итого 72бита по 125мкс = 9мс

общие время передачи команды 10мс, фирштейн?

а время конвертирования это из другой оперы и составляет для 12бит 750мс...

5 часов назад, ARV сказал:

Всего -навсего надо убедиться, что в начале тайм-слота чтения и записи на 17-65 мкс запрещаются прерывания (в нормальной библиотечке это должно быть уже сделано).

вот именно что в библиотеке запрет идет на все время передачи команды, те от 10мс = сбой системного таймера, даже если речь о 65мкс для системного тика 10-20мс это уже много, о сигнале  сброс и сигнале присутствие вообще молчу ...

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
dasZebra    29
1 час назад, IMXO сказал:

мастер для команды "конвертирование температуры"

передает сброс 480мкс + пауза 1-20мкс , ответ слейва 480мкс+пауза 1-20мкс итого грубо 1мс...

далее 64бита индификационого кода + 8 бит команды , итого 72бита по 125мкс = 9мс

общие время передачи команды 10мс, фирштейн?

Ja, Sie kann deutsch sprechen? Das ist prima!  Aber muss ich Sie ein mal traurich machen. Sie sind mehr denken oder überlegen. Diese Zeit ist für uns überhaupt nicht wichtig. Die Hauptsache ist, das Intervall zwischen die erste und zweite Order. 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
ARV    306
10 часов назад, IMXO сказал:

вот именно что в библиотеке запрет идет на все время передачи команды, те от 10мс = сбой системного таймера, даже если речь о 65мкс для системного тика 10-20мс это уже много, о сигнале  сброс и сигнале присутствие вообще молчу

Что такое 10 мс? Вроде как преобразование в худшем случае длится от 750 мс, тайм-слот длится не более 120 мкс, что такое 10 мс - не могу понять... А вообще, я вам уже говорил: в нормальной библиотеке запрет прерываний при реализации протокола 1-wire длится где-то от 17 до 65 мкс (в разных случаях по-разному), и разговор о всяких "системных тиках" это уже не по теме (или вы имеете ввиду какую-то ОС для AVR?!). Что касается импульсов RESET и PRESENCE, то для них вообще не требуется запрещать прерывания, т.к. допуски на их длительность достаточно большие по меркам быстродействия МК.

По поводу кривых библиотек я в курсе, но выпрямить их, сделав запрет прерываний только в нужных местах, гораздо проще, чем реализовать побитный прием данных из сети 1-wire по прерываниям таймера...

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Alexeyslav    615

В случае одного датчика на шине передавать идентификационый код не нужно, только команду начала преобразования.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
balistik    0

Всем спасибо. Построил прототип, все заработало на нем без проблем. Даже дисплей по i2c подключил еще.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Ваша публикация должна быть проверена модератором

Гость
Вы не авторизованы. Если у вас есть аккаунт, пожалуйста, войдите.
Ответить в тему...

×   Вставлено в виде отформатированного текста.   Восстановить форматирование

  Разрешено не более 75 смайлов.

×   Ваша ссылка была автоматически встроена.   Отобразить как ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставить изображения напрямую. Загрузите или вставьте изображения по ссылке.

Загрузка...

  • Похожие публикации

    • Автор: Xwerty
      Увидел такую схему (на ютуб) шим регулятора напряжения. скажите, чтобы использовать её как регулятор оборотов моторчика на +24V, надо что то доработать? читал коменты под видео, пишут что 555 горит при подключении моторчика.
       

    • Автор: я не волшебник, я учусь
      ПОМОГИТЕ!  Заказал на АЛИ блок питания 24v! при первом включении БАХ! ШИМ затерт, но думаю это NCP1200P60(вроде бы мал-мала подходит),  НО НЕ СТАРТУЕТ!  Hv-290v Vcc-10.6v OUTPUT-0! на выходе блока питания вместо 24 v - 2.5v! ВОПРОС - ЧТО БЫ ЭТО ЗНАЧИЛО?!
    • Автор: Flash6300
      Приветствую всех. 
      Как на атмега8 подать единицу на конкретную ногу, а не на весь порт? То есть
      if (PINB&(1<<PB0)) { k=1; PORTC=0b0001001; } как теперь подать 1 на второй пин, не таким образом PORTC=0b0001011, а как-то по другому
    • Автор: NDG
      Прошу помощи сообщества в решении такой проблемы.
      Имеем Attiny13 задачей которой стоит формирование ШИМ сигнала, скважность задаём состояние входов PB4 PB3 PB2. 
      Загвоздка в том, что не могу заставить тиньку сменить скважность, несмотря на то, что на прерывание по состоянию входов реагирует, значения в OCR0A заносит. Маленькое замечание в железе не делал, только в Proteus.
      Код:
      #define F_CPU 9600000
      #include <avr/io.h>
      #include <avr/eeprom.h>
      #include <avr/interrupt.h>
      volatile bool SetMode_flag = false;
      volatile char Select_Mode = 0;
      //-------------------------------------------------
      void PWM_init() 
      {
          //Порты PB0 и PB1 устанавливаем на выход, остальные на вход
          DDRB = 0b00000011;
          //Входные порты PINB0 и PINB1 в HIGH, остальные в Pull-UP 
          PORTB = 0b00111111;
          //Разрешаем прерывания PCINT1 - по изменению вывода 
          GIMSK |= (1<<PCIE);
          //Накладываем маску на выводы
          PCMSK |= (1<<PINB4) |(1<<PINB3) |(1<<PINB2);
          //Запрещаем все прерывания пo совпадению и переполнению
          TIMSK0 = 0x00;
          //Устанавливаем режим работы таймера в режиме ШИМ с фазовой коррекцией
          TCCR0A |= (1<<COM0A1) |(1<<COM0B1) |(0<<WGM01) |(1<<WGM00);
          TCCR0B |= (1<WGM02);
          //Предделитель частоты уставливаем clk\1024 или приблизительно 18Гц
          //         Fclk_I/O
          //Fpcpwm = --------  (N предделитель 1, 8, 64, 256, 1024)
          //          N *510 
          TCCR0B |= (1<<CS02) |(0<<CS01) |(1<<CS00);
          //Обнуляем счётный регистр
          TCNT0 = 0x00;    
      }
      //-------------------------------------------------
      ISR (PCINT0_vect)
      {
          SetMode_flag = true;  // Устанавливаем флаг события
          Select_Mode = (PINB >> 2); //Сохраняем значение со сдвигом младших разрядов
      }
      //-------------------------------------------------
      int main(void)
      {
          PWM_init();
          sei();
          while (1)
          {
              
              if (SetMode_flag) 
              {
                  switch ( Select_Mode )
                  {    case 0:
                          OCR0A = 0; break;        // ШИМ выключен
                      case 1:
                          OCR0A = 40; break;        //Скважность 15%
                      case 2:
                          OCR0A = 80; break;        //Скважность 30%
                      case 3:
                          OCR0A = 120; break;        //Скважность 45%
                      case 4:
                          OCR0A = 150; break;        //Скважность 60%
                      case 5:
                          OCR0A = 180; break;        //Скважность 75%
                      case 6:
                          OCR0A = 210; break;        //Скважность 90%
                      case 7:
                          OCR0A = 255; break;        //Включен постоянно
                      default:
                           break;
                  }
                  SetMode_flag = false; //Сбрасывем флаг
              }
          }
      }
      main.cpp
      PWM neew.pdsprj
    • Автор: mefi73
      Этот ШИМ генератор мне предоставил на обзор магазин ICstation (ссылка на генератор)
      Фото генератора.


      Что может этот генератор? Взглянем на параметры.
       Рабочее напряжение: 3.3 - 30V; Частота генерации: 1Hz - 150KHz; Точность генерации частоты: 2%; Мощность нагрузки: 5…30mА; Амплитуда выходного сигнала равна напряжению питания; Температура окружающей среды: -20 … +70 °С.
      На дисплей можно вывести только 2 числа по 3 цифры в каждом. В нижней строке отображается скважность ШИМ в процентах, а в верхней – частота. Частота выводится на дисплей по следующим правилам:
      XXX, шаг в 1Гц, в диапазоне 1 – 999Гц; X.XX, шаг в 0.01кГц, в диапазоне 1.00 - 9.99кГц; XX.X, шаг в 0.1кГц; в диапазоне 10.0 - 99.9кГц; X.X.X, шаг в 1 кГц; в диапазоне 100 - 150 кГц. Дисплей управляется микросхемой HT1621B, дисплей универсальный, на нем имеются символы, необходимые для построения термометра, гигрометра, вольтметра, амперметра и ваттметра, но в нашем случае они не используются. Дисплей имеет яркую синюю подсветку. К слову, замечу, что дисплей на моем генераторе оказался потертым, будто его откуда-то сняли. Так же отсутствовала защитная пленка на дисплее.

      Главной микросхемой генератора является микроконтроллер STM8S003F3P6. И поскольку этот микроконтроллер имеет EEPROM память, то настройки сохраняются при выключении.
      Управлять генератором можно двумя способами: кнопками и по UART. С кнопками всё ясно, одна пара кнопок управляет частотой, вторая скважностью. А вот с UART всё намного интереснее. Обмен данными должен происходить со следующими параметрами:
       9600 bps Data bits: 8 Stop bit: 1 Check digit: none  Flow control: none Для того что бы установить частоту генерации, необходимо отправить частоту так, как она отображается на дисплее прибавив перед значением частоты букву F. Например, для установки частоты в 100 Гц необходимо отправить F100, для 105 кГц - F1.0.5, для 10.5 кГц - F10.5 и так далее.
      Для установки скважности необходимо отправить трехзначное число скважности добавив перед ним букву D . Например, D050, D100, D001.
      Что бы прочитать установленные параметры, необходимо отправить слово "read".
      Если отправлена верная команда, то генератор ответит DOWN, если ошибочная – FALL. Но есть одно НО, я так и не смог настроить работу с генератором через UART.
      Я решил проверить генератор при помощи логического анализатора. Вот что получилось.
      Частота 1 Гц, скважность 1%. Как видим погрешность пока небольшая.

      Частота 1 Гц, скважность 50%.

      Частота 1 Гц, скважность 99%.

      Частота 1 кГц, скважность 1%.

      Частота 1 кГц, скважность 50%.

      Частота 1 кГц, скважность 99%.  Тут мы видим, что при установленных 99% скважности на самом деле заполнение составляет 100%.

      Частота 1 кГц, скважность 91%. Я начал снижать скважность, и вплоть до 92% заполнение составляло 100%, и только при 91% ситуация исправляется.

      Частота 50 кГц, скважность 1%. Как видим что тут всего 0,2% вместо 1%.

      Частота 50 кГц, скважность 50%. Здесь отличается на -1%.

      Частота 50 кГц, скважность 99%. И тут снова отклонение -1%.

      Частота 100 кГц, скважность 1%. А вот тут ещё ничего нет.

      Частота 100 кГц, скважность 2%. А при 2% сигнал появляется, но на самом деле заполнение 0,4%.

      Частота 100 кГц, скважность 50%. Отклонение почти -2%.

      Частота 100 кГц, скважность 99%. И тут почти -1%.

      Частота 150 кГц, скважность 1%. Снова нет сигнала.

      Частота 150 Гц, скважность 3%. И появляется сигнал только при 3%, но заполнение составляет 0,6%.

      Частота 150 кГц, скважность 50%. Но на самом деле заполнение 46,5%, на -3,5% уже отличие.

      Частота 150 кГц, скважность 99%. И тут отличается, но всего -1,5%.

      Выборка достаточно грубая, но на этом исследования не закончены. Я решил измерить скважность при различном заполнении (шаг 5%) и на различных частотах (шаг 25000 Гц) и занести их в таблицу.
      Верхняя строка содержит частоту, я выбрал шаг в 25 кГц, левый столбец – установленная скважность, в остальных ячейках замеренная скважность.

      В этой таблице указана разница между установленной и замеренной скважности.

      Чем выше частота, тем больше отклонение между установленным и замеренным значениями. Так же замеренная скважность всегда ниже установленной, но строгой закономерности в отклонении не наблюдается.
      Так же я проверил соответствие установленной и замеренной частоты. Результат так же занес в таблицу.

      Заявленная точность в 2% от установленной частоты соблюдается.
      В итоге, если вам необходимо установить точные значения генерации, то проверяйте установленные параметры перед использованием генератора. Если же необходимо просто управлять яркостью светодиода или скоростью вращения двигателя, то этот генератор без проблем подойдет для этих задач.