Плавное включение ШИМ tiny13A

Alex_pcb
Offline
Зарегистрирован: 11.12.2017

Прошу помочь с кодом, готов оплатить не большую сумму.
 
код внизу , но проблема в том что резко включается и моторчик , просто вздрагивает . А вот плавное выключение вроде как у меня получилось .
Код за основу взял с примеров с интернета 

почта: budaev919@gmail.com

 

// 12V_Dimmer_v2.c
// 2nd generation of 12V Dimmer project
// dale wheat - 27 march 2010

// notes:

// device:  ATtiny13 or ATtiny13A
// clock:   4.8 MHz internal RC oscillator, shortest startup time
// brownout detect:  2.7V

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <avr/eeprom.h>
#include <avr/wdt.h>
#include <util/delay.h>
#define F_CPU 4800000UL

// These registers are available on the ATtiny13A but not the original ATtiny13

// Brown out detector control register

#define BODCR _SFR_IO8(0x30)
#define BODSE 0
#define BODS 1

// Power reduction register

#define PRR _SFR_IO8(0x3C)
#define PRADC 0
#define PRTIM0 1

///////////////////////////////////////////////////////////////////////
// macros
///////////////////////////////////////////////////////////////////////

#define nop() asm("nop")

#define sbi(port, bit) (port) |= (1 << (bit))
#define cbi(port, bit) (port) &= ~(1 << (bit))

///////////////////////////////////////////////////////////////////////
// system constants
///////////////////////////////////////////////////////////////////////

#define PWM_MAX (248 << 8)
#define DIAL_HYSTERESIS (10 << 8)

///////////////////////////////////////////////////////////////////////
// global variables
///////////////////////////////////////////////////////////////////////

typedef enum {
	MODE_DIAL,
	MODE_BUTTON,
} MODE;

//volatile MODE mode __attribute__ ((section(".noninit"))); // operational mode, survives resets
volatile unsigned char mode; // can't watch defined types in debugger

///////////////////////////////////////////////////////////////////////
// EEPROM non-volatile storage section
///////////////////////////////////////////////////////////////////////

//unsigned char eeprom_do_not_use EEMEM; // bad luck - do not use location 0
//unsigned char eeprom_mode EEMEM; // mode storage location
//unsigned char eeprom_button_index EEMEM; // last known button index

enum {
	eeprom_do_not_use, // bad luck - do not use location 0
	eeprom_mode, // mode storage location
	eeprom_dial_trigger_low,
	eeprom_dummy_1,
	eeprom_dial_trigger_high,
	eeprom_dummy2,
	eeprom_button_index, // last known button index
};

///////////////////////////////////////////////////////////////////////
// adc() - read analog value: Vcc=0, gnd=PWM_MAX, returns 0 if no potentiometer installed
///////////////////////////////////////////////////////////////////////

#define VCC_PORT PORTB
#define VCC_PIN PB3

#define vcc_on() sbi(VCC_PORT, VCC_PIN)
#define vcc_off() cbi(VCC_PORT, VCC_PIN)

unsigned int adc(void) {

	unsigned int value; // return value

	vcc_on(); // apply Vcc to potentiometer

	// configure on-chip analog-to-digital converter

	ADMUX = 0<<REFS0 | 1<<ADLAR | 1<<MUX1 | 0<<MUX0; // REF = Vcc, left adjust, ADC2/PB4 selected
	ADCSRA = 1<<ADEN | 0<<ADSC | 0<<ADATE | 1<<ADIF | 1<<ADIE | 1<<ADPS2 | 1<<ADPS1 | 0<<ADPS0;

	// go to sleep, wake when conversion complete

	set_sleep_mode(SLEEP_MODE_IDLE); // "SLEEP_MODE_ADC" shuts down PWM clock, so use "IDLE" mode instead
	sleep_enable();
	sleep_cpu();

	// conversion is complete

	value = ADC; // get converted analog value from ADC
	value = ~value; // invert bits
	value &= 0xFFC0; // mask 10 significant bits
	vcc_off(); // remove Vcc from potentiometer

	// disable ADC
	// disable ADC conversion complete interrupt
	// clear pending conversion conplete interrupt, if any

	ADCSRA = 0<<ADEN | 0<<ADSC | 0<<ADATE | 1<<ADIF | 0<<ADIE | 1<<ADPS2 | 1<<ADPS1 | 0<<ADPS0;

	return value;
}

