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

Дим
Offline
Зарегистрирован: 05.05.2017

Не встретилась

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

Если на 85, то как угодно. Я делал и по и2с на другую плату, и софт сериал.. да как хочешь изгаляйся, там памяти хватит.

Если на 13, то отладь сперва на 85-ой. ;) Я серьезно, у тебя 1 К программы. Я ставил как-то себе софтварный и2с собственного разлива и ловил на Ардуинку, но для кода уже очень мало остается. Тут либо на симуляторе - терпеть их не могу! - либо на 85-ой отлаживать.

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

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

sav13
sav13 аватар
Offline
Зарегистрирован: 17.06.2013

wdrakula пишет:

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

Есть несколько готовых схем, где тинька 13 вполне себя оправдывает. Лично у меня работает

- Сенсорный выключатель с диммированием по оному каналу

- Сторожевой таймер

- Таймер сна или кнопка питания для более прожорливых МК

Когда есть готовые схемки и разведенные платки и госрть корпусов купленных по 0.3$ там вполне ксть где развернуться

Но вот сидеть и впихивать код в МК с мизерной памятью, когда Mega8 стоит всего в 1.5 раза дороже извращение еще то

Дим
Offline
Зарегистрирован: 05.05.2017

sav13 пишет:
- Сенсорный выключатель с диммированием по оному каналу

Можно исходники и схему

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

sav13 пишет:

wdrakula пишет:

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

Есть несколько готовых схем, где тинька 13 вполне себя оправдывает. Лично у меня работает

- Сенсорный выключатель с диммированием по оному каналу

- Сторожевой таймер

- Таймер сна или кнопка питания для более прожорливых МК

Когда есть готовые схемки и разведенные платки и госрть корпусов купленных по 0.3$ там вполне ксть где развернуться

Но вот сидеть и впихивать код в МК с мизерной памятью, когда Mega8 стоит всего в 1.5 раза дороже извращение еще то

Да я не о замене на Мегу, я про ТИНЬКУ, Точно такую же по ногам - в 8-ми ногом корпусе и совместимую на плате - про Тиньку85. Если есть идея и плата, то ну ее нахер это 13-ую. Только если в столе валяются и девать некуда.

 

sav13
sav13 аватар
Offline
Зарегистрирован: 17.06.2013

Дим пишет:

sav13 пишет:
- Сенсорный выключатель с диммированием по оному каналу

Можно исходники и схему

 

#define F_CPU 9600000
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/atomic.h>
#include <avr/eeprom.h>
#include <util/delay.h>
#include <avr/sleep.h>

struct bits {   
	uint8_t b0:1;
	uint8_t b1:1;
	uint8_t b2:1;
	uint8_t b3:1;
	uint8_t b4:1;
	uint8_t b5:1;
	uint8_t b6:1;
	uint8_t b7:1;
} __attribute__((__packed__));

#define SBIT(port,pin) ((*(volatile struct bits*)&port).b##pin)

#define SENSKEY_A0      SBIT( PORTB, 3 )        // connect to senspad
#define SENSKEY_A0_DDR  SBIT( DDRB,  3 )

#define SENSKEY_B0      SBIT( PORTB, 4 )        // connect to cap to A0
#define SENSKEY_B0_DDR  SBIT( DDRB,  4 )
#define SENSKEY_B0_PIN  SBIT( PINB,  4 )

#define TP_THRESHOLD	8
#define TP_UP			0
#define TP_DOWN			1
#define TP_HOLD			2

// Значения настроек при первом включении (хранятся в EEPROM)
EEMEM unsigned char param_eeprom [] = 
{
  120,  // Уровень яркости
};

uint8_t led_on, up, adj, hold;

volatile uint8_t smplctr, level;

	int16_t tp_filter, tp_current;
	int8_t tp_state;

#define MAX_CYCLE       2000

