Attiny13 и посыл NEC IR кода

ExGen
Offline
Зарегистрирован: 11.09.2018

Приветствую!

Собрал небольшую схемку на attiny13 и есть необходимость циклически отправлять определенный код кнопки пульта NEC. Библиотеку в attiny13 не впихнуть к сожалению) По крайней мере таковых не нашел.
Читал как работает протокол, пробовал определенный алгоритм, но хоть убей никак не могу получить генерацию.
Приемник собран на arduino nano 328. Обычный пульт нормально обрабатывает. С attiny мой алгоритм всегда как неизвестный пульт и всегда разное значение hex... Уже  несколько дней пытаюсь менять алгоритм, никак не въеду.
Приемник на 38Кгц. Рассчитывая 1 / 38000 = 26 микросекунд - длина одного импульса.
Прошу подсказать, где я что не так понял? Что не так в коде, в чем может быть ошибка моя?
Последняя версия кода:
 

#define OSC_pin 0

#define NEC_BITS          32
#define NEC_HDR_MARK    9000
#define NEC_HDR_SPACE   4500
#define NEC_BIT_MARK     560
#define NEC_ONE_SPACE   1690
#define NEC_ZERO_SPACE   560
#define NEC_RPT_SPACE   2250

unsigned int periodTime = 26;
unsigned int periodOnTime = 26;

void setup() {
pinMode(OSC_pin,OUTPUT);
}

void start() {
for(int g=0;g<173;g++){ 
  digitalWrite(OSC_pin, HIGH);
  delayMicroseconds(periodTime);
  digitalWrite(OSC_pin, LOW);
  delayMicroseconds(periodOnTime);
  }
}

void impulse1() {
for(int g=0;g<10;g++){ 
  digitalWrite(OSC_pin, HIGH);
  delayMicroseconds(periodTime);
  digitalWrite(OSC_pin, LOW);
  delayMicroseconds(periodOnTime);
  }
delayMicroseconds(1690);
}

void impulse0() {
for(int g=0;g<10;g++){ 
  digitalWrite(OSC_pin, HIGH);
  delayMicroseconds(periodTime);
  digitalWrite(OSC_pin, LOW);
  delayMicroseconds(periodOnTime);
  }
delayMicroseconds(560);
}

void footer() {
for(int g=0;g<10;g++){ 
  digitalWrite(OSC_pin, HIGH);
  delayMicroseconds(periodTime);
  digitalWrite(OSC_pin, LOW);
  delayMicroseconds(periodOnTime);
  }
}

void loop() {
digitalWrite(OSC_pin, LOW);
start();
delayMicroseconds(4500);

impulse1();  //1
impulse0();
impulse1();  //2
impulse0();
impulse0();
impulse0();
impulse0();
impulse1();  //3

impulse0();
impulse1();  //4
impulse0();
impulse1();  //5
impulse1();  //6
impulse1();  //7
impulse1();  //8
impulse0();

impulse1();  //1
impulse1();  //2
impulse1();  //3
impulse0();
impulse0();
impulse0();
impulse0();
impulse0();

impulse0();
impulse0();
impulse0();
impulse1();  //4
impulse1();  //5
impulse1();  //6
impulse1();  //7
impulse1();  //8

footer();
//A15EE01F
delay(41);
delayMicroseconds(940); 
}

 

rkit
Offline
Зарегистрирован: 23.11.2016

А откуда у тебя микросекунды считаются?

ExGen
Offline
Зарегистрирован: 11.09.2018

ExGen
Offline
Зарегистрирован: 11.09.2018

Использовал https://github.com/MCUdude/MicroCore
И настройки выше. Хз откуда он там считает, но что-то считает...
Есть вариант несоответствия времени в МК относительно реального времени?

rkit
Offline
Зарегистрирован: 23.11.2016

Ну точность этого регулятора +-10% в идеальных условиях. Вообще такое без осциллографа отлаживать замучаешься.

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

на 16 мегагерцах точность микрос 4 микросекунды, на 4.8-х видимо в четыре раза хуже