///////////////////////////////////////////////////////////////////////
// button_state() - return state of push button
///////////////////////////////////////////////////////////////////////

#define BUTTON_PORT PINB
#define BUTTON_PIN PB0

enum {
	BUTTON_RELEASED,
	BUTTON_PRESSED
};

unsigned char button_state(void) {

	if(bit_is_clear(BUTTON_PORT, BUTTON_PIN)) {
		return BUTTON_PRESSED; // button pressed, it seems
	} else {
		return BUTTON_RELEASED; // button not pressed, it seems
	}
}

///////////////////////////////////////////////////////////////////////
// pwm() - set PWM output value
///////////////////////////////////////////////////////////////////////

void pwm(unsigned int value) {

int flag_but;

if( flag_but == 0  && (PINB & (1 << PB2)) == 0 || (value >> 8 == 0) ) 
{

         flag_but = 1;
		OCR0A = (PWM_MAX >> 8) - 1; // set TOP value for PWM output:  composite of min reading from ADC with pullup (~252) and limitations of averaging aglorithm (+/- 1)
		OCR0B = 100; // normal case, simply set value
           _delay_ms(1000);
		   //
		cbi(PORTB, PB1); // set output to low level (should already be, but)
		TCCR0A = 0<<COM0A1 | 0<<COM0A0 | 0<<COM0B1 | 0<<COM0B0 | 0<<WGM01 | 0<<WGM00; // PWM off
		TCCR0B = 0<<FOC0A | 0<<FOC0B | 0<<WGM02 | 0<<CS02 | 0<<CS01 | 0<<CS00; // PWM clock = off

	}
	
	else  {

		// это цикл повторяеться не менять , иначе будет спотыкаться
		OCR0A = (PWM_MAX >> 8) - 1; // set TOP value for PWM output:  composite of min reading from ADC with pullup (~252) and limitations of averaging aglorithm (+/- 1)	   
		OCR0B = value >> 8; // normal case, simply set value
		TCCR0A = 0<<COM0A1 | 0<<COM0A0 | 1<<COM0B1 | 0<<COM0B0 | 1<<WGM01 | 1<<WGM00; // PWM B on
		TCCR0B = 0<<FOC0A | 0<<FOC0B | 1<<WGM02 | 0<<CS02 | 0<<CS01 | 1<<CS00; // PWM clock = CK/256
	    // это цикл повторяеться не менять , иначе будет спотыкаться
	}

}

///////////////////////////////////////////////////////////////////////
// main() - main program function
///////////////////////////////////////////////////////////////////////