uint16_t senskey( void )
{
	uint16_t i = MAX_CYCLE + 1;

	SENSKEY_A0 = 0;
	SENSKEY_A0_DDR = 1;
	SENSKEY_B0 = 0;
	SENSKEY_B0_DDR = 1;           // discharge cap

	ATOMIC_BLOCK(ATOMIC_FORCEON){
		do{
			SENSKEY_A0_DDR = 0;       // A0 = tristate
			SENSKEY_B0 = 1;           // B0 = weak high
			SENSKEY_B0_DDR = 1;       // B0 = strong high
			SENSKEY_B0_DDR = 0;       // B0 = weak high
			SENSKEY_B0 = 0;           // B0 = tristate
			SENSKEY_A0_DDR = 1;       // A0 = strong low
			if( --i == 0 )
			break;                          // timeout
		}while( SENSKEY_B0_PIN == 0 );      // until charged
	}
	SENSKEY_B0_DDR = 1;           // discharge cap
	return MAX_CYCLE - i;         // big value = key touched or timeout
}

SIGNAL(TIM0_OVF_vect) 
{
// Counter for main loop
smplctr++;
// Check if the lamp should be on
if(led_on && tp_state == TP_UP) 
{
TCCR0A |= (1 << COM0A1); // Включаем выход таймера
  for(OCR0A = 0; up && (OCR0A != level); OCR0A++) // Светодиод разгорается
  {
  _delay_ms(5);
  }
up = 0;
OCR0A = level;
}
if(led_on == 0 && tp_state == TP_UP) 
{
  for(OCR0A = level; up == 0 && (OCR0A != 0); OCR0A--) // Светодиод тухнет
  {
  _delay_ms(5);
  }
up = 1;
OCR0A = 0; // Минимальная яркость
TCCR0A &= ~(1 << COM0A1)|(1 << COM0A0); // Отключаем выход таймера
}
}

#define FILORD		8
#define FILSHIFT	3

// Moving average lowpass filter
int16_t lpfilter(int16_t sample) {
	static int16_t z[FILORD];
	static int8_t ctr;
	int8_t i;
	int16_t fil;
	
	z[ctr&(FILORD-1)] = sample;
	ctr++; fil=0;
	for(i=0 ; i<FILORD ; i++) {
		fil += z[i];
	}
	return fil>>FILSHIFT;
}

// Settle the lowpass filter to some sampled value
void lpfilter_settle(int16_t sample) {
	int8_t i;
	for(i=0 ; i<FILORD ; i++) lpfilter(sample);
}


int	main(void)
{
DDRB |= (1 << PB0); // Светодиод
PORTB &= ~(1 << PB0);

ACSR |= (1 << ACD);

TCCR0A |= (1 << WGM00)|(1 << WGM01); 
TCCR0B |= (1 << CS02);	// 122 Hz PWM

TIMSK0 |= (1 << TOIE0);
	
tp_state = TP_UP;
	
tp_filter = tp_current = senskey();
lpfilter_settle(tp_current);
set_sleep_mode(SLEEP_MODE_IDLE);
sei();
// Установки при первом включении
adj = 1;
level = eeprom_read_byte(param_eeprom);
up = 1;
// Main loop
while(1) {		       
		// Go to idle mode until next timer event
		sleep_mode();
		// Read touchpad and filter signals at 5Hz
		if(smplctr >= 12) {
			
			// Read touchpad value
			tp_current=0;
			for(char i=0;i<8;i++) tp_current += senskey();
			tp_current >>= 3;

			if(tp_current < (tp_filter - TP_THRESHOLD) && tp_state == TP_UP) {
				
				// New touchpad state
				tp_state = TP_DOWN;
				
                // Toggle the lamp on/off
				led_on ^= 1;
								
				// Settle the lowpass filter to the current touchpad value
				// so that a touchpad change will be sensed relative to this value
				lpfilter_settle(tp_current);			
			}
			else if(tp_current > (tp_filter + TP_THRESHOLD) && tp_state != TP_UP) 
			{
				// "Button up event"
				
				// New touchpad state
				tp_state = TP_UP;
				  if(hold > 20) // Если сенсор удерживался 
                  {
				  eeprom_write_byte(param_eeprom, level); // Записываем уровень в EEPROM
				  hold = 0;
				  led_on = 1; // Оставляем включенным
				  up = 0;
				  }
				// Settle the lowpass filter to the current touchpad value
				// so that a touchpad change will be sensed relative to this value
				lpfilter_settle(tp_current);			
			}
			else if(tp_state != TP_UP) 
            {
				// "Button hold event"
				
				// New touchpad state
				tp_state = TP_HOLD;
				if(hold ++> 21) hold = 21;
				
				if(hold > 20 && led_on == 0)
				{
				OCR0A = level;
				  if(level != 255 && adj == 1)
				  {
				   level = level + 5;
				     if(level == 255)
				     {
				     OCR0A = 50;
					 _delay_ms(100);
				     OCR0A = 255;
					 _delay_ms(100);
				     OCR0A = 50;
					 _delay_ms(100);
				     OCR0A = 255;
					 _delay_ms(100);
					 adj = 0;
				     }
				   }
				if(level != 0 && adj == 0)
				{
				   level = level - 5;
				     if(level == 5)
				     {
				     adj = 1;
				     level = 5;
				     }
				 }
			   }
			}
			
			// Filter touchpad value
			tp_filter = lpfilter(tp_current);
			
			// Start counting the timer from 0
			smplctr = 0;
		}	
	};
	return 0;
}

 