rkit
Offline
Зарегистрирован: 23.11.2016

ua6em пишет:

на 16 мегагерцах точность микрос 4 микросекунды, на 4.8-х видимо в четыре раза хуже

Нет, это особенность реализации. 1МГц это разрешение в одну мкс, тут аж 4.8. Но поглядеть на конкретную реализацию и ее проблемы не помешало бы. А то и переписать генерацию несущей на ШИМ.

ExGen
Offline
Зарегистрирован: 11.09.2018

Не в курсе был этого... Это значение отклонения стабильное будет или динамическое?

rkit
Offline
Зарегистрирован: 23.11.2016

ExGen пишет:

Не в курсе был этого... Это значение отклонения стабильное будет или динамическое?

В пределах постоянной температуры и напряжения. Даташит надо читать, раз уж полез.

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

ExGen пишет:

Приемник на 38Кгц. Рассчитывая 1 / 38000 = 26 микросекунд - длина одного импульса.

Круто! Пешы исчо!

ЗЫ: ...изпацтала: 26 мкс - это весь импульс и хай и лоу... каждого по 13. Все остальное выше для таких таймингов - херня. Честное пионЭрское! Хотя ослик был бы кстати.

ExGen
Offline
Зарегистрирован: 11.09.2018

Тоже прикинул этот момент и сделал по 13... И перерасчет всех функций под 13 (увеливив в 2 раза циклы) - результат тот же... за NEC он это не принимает...вместо 9000мс первых всегда 10800мс, что интересно...

 

nik182
Offline
Зарегистрирован: 04.05.2015

Ё! А я привык, что 38 кГц это несущая, которая в приёмнике фильтруется. А сигнал, совсем не 38 летит. Это нет так?

ExGen
Offline
Зарегистрирован: 11.09.2018

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

ExGen
Offline
Зарегистрирован: 11.09.2018

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

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

Как образец для подражания, можно посмотреть у широко известного в узких кругах Ридико Л.И.

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

Green пишет:

Как образец для подражания, можно посмотреть у широко известного в узких кругах Ридико Л.И.

осталось код для IDE адаптировать... но можно и не адаптировать, прошивки приложены, константу подстройки внутреннего генератора менять тут )))

 

и код для attiny13
 

:020000020000FC
:1000000002C018952100E4E0F0E0C89501BE00E8C8
:1000100008B90FE108BB0DE107BB00E305BF00E431
:100020000BBF78948895F8941CE420E002E008BBAC
:10003000000034E03A95F1F70FE108BB000033E02F
:100040003A95F1F71150204088F715E826E00000B6
:1000500035E03A95F1F711502040C8F71EE020E056
:1000600002E008BB000034E03A95F1F70FE108BB6D
:10007000000033E03A95F1F71150204088F71EE573
:1000800020E0000035E03A95F1F711502040C8F724
:100090001FE020E002E008BB000034E03A95F1F7F1
:1000A0000FE108BB000033E03A95F1F71150204012
:1000B00088F716ED20E0000035E03A95F1F7115091
:1000C0002040C8F71EE020E002E008BB000034E05A
:1000D0003A95F1F70FE108BB000033E03A95F1F7EC
:1000E0001150204088F71FEC2EE0000035E03A95D3
:1000F000F1F711502040C8F71CE420E002E008BBF3
:10010000000034E03A95F1F70FE108BB000033E05E
:100110003A95F1F71150204088F715E826E00000E5
:1001200035E03A95F1F711502040C8F71EE020E085
:1001300002E008BB000034E03A95F1F70FE108BB9C
:10014000000033E03A95F1F71150204088F71EE5A2
:1001500020E0000035E03A95F1F711502040C8F753
:100160001FE020E002E008BB000034E03A95F1F720
:100170000FE108BB000033E03A95F1F71150204041
:1001800088F716ED20E0000035E03A95F1F71150C0
:100190002040C8F71EE020E002E008BB000034E089
:1001A0003A95F1F70FE108BB000033E03A95F1F71B
:1001B0001150204088F7B19BFECF04E6B19BFBCFE6
:1001C0001BE320E0000035E03A95F1F711502040A4
:0801D000C8F70A9599F725CF45
:00000001FF

 