int main(void) {

	// system-level variables
	int flag_but = 0;
	unsigned int brightness = 0; // how bright my light is
	int proportional_error = 0, derivative_error = 0; // filter terms
	int error;

	// dial mode variables

	unsigned int dial_reading;
	unsigned int dial_trigger_low, dial_trigger_high; // escape from button mode values

	// button mode variables
	//unsigned char button_value; // to measure duration of button press
	unsigned char button_pressed = 0; // flag indicates button is currently believed to be pressed
	unsigned char button_released = 1; // flag indicates that button is believed to be released

	unsigned char button_press_event = 0; // button press event flag
	const unsigned int button_preset[] = { 0, 0x100, 6349, 15872, 31744, PWM_MAX }; // 0%, min visible, 10%, 25%, 50%, 100%
	const int button_step_rate[] = { 12 << 8, 1 << 8, 1 << 8, 2 << 8, 3 << 8, 5 << 8 }; // linear step rates
	unsigned char button_index = 0;

	// initialize everything

	// turn off unused peripherals to save power

	ACSR = 1<<ACD; // disable analog comparator
	DIDR0 = 1<<ADC3D | 1<<ADC2D | 0<<ADC1D | 1<<ADC0D | 1<<AIN1D | 0<<AIN0D; // disable unused digital inputs on ADC/AC (except PB1/AIN1/INT0)

	// initialize input & output port PORTB

	//	PB0		5		MOSI/AIN0/OC0A/PCINT0		pushbutton input
	//	PB1		6		MISO/AIN1/OC0B/INT0/PCINT1	PWM output B
	//	PB2		7		SCK/ADC1/T0/PCINT2			debug output
	//	PB3		2		PCINT3/CLKI/ADC3			Vcc for potentiometer
	//	PB4		3		PCINT4/ADC2					analog input for potentiometer
	//	PB5		1		PCINT5/-RESET/ADC0/dW		RESET button (maybe)

	DDRB = 0<<DDB5 | 0<<DDB4 | 1<<DDB3 | 0<<DDB2 | 1<<DDB1 | 0<<DDB0;
	PORTB = 1<<PORTB5 | 1<<PORTB4 | 0<<PORTB3 | 0<<PORTB2 | 0<<PORTB1 | 1<<PORTB0;

	// initialize ATtiny13 external & pin change interrupts

	PCMSK = 0<<PCINT5 | 0<<PCINT4 | 0<<PCINT3 | 0<<PCINT2 | 0<<PCINT1 | 1<<PCINT0;

	sei(); // enable global interrupts

	// restore saved values from EEPROM

	mode = eeprom_read_byte((const uint8_t *) eeprom_mode);
	//if((mode != MODE_DIAL) && (mode != MODE_BUTTON)) mode = MODE_DIAL; // default, explicit
	if(mode != MODE_BUTTON) mode = MODE_DIAL; // default, slightly more optimized

	//dial_trigger_low = eeprom_read_byte((const uint8_t *) eeprom_dial_trigger_low);
	dial_trigger_low = eeprom_read_word((const uint16_t *) eeprom_dial_trigger_low);
	//dial_trigger_high = eeprom_read_byte((const uint8_t *) eeprom_dial_trigger_high);
	dial_trigger_high = eeprom_read_word((const uint16_t *) eeprom_dial_trigger_high);

	button_index = eeprom_read_byte((const uint8_t *) eeprom_button_index);
	if(button_index >= (sizeof(button_preset) / sizeof(button_preset[0]))) button_index = 0; // default

	// the big loop
	
	



	
	
	
	
	
	
	
	
	
	
	
	
	
	

	while(1) {
	


		dial_reading = adc(); // get new input value

		// determine if button events (button press or button release) have occurred

		if(button_released) {
			if(button_state() == BUTTON_PRESSED) {
				button_press_event = 1; // a button press event has occurred
				button_pressed = 1; // pressed
				button_released = 0; // not released
			}
		} else if(button_pressed) {
			if(button_state() == BUTTON_RELEASED) {
				//button_release_event = 1; // a button release event has occurred
				button_pressed = 0; // not pressed
				button_released = 1; // released
			}
		}

		switch(mode) {

			case MODE_DIAL: // dial mode active - responds to input potentiometer

				if(button_press_event) {

					//button_press_event = 0; // consume event
					mode = MODE_BUTTON; // shift to button mode
					eeprom_write_byte((uint8_t *) eeprom_mode, mode); // commit to memory

					// set trigger points to escape button mode via dial adjust

					if(dial_reading >= DIAL_HYSTERESIS) {
						dial_trigger_low = dial_reading - DIAL_HYSTERESIS;
					} else {
						dial_trigger_low = 0; // avoid going negative here
					}
					eeprom_write_word((uint16_t *) eeprom_dial_trigger_low, dial_trigger_low); // commit to memory

					if(dial_reading < ~DIAL_HYSTERESIS) {
						dial_trigger_high = dial_reading + DIAL_HYSTERESIS;
					} else {
						dial_trigger_high = 0xFFFF;
					}
					eeprom_write_word((uint16_t *) eeprom_dial_trigger_high, dial_trigger_high); // commit to memory

					continue; // start over at the top of the big loop
				}

				// PD filter

				error = dial_reading - brightness; // compute error term
				
				proportional_error = error >> 2; // Kp = 1/4;  normal
				
				brightness += (proportional_error + derivative_error); // sum error terms

				derivative_error = proportional_error >> 1; // Kd = 1/2

				break;

			case MODE_BUTTON: // 6-click dimmer mode

				// mode decision

				if((dial_reading < dial_trigger_low) || (dial_reading > dial_trigger_high)) {
					mode = MODE_DIAL; // switch back to dial mode
					eeprom_write_byte((uint8_t *) eeprom_mode, mode); // commit to memory
					continue; // start over at the top of the big loop
				}

				// button press action

				if(button_press_event) {
					button_press_event = 0; // consume event
					button_index++; // advance button preset index
					if(button_index >= sizeof(button_preset) / sizeof(button_preset[0])) button_index = 0; // rollover
					eeprom_write_byte((uint8_t *) eeprom_button_index, button_index); // commit to memory
				}

				error = (button_preset[button_index] >> 1) - (brightness >> 1); // distance from target

				if(error > button_step_rate[button_index]) {
					brightness += button_step_rate[button_index];
				} else if(error < -button_step_rate[button_index]) {
					brightness -= button_step_rate[button_index];
				} else {
					brightness = button_preset[button_index]; // close enough - get there fast
				}

				break;
		}

		pwm(brightness); // set PWM level

		// prepare for a variable period of sleep:  16ms for normal, 250ms for sleepy

		wdt_reset(); // reset the watchdog timer
		if(brightness > 255) {
			// a short nap while the output is somewhat on
			WDTCR = 0<<WDTIF | 0<<WDTIE | 0<<WDP3 | 1<<WDCE | 1<<WDE | 0<<WDP2 | 0<<WDP1 | 0<<WDP0; // enable changes
			WDTCR = 1<<WDTIF | 1<<WDTIE | 0<<WDP3 | 0<<WDCE | 0<<WDE | 0<<WDP2 | 0<<WDP1 | 0<<WDP0; // new values: 16ms
			set_sleep_mode(SLEEP_MODE_IDLE);
			//sleep_enable();
		} else {
			// shut down as much as possible when the output is completely off
			WDTCR = 0<<WDTIF | 0<<WDTIE | 0<<WDP3 | 1<<WDCE | 1<<WDE | 0<<WDP2 | 0<<WDP1 | 0<<WDP0; // enable changes
			WDTCR = 1<<WDTIF | 1<<WDTIE | 0<<WDP3 | 0<<WDCE | 0<<WDE | 1<<WDP2 | 0<<WDP1 | 0<<WDP0; // new values: 250ms
			GIFR = 1<<INTF0 | 1<<PCIF; // clear pending interrupts
			GIMSK = 0<<INT0 | 1<<PCIE; // enable pin change interrupt for instant wake-up on button-press
			set_sleep_mode(SLEEP_MODE_PWR_DOWN);

		}

		// go to sleep; wait for interrupts

		sleep_enable();
		sleep_cpu();

		// recover from deep sleep

		GIMSK = 0<<INT0 | 0<<PCIE; // disable pin change interrupt
	}
}

