ATtiny13A 101 применение

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

andycat пишет:

Собрал новый.

И самая странность с которой я встретился в следующем:

Прошиваю Attiny85 на 1МГц тем же самым скетчем годовалой давности, который исправно работает до сих пор и он не находит DS18B20 совсем :(

Перебрал массу вариантов, перечитал кучу всего, наткнулся на мысль что МК на частоте 1Мгц не успевает обрабатывать данные, но как то это все работало?

Из изменений за этот год - только новая версия Arduino IDE.

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

andycat пишет:

Из изменений за этот год - только новая версия Arduino IDE.

Лучшее враг хорошего???

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

andycat пишет:

При питании от CR2032 потребление в спящем режиме ~110 мкА.

при емкости CR2032 порядка 220 мА*ч  - батарейки хватает на пару-тройку месяцев?

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

b707 пишет:

andycat пишет:

При питании от CR2032 потребление в спящем режиме ~110 мкА.

при емкости CR2032 порядка 220 мА*ч  - батарейки хватает на пару-тройку месяцев?

сложный вопрос. На другом скетче (частота МК 1Мгц) при потреблении ~35 мкА две параллельные CR2032 совсем китайские (по 10 руб штучка) отработали почти 9 месяцев. Сейчас VARTA поставил...посмотрим. Если хотя бы полгода отработают - меня вполне устроит.

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

ua6em пишет:

andycat пишет:

Из изменений за этот год - только новая версия Arduino IDE.

Лучшее враг хорошего???

я то надеялся на лучшее :(

selevo
selevo аватар
Offline
Зарегистрирован: 21.12.2013

есть рабочие примеры эмулятора DS18b20 ? проверял кто ?

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

b707 пишет:

andycat пишет:

При питании от CR2032 потребление в спящем режиме ~110 мкА.

при емкости CR2032 порядка 220 мА*ч  - батарейки хватает на пару-тройку месяцев?

Да, были правы: б/у батарейки Varta через 1.5 месяца померли, напряжение упало до 0.8 вольт, что уже не хватало для работы.
Перепаяю на старую рабочую схему с рабочим напряжением 3.3 вольта или возьму более мощный источник питания.

ELITE
ELITE аватар
Offline
Зарегистрирован: 11.01.2018

andycat пишет:
b707 пишет:

andycat пишет:

При питании от CR2032 потребление в спящем режиме ~110 мкА.

при емкости CR2032 порядка 220 мА*ч  - батарейки хватает на пару-тройку месяцев?

Да, были правы: б/у батарейки Varta через 1.5 месяца померли, напряжение упало до 0.8 вольт, что уже не хватало для работы. Перепаяю на старую рабочую схему с рабочим напряжением 3.3 вольта или возьму более мощный источник питания.

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

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

ELITE пишет:

 

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

мысль, ссылка на описание/расчет витков и размеров есть? чтоб не искать....

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

P.P.S. И сильного источника сигнала нет...деревня, две радиостанции ловит, ТВ только с высокой антеной, мобильник только 2G и то в определенных местах.

ELITE
ELITE аватар
Offline
Зарегистрирован: 11.01.2018

andycat пишет:

ELITE пишет:

 

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

мысль, ссылка на описание/расчет витков и размеров есть? чтоб не искать....

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

P.P.S. И сильного источника сигнала нет...деревня, две радиостанции ловит, ТВ только с высокой антеной, мобильник только 2G и то в определенных местах.

ну тут надо просто пробовать - обычный колебательный контур мотаете и старый переменный конденсатор (как в старых приемника) - мультиметр и крутить-вертеть в разных частотных диапазонах.... наверняка ан СВ диапазоне будет чтото весьма прилично фонить....

а по размерам - вполне возможно уровня сигнала с ТВ антенну будет вполне достаточно для питания, а то и даже с избытком и хватит даже экран ЛСД питать (без подсветки)

alex286
Offline
Зарегистрирован: 16.07.2012

Обратите взгляд в  сторону химических источников тока... 

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

При отправке потребление до 15мА,пока поставил три батарейки ААА.
Зимой, как времени свободного больше будет, попробую все таки катушку большую сделать.

ELITE
ELITE аватар
Offline
Зарегистрирован: 11.01.2018

конденсаторы или еще лучше ионисторы - пока спит - заряжай, надо отправить - питайся

я делал авто БК и надо было немного автономного питания (2-3 секунды)

поставил ионистор 5В 1Ф - этого для полноценной работы ардуины мини с сд картой хватает секунд на 30....

при этом размер ионистора как две таблетки 2032

KPG
Offline
Зарегистрирован: 09.06.2019
Morroc
Offline
Зарегистрирован: 24.10.2016

ELITE пишет:

наверняка ан СВ диапазоне будет чтото весьма прилично фонить....

Если только китайцы в определенное время суток. У нас практически все ДВ/СВ позакрывали, в некоторых регионах 2-3 станции только не сильно большой мощностью и то некоторые не круглосуточно. http://www.novosibdx.info/schedules.html

mir0tv0rec
Offline
Зарегистрирован: 19.09.2018

Всем доброго времени! Прошу помощи или направления для решения проблемы. Ситуция такая - решил заменить драйвер светодиодного фонаря на неизвестном китайском МК, который ушел в мир иной на тини13а. Набросал програмку. На порту 0 и 1 сделал шим, 3 порт хочу сделать, как выход у управлять им полевиком, чтобы включать делитель напряжения в цепь АКБ и не жрать через него аккумулятор, когда фонарь не работает. На 4ом кнопка с внутренней подтяжкой. Порты нагружены светодиодами через резисторы 4.7к. Но столкнулся с проблеммой - если включаю 3й порт, то все начинает глючить... Диоды на 0 и 3 порте или на 1 и 3м (если переключить кнопкой) начинают мигать с частотой герц 15-20 в пол накала. В протеусе тоже ситуация странная на выводах шим амплитуда всего чуть больше вольта, как закоментирую стороки 142-152 все начинает работь нормально.

#define F_CPU 9600000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
//#include <avr/sleep.h>		// здесь описаны режимы сна

#define true 1	// логическое состояние правда
#define false 0	// логическое состояние ложь

volatile uint16_t voltVal = 0;			// переменная для накопления значений АЦП
volatile uint8_t sss1 = 0;				// счетчик значений АЦП
volatile uint8_t sleep_MODE = true;		// режим сна

uint8_t PWM_MODE[4] = {255, 0, 86, 172};		// режимы PWM (100%, 67%, 33%)
uint8_t LedMode = false;		// переключатель светодиодов		


uint8_t butCount = 0;					// счетчик времени нажатия
uint8_t flgPress = false;				// признак кнопка в нажатом состоянии
uint8_t flgClick = false;				// признак отпускания кнопки
uint8_t switchLED = false;				// признак переключения диодов
uint8_t flgLngPress = false;			// признак удержания кнопки
uint8_t i = 0;							// счетчик	

void Set_PWM (void) {
	
	switch (LedMode) {
		case 0:
		DDRB &= (0 << PINB1);
		DDRB |= (1 << PINB0);
		OCR0A = PWM_MODE[i];
		OCR0B = PWM_MODE[0];
		break;
		
		case 1:
		DDRB &= (0 << PINB0);
		DDRB |= (1 << PINB1);
		OCR0A = PWM_MODE[0];
		OCR0B = PWM_MODE[i];
		break;
	}// end switch
	
}// end Set_PWM()

/*
ISR(PCINT0_vect){
	
	GIMSK=0x00;             // Pin Change Interrupt выкл.
	PCMSK=0x00;             // PCINT4 откл.
	if (sleep_MODE) sleep_MODE = false;
	DDRB |= (1 << PINB3);		// порт 3 на выход (для подключения делителя)
	PORTB |= (1 << PINB3);	// порт 3 высокий уровень
				
}// ISR(PCINT0_vect)
*/
/*
ISR (ADC_vect){	
	
	voltVal += ADCW;
	sss1++;	
	
	if (sss1 > 10) {
		voltVal = voltVal / sss1;
		sss1 = 0;
	}// end if
	
	if (voltVal < 690){
		sleep_MODE = true;
	}// end if
	
}// end ISR (ADC_vect)
*/

int main(void){
	/*
	ADMUX |= (1 << REFS0) | (0 << ADLAR) | (1 << MUX0);	// внутреннее опорное напряжение,
														// левое ориентирование данных, выбран вход ADC1
	ADCSRA = 0xEF;	// АЦП включен, запуск преобразования, режим автоизмерения,
					// прерывание по окончанию преобразования, частота CLK/128
	ADCSRB = 0x00;	// режим автоизмерения: постоянно запущено
	DIDR0 |= (1 << PINB2); // запрещаем цифровой вход на ноге аналогового входа
	*/
	
	PORTB |= (1 << PINB4);	// подтяжка кнопки порт 4, высокий на порт 3 (для включения делителя в цепь)	
	DDRB |= (1 << PINB3);		// порт 3 на выход (для подключения делителя)
		
	// Режим Fast PWM, частота сигнала=F_CPU / делитель*256
	TCCR0A |= (1<<WGM00) | (1<<WGM01);	// Режим Fast PWM, таймер считает до 255 и сбрасывается в 0
	TCCR0A |= (1<<COM0A1) | (1<<COM0A0); // 0 при равенстве регистров TCNT0 и OCROA. 1 при переполнении (инвертированный ШИМ-сигнал)
	TCCR0A |= (1<<COM0B1) | (1<<COM0B0); // 1 при равенстве регистров TCNT0 и OCROB. 0 при переполнении (неинвертированный ШИМ-сигнал)
	TCCR0B |= (1<<CS01);				// делитель 8
	OCR0A = 255; // регистр сравнения (инвертированный сигнал ШИМ 255)
	OCR0B = 255; // регистр сравнения (инвертированный сигнал ШИМ 0)
	
	//_delay_ms(50);
	
	//asm("sei");		//разрешаем глобально прерывания
	
	//set_sleep_mode(SLEEP_MODE_PWR_DOWN); // если спать - то на полную

	while(1) {
		
		if ((PINB & (1 << PINB4)) == 0 && !flgLngPress) {
			_delay_ms(10);		// задержка (защита от дребезга)
			if ((PINB & (1 << PINB4)) == 0) {
				flgPress = true;		// кнопка нажата (устанавливаем флаг в 1)
				butCount++;				// начало отсчета нажатия кнопки
				if (butCount > 100){
					flgLngPress = true;
					flgPress = false;	// сбрасываем флаг нажатия
					butCount = 0;		// обнуляем счетчик времени нажатия
				}// end if
			}// end if
		}// end if
		
		if ((PINB & (1 << PINB4)) && flgLngPress){	// если отпустили после длительного нажатия
			switchLED = false;
			flgLngPress = false;
			flgPress = false;	// сбрасываем флаг нажатия
			flgClick = false;
		}// end if
		
		if (flgPress && (PINB & (1 << PINB4))){	// отпустили кнопку
			flgClick = true;	// устанавливаем флаг клика
			flgPress = false;	// сбрасываем флаг нажатия
			butCount = 0;		// обнуляем счетчик времени нажатия
		}// end if
		
		if (flgLngPress && !switchLED){	// было удержание кнопки
			LedMode++;		// переключаем на другой светодиод
			if (LedMode > 1) LedMode = 0;
			i = 1;
			Set_PWM();	// устанавливаем режим светодиода
			switchLED = true;
		}// end if
		
		if (flgClick){			// был клик
			flgClick = false;	// сбрасываем флаг клика
			i++;				// инкрементируем режим PWM
			if (i > 3) i = 0;	// обнуляем счетчик
			Set_PWM();			// устанавливаем режим светодиода
			if (i == 0){
				sleep_MODE = true;
				// отладка
				DDRB |= (1 << PINB3);	// порт 3 на выход
				PORTB |= (1 << PINB3);	// высокий уровень	
			}// end if
			else{
				// отладка
				sleep_MODE = false;
				PORTB &= (0 << PINB3);	// низкий уровень
				DDRB &= (0 << PINB3);	// порт 3 на вход
			}// end else
		}// end if
		
		/*if (sleep_MODE){
			
			GIMSK=0x20;             // Pin Change Interrupt Enable
			PCMSK=0x10;             // PCINT4 set для возращения в нормальный режим из сна
			DDRB &= (0 << PINB3) | (0 << PINB1) | (0 << PINB0);	// выключаем светодиоды, делитель
			PORTB = 0x00;			// отключаем подтяжку и высокий уровень на всех портах
			sleep_enable(); // разрешаем сон
			sleep_cpu(); // спать!
			
		}// end if*/
			
	}// end while(1)
}// end main

 

inspiritus
Offline
Зарегистрирован: 17.12.2012

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

тинька13 стоит почти ничего. И потому вачдог на ней, что для наны, что для меги (у которых в общем то проблема собаки почтирешена), что для ESP, где оная не решена вообще, достаточно удобен. Можно конечно на 555, но стоит она чуть ли не дороже, плюс обвязка.

зо... рецепт счастия:

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

Простейший код на защищаемом мк , который внутри самого значимого события дергает ногу в GND. 

Ногу тиньки заводим на reset мк.

Ногу мк заводим на reset тиньки.

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

Самое главное- задержку в тиньке выставить существенно больше, чем критичесвка задержка значимого события в мк.

спасибо за внимание

тэги- #watchdog #attiny #esp 266 #провереноработает

Morroc
Offline
Зарегистрирован: 24.10.2016

Встроенная собака имеет какой то принципиальный изъян ?

xorkrus
Offline
Зарегистрирован: 22.09.2013

Товарищи, а может кто подсказать, как вот этот код переделать под тиньку13?

void setup() {
  pinMode(3, OUTPUT); //MAG: Timer 2B cycle output
  pinMode(10, OUTPUT); //LED: Timer 1B cycle output 
  TCCR2A = 0;
  TCCR2B = 0;
  TCCR2A = _BV(COM2A0) | _BV(COM2B1) | _BV(WGM21) | _BV(WGM20);
  TCCR2B = _BV(WGM22) | _BV(CS22)| _BV(CS21)| _BV(CS20);
  OCR2A = 195;//80Hz
  OCR2B = 29;//15% duty cycle for magnet
  TCCR1A = 0;
  TCCR1B = 0;
  TCCR1A = _BV(COM1A0) | _BV(COM1B1) | _BV(WGM11) | _BV(WGM10); 
  TCCR1B =  _BV(WGM13) | _BV(WGM12)  |  _BV(CS11);
  OCR1A = 24845;//80.5Hz
  OCR1B = 4969;//20% duty cycle for LED
  sei();
}

void loop() {
} //main loop

Мне не совсем понятно, зачем зачем задаются OCR1A и OCR2A, если нужная частота задается в OCR2B и OCR1B.

upd. а может в OCRxA задается частота, а в OCRxB коэфициент заполнения? Тогда непонятно все равно как сделать это в тиньке13

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

xorkrus, "upd." -да, именно так. На tiny13 в лоб не перенести. В данном скетче работают 2 независимых таймера. В tiny13 всего один таймер. Остаётся вариант всё сделать программно.

zilibob4ik
Offline
Зарегистрирован: 02.06.2014

Вопрос к народу, какой мнимальный ток потребления добивались от тини13 в режиме сна?

Joiner
Offline
Зарегистрирован: 04.09.2014

zilibob4ik пишет:

Вопрос к народу, какой мнимальный ток потребления добивались от тини13 в режиме сна?

Какой ток в режиме сна не знаю, но "Шар судьбы", который я сделал на тини13 не имеет выключателя и спит, пока к нему не обратятся, вот он работает уже больше года на батарейке 2032.

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

zilibob4ik пишет:

Вопрос к народу, какой мнимальный ток потребления добивались от тини13 в режиме сна?

Даташит посмотрите - там написано, он не врет.

 

inspiritus
Offline
Зарегистрирован: 17.12.2012

Morroc пишет:

Встроенная собака имеет какой то принципиальный изъян ?

 

Встроенная собака во ЧТО?

я дергаю esp8266, в которой собака не работает от слова ВААЩЕ.

Сепар
Сепар аватар
Offline
Зарегистрирован: 27.12.2018

Доброго времени суток. Имееца несколько куллеров, где Attiny 13 считывает температуру и управляет скоростью вращения вентилятора, подскажите пожалуйста, как с них снять данные о температуре и оборотах на ардуину, чтоб вывести на дисплей?

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

Без точной схемы с применяемыми компонентами ответить на этот вопрос не представляется возможным.

Сепар
Сепар аватар
Offline
Зарегистрирован: 27.12.2018

Схема обычная термодатчик, аттини, pwm вентилятор с датчиком оборотов и регулировкой шим, полевик, мелочовка в виде нескольких сопротивлений и пара кондеров.

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

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

Сепар
Сепар аватар
Offline
Зарегистрирован: 27.12.2018

Зачем мне их менять на ардуины? Их 6 штук на каждую ардуину ставить? Суть вопроса сводица к организации шины i2c и присвоении каждой аттини идентификатора.

anarch
Offline
Зарегистрирован: 10.09.2017

AVR 300: Software TWI Master Interface поищите может чем поможет

Yurchik26
Offline
Зарегистрирован: 16.03.2013

Добрый день. Помогите советом. Не могу найти информацию по моему вопросу. Почему код под номером 1 работает, а под номером 2 не работает. Сам цикл выполняется, а значение timer к millis не приравнивается. Проверял только на attiny 13

unsigned long timer = 0;

void setup() {
DDRB |= (1<<1);//  pinMode(ledPin, OUTPUT);
PORTB &= ~(1<<1);//  digitalWrite(ledPin, LOW);
}

void loop() {
            timer = millis();
            digitalWrite(1, HIGH);
            if (timer>=2000) digitalWrite(1, HIGH);
            else {
            digitalWrite(1, LOW);
}
}

--------------------------------------------------------------------------------------

unsigned long timer = 0;

int main( void )
{ 
  DDRB |= (1<<1);//  pinMode(ledPin, OUTPUT);
  PORTB &= ~(1<<1);//  digitalWrite(ledPin, LOW);
  while (1)
           { 
            timer = millis();
            digitalWrite(1, HIGH);
            if (timer>=2000) digitalWrite(1, HIGH);
            else {
            digitalWrite(1, LOW);
            }
          } 
  return 0;
}

 

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Внутренний код функции setup и loop не выполняется - в итоге таймер не инициализируется, прерывания не подключаются и millis не тикает ...

init(); перед DDRB думаю будет достаточно.

Не ясно почему в начале идет прямое обращение к портам, а потом через digitalWrite ... ???

Yurchik26
Offline
Зарегистрирован: 16.03.2013

Понял. В общем тогда с таймерами как на си надо работать. Спасибо. Прямое обращение, а потом через digital это чтоб укоротить, я вырезал все лишнее, и для наглядности по обычному все вставил. Добавил по вашему совету, все заработало.

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

attiny уж точно не для библиотек ...

Green
Offline
Зарегистрирован: 01.10.2015

Командиры они такие, категоричные.)

mir0tv0rec
Offline
Зарегистрирован: 19.09.2018

Товарищи, прошу помочь разобраться. Не пойму "где собака зарыта". Прошлый свой вопрос решил. Но возник еще один. В общем так: собрал фонарь,  все работает, но периодически тинька не выходит из сна (сброс или передергивание питания помогает). Никак не могу найти, что не так.

#define F_CPU 9600000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

#define false 0 // ложь
#define true 1  // истина

volatile uint8_t sss1 = 0;            // счетчик значений АЦП
volatile uint8_t lowBat = false;      // батарея разряжена
volatile uint8_t flgClick = false;    // флаг клика
volatile uint8_t beUnPress = false;   // флаг отпускания
volatile uint8_t switchLED = false;   // флаг переключения диодов
volatile uint8_t keyFalsePress = false;   // флаг нажатия кнопки

volatile uint16_t tCounter = 0;       // счетчик мкС
volatile uint16_t msCounter = 0;      // счетчик кратно - 10мС
volatile uint16_t msCounterNow = 0;   // счетчик кратно - 10мС текущий
volatile uint16_t voltVal = 0;        // переменная для накопления значений АЦП


uint8_t PWM_MODE_LED[4] = {255, 0, 128, 230};  // режимы PWM (0% - 255, 100% - 0, 50% - 128, 25% - 192)
uint8_t PWM_MODE_COB[4] = {255, 0, 128, 192};  // режимы PWM (0% - 255, 100% - 0, 50% - 128, 25% - 192)
uint8_t butCount = 0;           // счетчик времени нажатия
uint8_t i = 0;                  // счетчик
uint8_t j = 0;                  // счетчик


uint8_t flgPress = false;   // признак кнопка в нажатом состоянии
uint8_t LedMode = false;    // переключатель светодиодов
uint8_t flgLngPress = false;  // признак удержания кнопки



//****************************************************************
// мигаем основным светодиодом при низком заряде
//
void BlinkLed(){
  TCCR0A &= ~((1<<COM0B1) | (1<<COM0B0)); // отключаем ШИМ COB
  TCCR0A |= (1<<COM0A1) | (1<<COM0A0);  // включаем ШИМ PB0
  for (uint8_t i = 0; i < 5  ; i++){
    for (uint8_t j = 127; j < 255  ; j++){
      _delay_ms(1);     // отладка
      OCR0A = j;
    }// end for  
    for (uint8_t j = 255; j > 127  ; j--){
      _delay_ms(1);     // отладка
      OCR0A = j;
    }// end for
  }// end for  
}// end BlinkLed()

// переходим в режим сна
//
void RunSleep(){
  LedMode = false;
  flgLngPress = false;    // сбрасываем флаги
  flgPress = false;       // сбрасываем флаги
  ADCSRA &= ~(1<<ADEN);   // выключаем АЦП
  GIMSK |= (1 << PCIE);   // включаем прерывания по кнопке
  PCMSK |= (1 << PCINT2); // PCINT2 для возращения в нормальный режим из сна
  TCCR0A &= ~((1<<COM0A1) | (1<<COM0A0)); // отключаем ШИМ
  TCCR0A &= ~((1<<COM0B1) | (1<<COM0B0)); // отключаем ШИМ
  PORTB &= ~((1 << PB4) | (1 << PB1) | (1 << PB0));  // низкий уровень на портах
  MCUCR |= (1 << SE); // режим сна включен
  asm("sleep");   // уходим в сон
}// end RunSleep()

// устанавливаем режим работы светодиодов
//
void Set_PWM() {
  switch (LedMode) {
    case 0:
      OCR0A = PWM_MODE_LED[i];
      TCCR0A &= ~((1<<COM0B1) | (1<<COM0B0)); // отключаем ШИМ PB1
      TCCR0A |= (1<<COM0A1) | (1<<COM0A0);    // включаем ШИМ PB0
    break;
    
    case 1:
      OCR0B = PWM_MODE_COB[i];
      TCCR0A &= ~((1<<COM0A1) | (1<<COM0A0)); // отключаем ШИМ PB0
      TCCR0A |= (1<<COM0B1) | (1<<COM0B0);    // включаем ШИМ PB1
    break;
  }// end switch
}// end Set_PWM()

// выходим из сна по изменению состояния кнопки (обработчик прерывания)
//
ISR(PCINT0_vect){
  MCUCR &= ~(1 << SE);    // режим сна выключен
  GIMSK &= ~(1 << PCIE);  // выключаем прерывания по пинам
  PCMSK = 0x00;           // выключаем прерывания по выводу кнопки
  PORTB |= (1 << PB4);    // открываем полевик, подтягиваем делитель в минусу
  ADCSRA |= (1 << ADEN)|(1 << ADSC);  // включаем АЦП
  lowBat = false;       // снимаем флаг низкого уровня АКБ
  switchLED = false;    // снимаем флаг переключение светодиодов
  keyFalsePress = true;       // поднимаем флаг случайного нажатия / помехи / дребезга
  msCounterNow = msCounter;   // запускаем счетчик после нажатия
  if (!(PINB & (1 << PB2))) {  // если включились по отпусканию кнопки 
    beUnPress = true; // поднимаем флаг включения по отпусканию кнопки 
  }// end if
}// ISR(INT0_vect)

// обработчик прерывания АЦП
//
ISR (ADC_vect){
  
  uint16_t voltValTmp = 1024;
  
  voltVal += ADCW;  // добавляем текущее значение АЦП
  sss1++; // инкрементируем счетчик
  
  if (sss1 > 9) { // если количество отсчетов АЦП больше 10
    voltValTmp = voltVal / (sss1);  // находим среднее арифметичсекое АЦП
    voltVal = 0;
    sss1 = 0;
  }// end if

  // если напряжение меньше 3В - поднимаем флаг
  if (voltValTmp < 665) lowBat = true;  // ~3V  
  else lowBat = false;
}// end ISR (ADC_vect)


// обработчик прерывания по переполнению 0 таймера
//
ISR (TIM0_OVF_vect) {
  tCounter++;
  if (tCounter > 375) { // ~10ms
    tCounter = 0; // обнуляем счетчик
    msCounter++;  // счетчик 10мс
  }// end if
}// ISR (TIM0_OVF_vect)


int main(void){
  
  DDRB |= (1 << PB4) | (1 << PB1) | (1 << PB0);   // порты 0, 1, 4 на выход
  PORTB |= (1 << PB4);    // открываем полевик, подтягиваем делитель к минусу
  
  // Отключаем компаратор
  ACSR = 0x00;        // обнуляем регистр
  ACSR |= (1 << ACD); // выключаем компаратор
    
  // Инициализируем АЦП
  ADMUX |= (1 << REFS0) | (1 << MUX1) | (1 << MUX0);  // внутреннее опорное напряжение, выбран вход ADC3 (PB3)
  ADCSRA |= (1 << ADEN) | (1 << ADSC) | (1 << ADATE)  // АЦП включен, запуск преобразования, режим автоизмерения,
  | (1 << ADIE)                                       // прерывание по окончанию преобразования,
  | (1 << ADPS2) | (1 << ADPS1)| (1 << ADPS0);        // частота CLK/128
  ADCSRB = 0x00;  // режим автоизмерения: постоянно запущено
  DIDR0 |= (1 << ADC3D); // запрещаем цифровой вход на ноге аналогового входа
  
  // Режим Fast PWM, частота сигнала=F_CPU / делитель*256
  OCR0A = 255; // регистр сравнения (инвертированный сигнал ШИМ 0)
  OCR0B = 255; // регистр сравнения (инвертированный сигнал ШИМ 0)
  TCCR0A |= (1<<WGM00) | (1<<WGM01) |   // Режим Fast PWM, таймер считает до 255 и сбрасывается в 0
            (1<<COM0A1) | (1<<COM0A0) | // 0 при равенстве регистров TCNT0 и OCROA. 1 при переполнении (инвертированный ШИМ-сигнал)
            (1<<COM0B1) | (1<<COM0B0);  // 1 при равенстве регистров TCNT0 и OCROB. 0 при переполнении (неинвертированный ШИМ-сигнал)
  TCCR0B |= (1<<CS00);  // делитель 1 (ШИМ ~37кГц)
  TIMSK0 |= (1 << TOIE0); // вкл. прерывание по переполнению таймера
  
  
  // настройка режима сна
  
  MCUCR |= (1 << SM1);  // power-down mode
  
  
  sei();    // разрешаем глобально прерывания
  
  while(1) {

    // если нажата кнопка
    if ((PINB & (1 << PB2)) && !flgLngPress) {
      _delay_ms(15);      // время на дребезг
      if (PINB & (1 << PB2)) {  // если кнопка все еще нажата
        keyFalsePress = false;  // снимаем флаг случайного нажатия
        butCount++;             // начало отсчета нажатия кнопки
        if (butCount >= 55){    // ~1 сек (15мс *(55 + обработка команд))
          flgLngPress = true;
          butCount = 0;       // обнуляем счетчик времени нажатия
        }// end if
        else{
          flgPress = true; // клик
        }// end else
      }// end if  
    }// end if
    
    
    // если отпустили после длительного нажатия
    if (flgLngPress && !(PINB & (1 << PB2))){
      switchLED = false;
      flgLngPress = false;
      flgPress = false; // сбрасываем флаг нажатия
    }// end if
    
    // отпустили кнопку
    if (flgPress && !(PINB & (1 << PB2))){
      flgClick = true;  // устанавливаем флаг клика
      flgPress = false; // сбрасываем флаг нажатия
      butCount = 0;    // обнуляем счетчик времени нажатия
    }// end if


    // если длительное нажатие
    if (flgLngPress && !switchLED){
      LedMode = !LedMode;   // переключаем на другой светодиод
      i = 1;
      Set_PWM();  // устанавливаем режим светодиода
      switchLED = true;   // поднимаем флаг, что переключили светодиоды (защита от многократно срабатывания)
    }// end if

    // был клик
    if (flgClick){
      flgClick = false; // сбрасываем флаг клика
      i++;  // инкрементируем режим PWM
      if (i > 3) i = 0; // обнуляем счетчик (у нас всего 4 режима: 0-3)
      Set_PWM();        // устанавливаем режим светодиода
      if (!i) RunSleep();
    }// end if

    // защита от помехи / случайного нажатия
    // если нажатие было случайное или помеха, фонарь не включен и прошло больше 2с
    if (keyFalsePress && !i && ((msCounter - msCounterNow) > 200)){
      RunSleep();  
    }// end if
    
    // если аккумулятор разрядился
    if (lowBat){
      if (!beUnPress) BlinkLed();
      else beUnPress = false;
      i = 0;
      RunSleep();
    }// end if
        
       
  }// end while(1)
}// end main

По железу: питание от 1го 18650, тинька запитана через диод шоттки, после диода керамика 22u+0.1u.

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

а  диод шоттки зачем?

mir0tv0rec
Offline
Зарегистрирован: 19.09.2018

Для разделения питания светодиодов и тинки. При запуске происходит кратковременная просадка напряжения и, если не ставить диод с конденсатором, тинька вырубается. А так на момент запуска тинька питается от своего конденсатора.

Green
Offline
Зарегистрирован: 01.10.2015

Неправильная схемотехника. Никаких просадок, тем более таких диких, быть не должно.

mir0tv0rec
Offline
Зарегистрирован: 19.09.2018

Товарищи давайте по теме (именно программа), дело точно не в схемотехнике. Но в любом случае отвечу. АКБ имеет конечное  сопротивление, причем оно, при использовании не самых высокотоковых АКБ, достаточно большое. При включении полевик открывается полностью и ток светодиода ограничен только выходным сопротивлением АКБ и полевика (ну и падением на самом светодиоде). А они для ограничения тока светодиода на приемлемом уровне слишком малы. Зато этого сопротивления достаточно для падения на нем напряжения ниже уровня, достаточного для нормальной работы тиньки.

Green
Offline
Зарегистрирован: 01.10.2015

Дело ваше. Неправильность в том, что полевик не должен открываться при включении (подаче питания).

mir0tv0rec
Offline
Зарегистрирован: 19.09.2018

Он(они) и не включается сразу, только после обработки нажатия кнопки. Тах же все в коде видно (по крайней мере я так думаю).

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

mir0tv0rec пишет:

 дело точно не в схемотехнике.

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

P.S. МК или работает или нет, уж наверное штук 6 железок на attiny85 собрал, месяцами работает (пока батарейка не сядет) без сбоев.

 

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

18650 вроде 10 ампер может отдать

mir0tv0rec
Offline
Зарегистрирован: 19.09.2018

Проверил на макетке, нагрузка 3 индикаторных светодиода через резисторы 470Ом (LED, COB и полевик АЦП), проблема повторилась. Правда только 1 раз. Питал от программатора 5В. В фонаре проявляется хаотично, какой-то закономерности нет.

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

не ...Вы меня не поняли, нагрузить МК минимальной нагрузкой, типа крошечного светодиода - чтоб полностью исключить проблему аппаратной части. Т е только МК светодиод и кнопка - а потом уже схемотехнику мучать.

mir0tv0rec
Offline
Зарегистрирован: 19.09.2018

Я так и сделал, 3 синих светодиода 3 мм через резисторы 470Ом, вместо 3х ваттных. 3й в качестве индикаторы работы АЦП.

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

В сообщении #1695 COB а это ни как не слабенькая нагрузка, и полевик написан...что то не сходится....

PS. впрочем не важно, я лично не очень спец и проблем в коде глобальных не вижу. По практике - плавающих проблем на МК пока не видел. Спецы потянутся - что то может и увидят - проблемы в коде.
Но думаю дело в питании. Вы бы схему что ли выложили полную.

Update : недавно тоже народ на форуме мучал и сам голову сломал :( питал схему от программатора - оказалось что тока совсем не хватало.

mir0tv0rec
Offline
Зарегистрирован: 19.09.2018

Я и написал, что реальная нагрузка заменена индикаторными светодиодами. Там максимальное потребление 30мА+тинька 5мА (по максимуму)

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

Наткнулся на схему регулятора оборотов коллекторного двигателя