ZXPirate
Offline
Зарегистрирован: 18.02.2020

Tiny13 имеет калибровочные байты внутреннего генератора, возможно они не были установлены китайцами или затерты при очистке чипа.

Загрузи в нее блинк, с паузой 10 сек и проверь секундомером.

rkit
Offline
Зарегистрирован: 23.11.2016

+-10% - цифра с заводской калибровкой. Читайте даташит.

ExGen
Offline
Зарегистрирован: 11.09.2018

Благодарю всех за подсказки. Вероятно реально весь прикол в частоте...
Итоговый код который стабильно стал нормально работать. Калибровать по нормальному возможности нет, но прикинул, что увеличивая/уменьшая немного периоды, возможно выйду на рабочий вариант. А как выше писал, первый сигнал у меня вместо 9000 был по факту 10800... То решил уменьшать, пока не получу 9000. При 10мс стабильно все заработало и передает нужное мне значение.

#define OSC_pin 0

#define NEC_BITS          32
#define NEC_HDR_MARK    9000
#define NEC_HDR_SPACE   4500
#define NEC_BIT_MARK     560
#define NEC_ONE_SPACE   1690
#define NEC_ZERO_SPACE   560
#define NEC_RPT_SPACE   2250

unsigned int periodTime = 10;
unsigned int periodOnTime = 10;

void setup() {
pinMode(OSC_pin,OUTPUT);
}

void start() {
for(int g=0;g<346;g++){ 
  digitalWrite(OSC_pin, HIGH);
  delayMicroseconds(periodTime);
  digitalWrite(OSC_pin, LOW);
  delayMicroseconds(periodOnTime);
  }
}

void impulse1() {
for(int g=0;g<20;g++){ 
  digitalWrite(OSC_pin, HIGH);
  delayMicroseconds(periodTime);
  digitalWrite(OSC_pin, LOW);
  delayMicroseconds(periodOnTime);
  }
delayMicroseconds(1690);
}

void impulse0() {
for(int g=0;g<20;g++){ 
  digitalWrite(OSC_pin, HIGH);
  delayMicroseconds(periodTime);
  digitalWrite(OSC_pin, LOW);
  delayMicroseconds(periodOnTime);
  }
delayMicroseconds(560);
}

void footer() {
for(int g=0;g<20;g++){ 
  digitalWrite(OSC_pin, HIGH);
  delayMicroseconds(periodTime);
  digitalWrite(OSC_pin, LOW);
  delayMicroseconds(periodOnTime);
  }
}

void loop() {
digitalWrite(OSC_pin, LOW);
start();
delayMicroseconds(4500);

impulse1();  //1
impulse0();
impulse1();  //2
impulse0();
impulse0();
impulse0();
impulse0();
impulse1();  //3

impulse0();
impulse1();  //4
impulse0();
impulse1();  //5
impulse1();  //6
impulse1();  //7
impulse1();  //8
impulse0();

impulse1();  //1
impulse1();  //2
impulse1();  //3
impulse0();
impulse0();
impulse0();
impulse0();
impulse0();

impulse0();
impulse0();
impulse0();
impulse1();  //4
impulse1();  //5
impulse1();  //6
impulse1();  //7
impulse1();  //8

footer();
//A15EE01F
delay(41);
delayMicroseconds(940); 
}

 

ZXPirate
Offline
Зарегистрирован: 18.02.2020

И того 20%. И это при заводской калибровке, а если без?

У меня был случай, тоже долго не мог понять почему не работает, вместо 10 секунд, пауза была 7. А это уже 30%

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

Есть апнот AVR055: Using a 32 kHz crystal to calibrate the internal RC oscillator.

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

Green пишет:

Есть апнот AVR055: Using a 32 kHz crystal to calibrate the internal RC oscillator.