///////////////////////////////////////////////////////////////////////
// pin-change interrupt handler
///////////////////////////////////////////////////////////////////////

EMPTY_INTERRUPT(PCINT0_vect);

///////////////////////////////////////////////////////////////////////
// timer/counter0 overflow interrupt handler
///////////////////////////////////////////////////////////////////////

//EMPTY_INTERRUPT(TIM0_OVF_vect);

///////////////////////////////////////////////////////////////////////
// analog-to-digital converter interrupt handler
///////////////////////////////////////////////////////////////////////

EMPTY_INTERRUPT(ADC_vect);

///////////////////////////////////////////////////////////////////////
// watchdog timer interrupt handler
///////////////////////////////////////////////////////////////////////

EMPTY_INTERRUPT(WDT_vect);

///////////////////////////////////////////////////////////////////////

// [end-of-file]

 

Kakmyc
Offline
Зарегистрирован: 15.01.2018

Переменная flag_but в строках 149, 151, 154 ,не имеет никакой смысловой нагрузки и не делает абсолютно ничего.

ELECTROS
Offline
Зарегистрирован: 28.05.2021

Kakmyc пишет:
Переменная flag_but в строках 149, 151, 154 ,не имеет никакой смысловой нагрузки и не делает абсолютно ничего.

Так еще и полагаться на компилятор..., чё оно там запишит при инициализации, по видимому раз хоть что то работает то инциализирует нулём.