Дим
Offline
Зарегистрирован: 05.05.2017

Такой модуль подойдёт?

Дим
Offline
Зарегистрирован: 05.05.2017

И всё же

sav13
sav13 аватар
Offline
Зарегистрирован: 17.06.2013

Дим пишет:

Такой модуль подойдёт?

Для чего подойдет?
Там нет диммирования. Там нет запоминания состояния. Плавного включения.

Дим
Offline
Зарегистрирован: 05.05.2017

Для включения в схему

sav13
sav13 аватар
Offline
Зарегистрирован: 17.06.2013

Дим пишет:

Для включения в схему

Тема про тини 13. Я написал, как использую тини 13

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

gzp13
Offline
Зарегистрирован: 06.04.2015
int main(void)
{
while(1)
{
mode = 0;
while ( (PINB&(1<<2)) == (1<<2) ) {};
while ( (PINB&(1<<2)) == 0b00000000 ) {};
_delay_us(1200);
if ( (PINB&(1<<2)) == (1<<2) ) mode++ ;
_delay_us(200);
if ( (PINB&(1<<2)) == (1<<2) ) mode++ ;
_delay_us(200);
if ( (PINB&(1<<2)) == (1<<2) ) mode++ ;
 
if  (mode == 0 && analogRead(2)<150) 
{
off();
}
 
 else flag=0;
if ( mode == 1 ) doubleflash();
if ( mode == 2  ) siren();
if ( mode == 3  ) always();
 if (   analogRead(2)<150 && flag==0)
{
always();
flag1=1;

}
}
}
 Коллеги, подскажите где ошибка? Смысл такой, с RC приемника идет сигнал, когда уровень меньше 150 то выполняется условие OFF()(подсветка выключена), и когда пропал сигнал управления с пульта, т.е сигнал будет тот же 150, должно выполняться условие always()., а это условие не выполняется.Понимаю что ошибка кроется в 15 и 24 строках т.к выполняется одновременно одно условие.Режим mode=0 тоже соответствует условию <150

 

gzp13
Offline
Зарегистрирован: 06.04.2015
#define F_CPU 1200000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
volatile int length = 0;
volatile int start_time = 0;
ISR(INT0_vect)
{
while (PINB & (1<<PB1)) //пока высокий уровень
 { 
  length = micros() - start_time;//считаем длительность импульса до спада
}
 if (length<1200) PORTB |= (1 << PB4);  
if (length>1500) PORTB &= ~ (1 << PB4);
}
int main()
{
  DDRB |= (1 << PB4);   // OUTPUT
  PORTB &= ~ (1 << PB4);
  DDRB &= ~(1 << PB1);  // INPUT
  PORTB |= (1 << PB1);
  rising();
   while (1)
  {
      }
  } 