ты жеж понимаешь в ассемлере, я поправил код чуток перевести  c 12 на attiny13 можешь глянуть,смущают два момента

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

Нет вопросов. Только я уже позабывал всё.) Ассемблер одинаковый, у 13-й больше команд.

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

В коде инициализации:
 

;Initialization:

Init:	ldi	ZL,byte1(OscCV*2)	;read oscillator calibration value
	ldi	ZH,byte2(OscCV*2)
	lpm
	out	OSCCAL,r0		;calibrate oscillator

	ldi	temp,(1<<ACD)		;analog comparator disable
	out	ACSR,temp

	ldi	temp,PUPB
	out	PORTB,temp		;init PORTB and on/off pullup
	ldi	temp,DIRB	
	out	DDRB,temp		;set PORTB direction

	ldi	temp,(1<<SE) | (1<<SM)	;sleep - power down, level INT0
	out	MCUCR,temp
	ldi	temp,(1<<INT0)		;INT0 enable
	out	GIMSK,temp

Строка 16, у attiny13 в отличии от 12 есть SM0 и SM1, что указывать?

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

Ну а причём здесь ассемблер? Открываешь ДШ и смотришь отличия.

У 12:

• Bit 4 - SM: Sleep Mode
This bit selects between the two available sleep modes. When SM is cleared (zero), Idle
Mode is selected as Sleep Mode. When SM is set (one), Power-down Mode is selected
as Sleep Mode. For details, refer to the paragraph “Sleep Modes” below.
 
У 13:
SM1 SM0
 0 0 - Idle
 0 1 - ADC Noise Reduction
 1 0 - Power Down
Ага?
ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Понятно, заменить на SM1 )))
 

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

Ага. Просто в 12-й два слип режима, а в 13-й три. Соответственно, на один бит больше.)

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

ExGen пишет:

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


Обычно пишется тестовая прошивка в цикле формирующая на пине импульс определённой длительности,
который как то возможно измерить. Например, если ничего нет, то на выход подключаешь светодиод, а импульс делаешь побольше, 10 сек, как тут уже советовали.
Для изменения OSCCAL подключаешь одну (лучше две) кнопки - на увеличение/уменьшение.
Изменённый OSCCAL выводишь доступным способом - Serial, EEPROM, да хоть кодом Морзе.)

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

Green пишет:

ExGen пишет:

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


Обычно пишется тестовая прошивка в цикле формирующая на пине импульс определённой длительности,
который как то возможно измерить. Например, если ничего нет, то на выход подключаешь светодиод, а импульс делаешь побольше, 10 сек, как тут уже советовали.
Для изменения OSCCAL подключаешь одну (лучше две) кнопки - на увеличение/уменьшение.
Изменённый OSCCAL выводишь доступным способом - Serial, EEPROM, да хоть кодом Морзе.)

интересно, а калибровочные константы считываемые программатором зашитые производителем что-то значат?

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

Значат. +/- %, для определённого напряжения, температуры. У некоторых ещё и для определённой частоты, например 1 мгц, а для других +/- лапоть.

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

Понятно! А за ссылку на проект TKS! Получил истинное программистское наслаждение )))
PS Всё таки ASM это божественно ...сидишь...раскладываешь по коробочкам...тасуешь )))

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

Это же ж хобби. Кому что нравится. Кому поп, а кому попадья.)

Где-то книжечка валяется. Здоровый талмуд. Название "Ассемблер для Windows."
Автор объясняет почему именно Ассемблер. Типа, всё под контролем, ощущение власти.)

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

учился как и Билл Гейтс - у Питера Нортона, он очно, я по его книге )))

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

Там и "Ассемблер для Windows" легко находится. Мы ещё учились по Журдену: "Справочник программиста на ПК IBM".)

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

Green пишет:

Там и "Ассемблер для Windows" легко находится. Мы ещё учились по Журдену: "Справочник программиста на ПК IBM".)

под виндовс мне было уже не интересно, я жеж железячник