b707
Offline
Зарегистрирован: 26.05.2017

ELECTROS пишет:

Так еще и полагаться на компилятор..., чё оно там запишит при инициализации, по видимому раз хоть что то работает то инциализирует нулём.

В любой книжке по Си четко расписано, что и как инициализируется... "полагаться на компилятор" необязательно, если знаешь

rst
Offline
Зарегистрирован: 25.06.2018

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

Там будет мусор от предыдущего кода.

 

PS: Хотя некоторые компиляторы, в некоторых режимах (DEBUG) заполняют такие переменные неким шаблоном (в целях отладки). Но это не обязательно.

ELECTROS
Offline
Зарегистрирован: 28.05.2021

b707 пишет:

ELECTROS пишет:

Так еще и полагаться на компилятор..., чё оно там запишит при инициализации, по видимому раз хоть что то работает то инциализирует нулём.

В любой книжке по Си четко расписано, что и как инициализируется... "полагаться на компилятор" необязательно, если знаешь

Делайте тогда так, а вообще это настраивается в IDE и по умолчанию может быть любая установка.

b707
Offline
Зарегистрирован: 26.05.2017

ELECTROS пишет:

Делайте тогда так, а вообще это настраивается в IDE и по умолчанию может быть любая установка.

что настраивается в ИДЕ ? инициализация переменных? - покажете?

b707
Offline
Зарегистрирован: 26.05.2017

rst пишет:

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

а я разве что другое сказал? :) - именно что в книжке написано, что именно инициализируется (и как), а что нет.

Поэтому "полагаться на компилятор" смысла нет.

 

Правда товарищ спорит, что это мол "настраивается в ИДЕ"... пусть покажет.

ELECTROS
Offline
Зарегистрирован: 28.05.2021

b707 пишет:

rst пишет:

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

а я разве что другое сказал? :) - именно что в книжке написано, что именно инициализируется (и как), а что нет.

Поэтому "полагаться на компилятор" смысла нет.

 

Правда товарищ спорит, что это мол "настраивается в ИДЕ"... пусть покажет.

Я давно это использовал и забыл уже, если вам прям это важно я могу поискать, но чтобы потом не было тыканья пальцами, конкретно сейчас я говорю про Code Composer Studio, допускаю что не во всех это есть.

b707
Offline
Зарегистрирован: 26.05.2017

ELECTROS пишет:

Я давно это использовал и забыл уже, если вам прям это важно я могу поискать, но чтобы потом не было тыканья пальцами, конкретно сейчас я говорю про Code Composer Studio, допускаю что не во всех это есть.

ну тоже "чтобы потом не было..." отмазок с вашей стороны - инициализация глобальных и статических локальных переменных прописана в стандарте языка и на всех компиляторах одинакова. Ни в каких "опциях ИДЕ" это не настраивается. Локальные переменные не инициализируются и это опять же прописано в стандарте и от компилятора не зависит.

Отдельные значения ОТДЕЛЬНЫХ ПЕРЕМЕННЫХ можно задать опциями компилятора, но общего принципа это не меняет. Если покажете что-то иное - с удовольствием посмотрю, но пока будем считать, что ваше замечание в сообщении №2 не особо грамотное.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