void rising() {
MCUCR |= (1 << ISC01) | (1 << ISC00); //включаем прерывание по нарастающему фронту
 GIMSK |= (1 << INT0);        //разрешаем прерывание
 start_time = micros();
sei(); 
}
}

Ребят, подскажите,почему не работает код?

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

а зачем 32 строка?

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

я бы отключение прерывания засунул внутрь ISR(INT0_vect)

 

да и не пойму логику - ISR срабатывает один раз при спаде, зачем цикл while для расчета времени между стартом программы и спадом?

gzp13
Offline
Зарегистрирован: 06.04.2015

Прерывание не срабатывает. светодиод подключен.

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

gzp13 пишет:

Прерывание не срабатывает. светодиод подключен.

значит начинаем последовательно искать где косяк,

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

ЗЫ. а вы правильно прерывание включаете? даташит читали?

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

срабатывает при любом изменении сигнала, а внутри уже обрабатывать

gzp13
Offline
Зарегистрирован: 06.04.2015

Ну я сделал прерывание по нарастанию фронта, так как мне нужно замерить длину импульса, while (PINB & (1<<PB1)) эта строка ждет пока не произойдет спад на 0, пока спада нет идет замер длительности, и если она меньше 1000мс то выключить светодиод.

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

обработка прерывания в любых МК (пусть меня гуру исправят если я не прав) ВСЕГДА должна занимать минимум времени, они не предназначены для периодов типа ваших целая секунда - вечность с точки зрения МК.

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

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

gzp13
Offline
Зарегистрирован: 06.04.2015