в Интеле xor ax,ax использовалась однако

rst
Offline
Зарегистрирован: 25.06.2018

b707 пишет:
Локальные переменные не инициализируются и это опять же прописано в стандарте и от компилятора не зависит.
Всё-таки - в некоторых IDE, с целью отладки, и локальные переменные инитятся. Например в VS, при DEBUG-компиляции это по умолчанию включено. Во все неинициализированные переменные прописывается 0xCCCCCCCC. Не только локальные, но и динамические, которые из кучи выделяются.

Это нужно для обнаружения использования неинициализированных данных. А также для обнаружения использования динамических переменных после их освобождения.

Но это конечно именно отладочная фича и в стандарте си не оговаривается.

b707
Offline
Зарегистрирован: 26.05.2017

ОК, для начала я признаю, что был излишне категоричен.

rst пишет:

Всё-таки - в некоторых IDE, с целью отладки, и локальные переменные инитятся. Например в VS, при DEBUG-компиляции это по умолчанию включено. Во все неинициализированные переменные прописывается 0xCCCCCCCC. Не только локальные, но и динамические, которые из кучи выделяются.

а теперь немного поспорю.

Это же не так просто - взять и прописать во все локальные переменные некое НЕСТАНДАРТНОЕ значение. ИМХО, средствами одной ИДЕ этого не сделать. ИДЕ это вообще не более чем интерфейс над тулчейном. Нужен специально приспособленный компилятор и линкер?

Но если взять VS - оно вообще само компилировать не умеет, используя для этого внешние средства, причем для каждого таргета свои. Из чего, на мой взгляд, вытекает два варианта

1. либо это работает только для очень малого числа платформ

2. либо такая опция все же есть в стандартном gcc

Первый вариант неинтересен, а вот если о втором кто-то что-то знает - хотелось бы послушать.

 

rst
Offline
Зарегистрирован: 25.06.2018

Конечно речь шла про связку: IDE+компилятор+компоновщик. VS под win.x86 и компиляция для него же.

Alex_pcb
Offline
Зарегистрирован: 11.12.2017

Я понял, что пример с интернета какой то явно старый видимо))), под компилятор под древний.

Тогда по новой ,  задача такая : есть
1)atiny13A
2)кнопка вкл-выкл 
3)регулятор скорости (10 килоом самый простой, крутилка, подстрочный резистор  )
4)транзистор полевой irl3705 , работает без какого либо драйвера , 5 вольт ему хватает для шим. IRF640 такой не подходит.
5) еепром нужно задеествовать , чтобы запоминал последнию скорость настроенную 

Управляет это всё : коллекторным моторчиком от шуруповерта

Я не знаю, сколько это будет стоить. Но готов оплатить денежку!. Вроде как начал писать на ардуино. А там блин памяти не хватает, то ли ботлуадер убирать, то ли как то сокращать что то не понятно. Но на языке ардуино тоже подойдет.


 

Kakmyc
Offline
Зарегистрирован: 15.01.2018

3000р
kakmycmail@gmail.com

ЗЫ:скорость задаём резистором, но нужно запоминать последнюю... Смысл ?

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Фетишь или вероятность сместить резистор в выключенном состоянии. Но тогда второе бессмысленно, поэтому - фетишь ))

Alex_pcb
Offline
Зарегистрирован: 11.12.2017

1500р цена , кто готов взяться чтобы сделать такой маленький код. Дайте знать, моя почта: budaev919@gmail.com/ 

b707
Offline
Зарегистрирован: 26.05.2017

Alex_pcb пишет:

1500р цена , кто готов взяться чтобы сделать такой маленький код. Дайте знать, моя почта: budaev919@gmail.com/ 

вместо тини13 возьми тини85 или обычную ардуину - тогда памяти хватит и напишешь сам. Это полезнее для навыков и деньги сэкономишь.

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Alex_pcb пишет:

1500р цена , кто готов взяться чтобы сделать такой маленький код. Дайте знать, моя почта: budaev919@gmail.com/ 

Если ты не валяешь дурака, то:

1. по теперешним временам рубли на карте как-то не сильно полезны. если не сказать  "нах не нужны". Готов ли платить криптой или  деньгами на иностранную карту? Пусть даже 15 долларов?

2. Схема не правильная. Транзистор нужен лоджик-левел или драйвер иначе включать. Добавь еще 5-10 евро и я тебе накидаю картинку на салфетке химическим карандашиком ;)). По желанию

3. Код для тиньки13 конечно есть. Б707 тебе разумно советует тиньку25/45/85, но хватит и 13. Я скажу как собирать.

4. Ввиду малости сумму - хрен с тобой, плати на русскую карту рублями. 2000р будет рублями. Просто имей ввиду, на будущее.

5. Ну и связь - телега @wdrakula.

Alex_pcb
Offline
Зарегистрирован: 11.12.2017

Всем спасибо, что откликнулись. Понял что всем нужно написать ТЗ, и было не понятно)) . А как правильно написать задание?). Короче сел сам за ПК, что то экспрементировал . И вот получилось самому!. Скажите пожалуйста такой код будет работать стабильно, или я что то не учел ??? 

 


//#include <EEPROM.h>
#include <avr/interrupt.h>
#include <avr/io.h>
#include <util/delay.h>

#define BUT_START 2
#define IRF 1
#define VCC_PIN 3
#define ADC_PIN A2
#define ADC_VREF_TYPE 0x00
//
unsigned int b = 0;
boolean flag_but = false;
unsigned long fstart_filter = 0;

void adc()
{
  if (millis() - fstart_filter > 50)
  {
    fstart_filter = millis();
    digitalWrite(VCC_PIN, HIGH);
    b = analogRead(ADC_PIN);
    b = b / 4;
    if (b > 150) b = 150; // low speed да тут инверсия
    if (b < 30) b = 30; // hign speed
  }
}

void speed_low()
{
  OCR0A++;
  OCR0B = OCR0A;
  _delay_ms(20);
}
void speed_HIGH()
{
  OCR0A--;
  OCR0B = OCR0A;
  _delay_ms(20);
}
void setup() {
  pinMode(BUT_START, INPUT); digitalWrite(BUT_START, LOW);
  pinMode(ADC_PIN, INPUT);
  pinMode(VCC_PIN, OUTPUT); digitalWrite(VCC_PIN, INPUT_PULLUP);
  pinMode(IRF, OUTPUT); digitalWrite(IRF, LOW);
  pinMode(0, INPUT_PULLUP); digitalWrite(0, HIGH);
  TCCR0A = 0xB3; // режим ШИМ, неинверсный сигнал на выходе OC0A, инверсный - на выходе OC0B
  TCCR0B = 0x00; //счетчик выключен.Можно использовать это значение как выключалку таймера-счетчика
  TCNT0 = 0; // начальное значение счётчика
  OCR0A = 0; // регистр совпадения A
  OCR0B = 0; // регистр совпадения B
  delay(500);
}

void loop()
{
  if  (digitalRead(BUT_START) == HIGH  )
  {
    TCCR0B = 0x01;
    while (flag_but == false)
    {
      adc();
      speed_HIGH();
      if (OCR0A == b)
      {
        //i = 300;
        OCR0B = b;
        flag_but = true;
      }
    }
    adc();
    flag_but = true;
    OCR0A = b;
    OCR0B = OCR0A;
    _delay_ms(20);
  }

  if  (digitalRead(BUT_START) == LOW && flag_but == true) 
  {
    speed_low();
    if (OCR0B == 255) // стоп машина
    {
      flag_but = false;
      //i = 0;
      b = 0;
      TCCR0B = 0x00 ; //счетчик выключен.Можно использовать это значение как выключалку таймера-счетчика
    }
  }
}