Не получается напивать скетч по нарастанию, по изменению сигнала получается, а по нарастанию не получается(((

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

А нарастание - это не изменение?
Что мешает проверить значение сразу после входа в прерывания?
Пробный скетч написали?

pittyalex
Offline
Зарегистрирован: 09.11.2016

gzp13 пишет:

Не получается напивать скетч по нарастанию, по изменению сигнала получается, а по нарастанию не получается(((


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

gzp13
Offline
Зарегистрирован: 06.04.2015

pittyalex пишет:
gzp13 пишет:
Что мешает прерыванию реагировать на оба фронта: по первому фронту запоминать текущее время, по второму вычислять длительность. В основном цикле проверять эту длительность и реагировать в бесконечном цикле.

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

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

чтоб набросать примерчик, необходимо вчитаться в даташит, на это нужно время, которого к сожалению нет :(

могу скинуть пример с прерыванием PCINT на attiny85 но там много лишнего....

вам необходимо по большому счету всю логику программы поменять (если я правильно задачу понял):

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

в прерывании первой командой выключить прерывание, установить флаг.

в цикле loop постоянно смотреть состояние флага/время и как только он установиться - делать свою логику.

примеров в интернете масса:

http://osboy.ru/blog/microcontrollers/attiny13-switch.html

http://1io.ru/articles/microcontroller/attiny13/

https://radiokot.ru/forum/viewtopic.php?p=1657416

 

gzp13
Offline
Зарегистрирован: 06.04.2015

andycat пишет:

Вам необходимо по большому счету всю логику программы поменять (если я правильно задачу понял):

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

volatile int length = 0;
volatile int start_time = 0;

void setup() {
Serial.begin(9600);
// Привязываем к Pin2 прерывание по фронту сигнала
attachInterrupt(0, rising, RISING);
}

void loop() { }

//Обработчик прерывания на возрастание сигнала
void rising() {
// Привязываем к Pin2 прерывание по срезу сигнала
attachInterrupt(0, falling, FALLING);
//сохраняем значение времени начала импульса
start_time = micros();
}

//Обработчик прерывания по срезу сигнала
void falling() {
// Привязываем к Pin2 прерывание по фронту сигнала
attachInterrupt(0, rising, RISING);
//сохраняем значение длительности импульса
length = micros() - start_time;
if (length<1000) Serial.println("werty");
else Serial.println(length);
}

Вот делал на ардуино, все работает как надо, не пойму как этот код перевети на Attiny.

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

это как? "идут каждые 20мс, и мне надо измерять длину импульса и если она меньше 1000мс"

противоречие - нет? импульс 1000 мс не может идти каждые 20 мс, или его длительность меньше 20

 

gzp13
Offline
Зарегистрирован: 06.04.2015

тьфу,период 20мс, длительность импульса от 1мс до 2мс, надо отследить импульс менее 1мс.

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

gzp13 пишет:

тьфу,период 20мс, длительность импульса от 1мс до 2мс, надо отследить импульс менее 1мс.

Между периодами (импульсами) низкий уровень на пине?

gzp13
Offline
Зарегистрирован: 06.04.2015

[/quote] Между периодами (импульсами) низкий уровень на пине?[/quote]

так точно,низкий.

gzp13
Offline
Зарегистрирован: 06.04.2015
#define F_CPU 1200000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
volatile int length = 0;
volatile int start_time = 0;

void rising (void)
{
  MCUCR |= (1 << ISC01); //устанавливаем прерывание по спаду
  MCUCR &= ~ (1 << ISC00);
  GIMSK |= (1 << INT0);         //INT0 Interrupt Enable
    sei();                  //Global Interrupts Enable
start_time = micros();
falling();
}

void falling (void)
{
  MCUCR |= (1 << ISC01) | (1 << ISC00);  // устанавливаем прерывание по фронту
  GIMSK |= (1 << INT0); 
   sei(); 
    length = micros() - start_time;
    if (length<1000) PORTB |= (1 << PB4);  //если меньше 1000мкс , зажигаем светодиод
    if (length>1300) PORTB &= ~(1 << PB4); 
    rising();
  }
  int main()
{
   DDRB |= (1 << PB4);   // OUTPUT
  DDRB &= ~(1 << PB1);  // INPUT
  PORTB |= (1<<4);
  rising();
 while (1)
  {
   
  }
}

попробовал так,тоже ничего не получается.

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

andycat пишет:
gzp13 пишет:

тьфу,период 20мс, длительность импульса от 1мс до 2мс, надо отследить импульс менее 1мс.

Между периодами (импульсами) низкий уровень на пине?

Серва  и вот её тайминг?

gzp13
Offline
Зарегистрирован: 06.04.2015

Ну да, по этой диаграмме и пытаюсь написать код.

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

вот пример сработки прерывания по низкому уровню для attiny85 (13ой нету попробовать)

попробуйте - откомпилируется или нет для attyny13

#include <avr/sleep.h>
#include <avr/interrupt.h>

#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

// PB0 pin 5
#define PB0_OUT sbi(DDRB,PB0)
#define PB0_IN cbi(DDRB,PB0)
#define PB0_HIGH sbi(PORTB,PB0)
#define PB0_LOW cbi(PORTB,PB0)
// PB1 pin 6 - input data
#define PB1_OUT sbi(DDRB,PB1)
#define PB1_IN cbi(DDRB,PB1)
#define PB1_HIGH sbi(PORTB,PB1)
#define PB1_LOW cbi(PORTB,PB1)
#define PB1_READ bitRead(PINB,PB1)
// PB2 pin 7
#define PB2_OUT sbi(DDRB,PB2)
#define PB2_IN cbi(DDRB,PB2)
#define PB2_HIGH sbi(PORTB,PB2)
#define PB2_LOW cbi(PORTB,PB2)
// PB3 pin 2
#define PB3_OUT sbi(DDRB,PB3)
#define PB3_IN cbi(DDRB,PB3)
#define PB3_HIGH sbi(PORTB,PB3)
#define PB3_LOW cbi(PORTB,PB3)
// PB4 pin 3
#define PB4_OUT sbi(DDRB,PB4)
#define PB4_IN cbi(DDRB,PB4)
#define PB4_HIGH sbi(PORTB,PB4)
#define PB4_LOW cbi(PORTB,PB4)

ISR(PCINT0_vect) {
  if (PB1_READ == 0) { // LOW level KEY
    // disable interrupt
    cbi(GIMSK, PCIE);
    cbi(PCMSK, PCINT1);
  }
}

void setup () {
  // pins mode
  PB0_OUT; PB0_LOW;
  PB1_IN; PB1_HIGH;
  PB2_OUT; PB2_LOW;
  PB3_OUT; PB3_LOW;
  PB4_OUT; PB4_LOW;
  // enable interrupt
  sbi(GIMSK, PCIE);
  sbi(PCMSK, PCINT1);
}

void loop () {
}

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

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

gzp13 пишет:

Ну да, по этой диаграмме и пытаюсь написать код.

Только там меньше 1000мкс не бывает.
От 1000 до 2000 с серединой 1500.
Ищите  RC Switch.
Включая поиском недавно на форуме,  кто-то уже сделал это.

http://arduino.ru/forum/programmirovanie/poluchenie-dannykh-s-priemnika-...

https://brainwagon.org/2014/06/14/making-a-simple-rc-switch/

gzp13
Offline
Зарегистрирован: 06.04.2015

andycat пишет:

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

Код компилится, условие поменял на ==1, туда же вставил строку PB4_HIGH else PB4_LOW, не работает.

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

gzp13 пишет:

 туда же вставил строку PB4_HIGH else PB4_LOW

ничего не понял - весь код приведите

gzp13
Offline
Зарегистрирован: 06.04.2015
#include <avr/sleep.h>
#include <avr/interrupt.h>

#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

// PB0 pin 5
#define PB0_OUT sbi(DDRB,PB0)
#define PB0_IN cbi(DDRB,PB0)
#define PB0_HIGH sbi(PORTB,PB0)
#define PB0_LOW cbi(PORTB,PB0)
// PB1 pin 6 - input data
#define PB1_OUT sbi(DDRB,PB1)
#define PB1_IN cbi(DDRB,PB1)
#define PB1_HIGH sbi(PORTB,PB1)
#define PB1_LOW cbi(PORTB,PB1)
#define PB1_READ bitRead(PINB,PB1)
// PB2 pin 7
#define PB2_OUT sbi(DDRB,PB2)
#define PB2_IN cbi(DDRB,PB2)
#define PB2_HIGH sbi(PORTB,PB2)
#define PB2_LOW cbi(PORTB,PB2)
// PB3 pin 2
#define PB3_OUT sbi(DDRB,PB3)
#define PB3_IN cbi(DDRB,PB3)
#define PB3_HIGH sbi(PORTB,PB3)
#define PB3_LOW cbi(PORTB,PB3)
// PB4 pin 3
#define PB4_OUT sbi(DDRB,PB4)
#define PB4_IN cbi(DDRB,PB4)
#define PB4_HIGH sbi(PORTB,PB4)
#define PB4_LOW cbi(PORTB,PB4)

ISR(PCINT0_vect) {
  if (PB1_READ == 1) { // LOW level KEY
    // disable interrupt
    cbi(GIMSK, PCIE);
    cbi(PCMSK, PCINT1);
   PB4_HIGH;
  }
  else PB4_LOW;
}

void setup () {
  // pins mode
  PB0_OUT; PB0_LOW;
  PB1_IN; PB1_HIGH;
  PB2_OUT; PB2_LOW;
  PB3_OUT; PB3_LOW;
  PB4_OUT; PB4_LOW;
  // enable interrupt
  sbi(GIMSK, PCIE);
  sbi(PCMSK, PCINT1);
}

void loop () {
}

 

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

а так работает?:

#include <avr/sleep.h>
#include <avr/interrupt.h>

#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

// PB0 pin 5
#define PB0_OUT sbi(DDRB,PB0)
#define PB0_IN cbi(DDRB,PB0)
#define PB0_HIGH sbi(PORTB,PB0)
#define PB0_LOW cbi(PORTB,PB0)
// PB1 pin 6 - input data
#define PB1_OUT sbi(DDRB,PB1)
#define PB1_IN cbi(DDRB,PB1)
#define PB1_HIGH sbi(PORTB,PB1)
#define PB1_LOW cbi(PORTB,PB1)
#define PB1_READ bitRead(PINB,PB1)
// PB2 pin 7
#define PB2_OUT sbi(DDRB,PB2)
#define PB2_IN cbi(DDRB,PB2)
#define PB2_HIGH sbi(PORTB,PB2)
#define PB2_LOW cbi(PORTB,PB2)
// PB3 pin 2
#define PB3_OUT sbi(DDRB,PB3)
#define PB3_IN cbi(DDRB,PB3)
#define PB3_HIGH sbi(PORTB,PB3)
#define PB3_LOW cbi(PORTB,PB3)
// PB4 pin 3
#define PB4_OUT sbi(DDRB,PB4)
#define PB4_IN cbi(DDRB,PB4)
#define PB4_HIGH sbi(PORTB,PB4)
#define PB4_LOW cbi(PORTB,PB4)

ISR(PCINT0_vect) {
  if (PB1_READ == 1) { // LOW level KEY
    // disable interrupt
    cbi(GIMSK, PCIE);
    cbi(PCMSK, PCINT1);
   PB4_HIGH;
  }
  //else PB4_LOW;
}

void setup () {
  // pins mode
  PB0_OUT; PB0_LOW;
  PB1_IN; PB1_HIGH;
  PB2_OUT; PB2_LOW;
  PB3_OUT; PB3_LOW;
  PB4_OUT; PB4_LOW;
  // enable interrupt
  sbi(GIMSK, PCIE);
  sbi(PCMSK, PCINT1);
}

void loop () {
}

я конечно не уверен - но вы реально думаете что сможете увидеть моргание светодиода длительностью 2 мс ?

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

тупо кнопку на PB1 прицепите - проверьте - от нажатия светодиод загорается?

gzp13
Offline
Зарегистрирован: 06.04.2015

Так сразу прерывание срабатывает, независимо от того, что подано на вход PB1, т.е сразу после загрузки скетча светодиод на PB4 загорается, специально добавил delay туда чтобы понять, прерывание включается сразу.

gzp13
Offline
Зарегистрирован: 06.04.2015

andycat пишет:

я конечно не уверен - но вы реально думаете что сможете увидеть моргание светодиода длительностью 2 мс ?

А мне не надо отслеживать моргание, мне же надо просто замерить длину импульса.

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

вот в этот скетч если кнопку подцепить - будет загораться при опузкании на ноль PB1? т.е. понять прерывание вообще работает?

 

http://arduino.ru/forum/programmirovanie/attiny13a-101-primenenie?page=2...

 

gzp13
Offline
Зарегистрирован: 06.04.2015

Вот набросал что я хочу получить, как это делаю,но ничего не получается((

gzp13
Offline
Зарегистрирован: 06.04.2015

andycat пишет:

вот в этот скетч если кнопку подцепить - будет загораться при опузкании на ноль PB1? т.е. понять прерывание вообще работает?

Да, работает, светодиод загорается при замыкании PB1 на землю.

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

наверное как то так:

#include <avr/sleep.h>
#include <avr/interrupt.h>

#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

// PB0 pin 5
#define PB0_OUT sbi(DDRB,PB0)
#define PB0_IN cbi(DDRB,PB0)
#define PB0_HIGH sbi(PORTB,PB0)
#define PB0_LOW cbi(PORTB,PB0)
// PB1 pin 6 - input data
#define PB1_OUT sbi(DDRB,PB1)
#define PB1_IN cbi(DDRB,PB1)
#define PB1_HIGH sbi(PORTB,PB1)
#define PB1_LOW cbi(PORTB,PB1)
#define PB1_READ bitRead(PINB,PB1)
// PB2 pin 7
#define PB2_OUT sbi(DDRB,PB2)
#define PB2_IN cbi(DDRB,PB2)
#define PB2_HIGH sbi(PORTB,PB2)
#define PB2_LOW cbi(PORTB,PB2)
// PB3 pin 2
#define PB3_OUT sbi(DDRB,PB3)
#define PB3_IN cbi(DDRB,PB3)
#define PB3_HIGH sbi(PORTB,PB3)
#define PB3_LOW cbi(PORTB,PB3)
// PB4 pin 3
#define PB4_OUT sbi(DDRB,PB4)
#define PB4_IN cbi(DDRB,PB4)
#define PB4_HIGH sbi(PORTB,PB4)
#define PB4_LOW cbi(PORTB,PB4)

byte flag_start;
unsigned long timer_end;
byte action_flag;

ISR(PCINT0_vect) {
  if ((PB1_READ == 1) && (flag_start == 0)) {
    // disable interrupt
    cbi(GIMSK, PCIE);
    cbi(PCMSK, PCINT1);
    //-
    flag_start = 1;
    timer_end = micros();
    action_flag = 0;
    // enable interrupt
    sbi(GIMSK, PCIE);
    sbi(PCMSK, PCINT1);
    //-
  } else if ((PB1_READ == 0) && (flag_start == 1)) {
    // disable interrupt
    cbi(GIMSK, PCIE);
    cbi(PCMSK, PCINT1);
    //-
    flag_start = 0;
    if ((micros() - timer_end) < 1000UL) {
      action_flag = 1;
    } else {
      // enable interrupt
      sbi(GIMSK, PCIE);
      sbi(PCMSK, PCINT1);
      //-
    }
  }
}

void setup () {
  // pins mode
  PB0_OUT; PB0_LOW;
  PB1_IN;
  PB2_OUT; PB2_LOW;
  PB3_OUT; PB3_LOW;
  PB4_OUT; PB4_LOW;
  // init
  flag_start = 0;
  timer_end = micros();
  action_flag = 0;
  // enable interrupt
  sbi(GIMSK, PCIE);
  sbi(PCMSK, PCINT1);
}

void loop () {
  if (action_flag == 1) {
    action_flag = 0;
    // do everything

    // enable interrupt
    sbi(GIMSK, PCIE);
    sbi(PCMSK, PCINT1);
  }
}

 

gzp13
Offline
Зарегистрирован: 06.04.2015

Не, не работает.

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

gzp13 пишет:

Не, не работает.

а в 92 строке вписали зажечь светодиод?

хм..интересно, а если в 61 строке поменять условие на > ?

там вообще есть имульсы меньше 1000 мкс ?

 

gzp13
Offline
Зарегистрирован: 06.04.2015

andycat пишет:

 

а в 92 строке вписали зажечь светодиод?

хм..интересно, а если в 61 строке поменять условие на > ?

там вообще есть имульсы меньше 1000 мкс ?

 

Вписал, на ардуине уно проверял (скетч выше писал)длительность, импульсы есть, от 98- до 1700мкс.

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

gzp13 пишет:

andycat пишет:

 

а в 92 строке вписали зажечь светодиод?

хм..интересно, а если в 61 строке поменять условие на > ?

там вообще есть имульсы меньше 1000 мкс ?

 

Вписал, на ардуине уно проверял (скетч выше писал)длительность, импульсы есть, от 98- до 1700мкс.

условие на больше 1000 поменяли для тестирования? светодиод загорелся?

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

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

и кстати: смотрю ваш код для UNO - а вы уверены что он корректно работает?

http://arduino.ru/forum/programmirovanie/attiny13a-101-primenenie?page=2...

во время отображения могут (и наверняка срабатывают, т.к. Serial.print работает несоизмеримо медленнее ваших замеров) оба прерывания сработать и наверняка переменная start_time дает уже некорректное значение.

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

да и здесь вам ответили что возможно времени меньше 1000 мкс не бывает

http://arduino.ru/forum/programmirovanie/attiny13a-101-primenenie?page=2...

 

gzp13
Offline
Зарегистрирован: 06.04.2015

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