внешние прерывания attiny13

iopq
Offline
Зарегистрирован: 05.07.2016

есть вот такой код, работающий на ардуино-

#define rxPin 2 //пин приемника

void setup()
{
pinMode(rxPin, INPUT);
Serial.begin(115200); 
Serial.println("Came started");
attachInterrupt(0, grab, CHANGE); 
interrupts();
}

volatile static long lastCode = 0;

void loop() {
if (lastCode > 0)
{
Serial.println(lastCode);
lastCode = 0;
}
}

#define MAX_DELTA 200
boolean CheckValue(unsigned int base, unsigned int value)
{
return ((value == base) || ((value > base) && ((value - base) < MAX_DELTA)) || ((value < base) && ((base - value) < MAX_DELTA)));
}
volatile unsigned long prevtime;
volatile unsigned int lolen, hilen, state;
volatile static byte cameCounter = 0; // count of bits stored
volatile static long cameCode = 0; // code itself

void grab() {
state = digitalRead(rxPin);
if (state == HIGH)
lolen = micros() - prevtime;
else
hilen = micros() - prevtime;
prevtime = micros();

if (state == LOW)
{
// последовательность закончилась
if (CheckValue(320, hilen) && CheckValue(640, lolen)) // valid 1
{
cameCode = (cameCode << 1) | 1;
cameCounter++;
}
else if (CheckValue(640, hilen) && CheckValue(320, lolen)) // valid 0
{
cameCode = (cameCode << 1) | 0;
cameCounter++;
}
else cameCounter = 0;
} else 
if (lolen > 1000 && (cameCounter == 24) 
{
lastCode = cameCode & 0xfff;
cameCounter = 0;
cameCode = 0;
}
if (lastCode == 432) 
{
 time1=millis()-time;
 if(time1>200) digitalWrite(13, !digitalRead(13));
 time = millis();  
}
}

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

#include <avr/io.h>
#include <avr/interrupt.h> 
#define MAX_DELTA 200
volatile unsigned long prevtime;
volatile unsigned int lolen, hilen, state;
volatile static byte cameCounter = 0;
volatile static long cameCode = 0; 
volatile static long lastCode = 0;
static unsigned long time = 0;
static unsigned long time1 = 0;

boolean CheckValue(unsigned int base, unsigned int value)
{
return ((value == base) || ((value > base) && ((value - base) < MAX_DELTA)) || ((value < base) && ((base - value) < MAX_DELTA)));
}

void InitINT0() 
{
  MCUCR =_BV(ISC01) | _BV(ISC00);
  GIMSK = _BV(INT0);
  sei();
}

void setup() { 
  DDRB |= (1 << PB1);   //pinMode(1, OUTPUT);     
  PORTB |= (1 << PB1);  //digitalWrite(1,HIGH);
  PORTB |= (1 << PB0); //digitalWrite(0, HIGH);
  InitINT0();
}

void loop()
{
  
}

ISR(PCINT0_vect) // прерывание по вектору PCINT0(ножка РВ0), тоесть по изменению состояния вывода
{
if (PINB & (1 << PINB0) == HIGH)
lolen = micros() - prevtime;
else
hilen = micros() - prevtime;
prevtime = micros();

if (PINB & (1 << PINB0) == LOW)
{
if (CheckValue(320, hilen) && CheckValue(640, lolen)) // valid 1
{
cameCode = (cameCode << 1) | 1;
cameCounter++;
}
else if (CheckValue(640, hilen) && CheckValue(320, lolen)) // valid 0
{
cameCode = (cameCode << 1) | 0;
cameCounter++;
}
else cameCounter = 0;
} else 
if (lolen > 1000 && (cameCounter == 24) )
{
lastCode = cameCode & 0xfff;
cameCounter = 0;
cameCode = 0;
}
if (lastCode == 432) 
{
 time1=millis()-time;
if(time1>200) digitalWrite(1, !PINB & (1 << PINB1));
 time = millis();  
}
}

 

iopq
Offline
Зарегистрирован: 05.07.2016

подскажите как вот тут-

digitalWrite(13, !(PINB&(1<<5))); //digitalWrite(13, !digitalRead(13));

избавиться от digitalWrite?

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

iopq пишет:

подскажите как вот тут- избавиться от digitalWrite?

PORTB ^= (1<<5);

Только у Attiny13a ножка PB5 она же ножка Reset. Чтобы её использовать как порт ввода-вывода, нужно во фьюзах отключить Reset. Но тогда вы не сможете прошивать тиньку ISP программатором.

iopq
Offline
Зарегистрирован: 05.07.2016

спасибо. у меня получился вот такой код, работающий на ардуино-


#include <avr/interrupt.h>
static unsigned long time = 0;
static unsigned long time1 = 0;
volatile static long lastCode = 0;
boolean CheckValue(unsigned int base, unsigned int value)
{
return ((value == base) || ((value > base) && ((value - base) < 200)) || ((value < base) && ((base - value) < 200)));
}
volatile unsigned long prevtime;
volatile unsigned int lolen, hilen;
volatile static byte cameCounter = 0; 
volatile static long cameCode = 0; 

void setup()
{
 DDRB |= (1 << PB5); //pinMode(13, OUTPUT);                            
//Attiny13 - DDRB |= (1 << PB1);
 
EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (CHANGE << ISC00); 
//Attiny13 - MCUCR =_BV(ISC01) | _BV(ISC00);
 EIMSK |= (1 << INT0);                                               
 //Attiny13 - GIMSK = _BV(INT0);
}

void loop() {
}

ISR(INT0_vect) { 
if (PIND&(1<<2))     // if (digitalRead(2) == HIGH)            
//Attiny13 - PINB&(1<<0)                     
lolen = micros() - prevtime;
else
hilen = micros() - prevtime;
prevtime = micros();

if (!(PIND&(1<<2)))  // if (digitalRead(2) == LOW)           
 //Attiny13 - PINB&(1<<0)
{
if (CheckValue(320, hilen) && CheckValue(640, lolen)) 
{
cameCode = (cameCode << 1) | 1;
cameCounter++;
}
else if (CheckValue(640, hilen) && CheckValue(320, lolen)) 
{
cameCode = (cameCode << 1) | 0;
cameCounter++;
}
else cameCounter = 0;
} else 
if (lolen > 1000 && (cameCounter == 24)) 
{
lastCode = cameCode & 0xfff;
cameCounter = 0;
cameCode = 0;
}
if (lastCode == 1234) 
{
 time1=millis()-time;
 if(time1>200) PORTB ^= (1<<5); //digitalWrite(13, !digitalRead(13));  
//Attiny13 - PORTB ^= (1<<1);
 time = millis();  
 lastCode = 0;
}
}

и занимающий 1176 байт. что то он пожирел вместо уменьшения. я в комментариях написал что на что планирую заменить для attiny13. насколько это корректно?

iopq
Offline
Зарегистрирован: 05.07.2016

добился 990 байт при частоте 600 кгц. подскажите должно ли работать?

#include <avr/interrupt.h>
static unsigned long time = 0;
static unsigned long time1 = 0;
boolean CheckValue(unsigned int base, unsigned int value)
{
return ((value == base) || ((value > base) && ((value - base) < 200)) || ((value < base) && ((base - value) < 200)));
}
volatile unsigned long prevtime;
volatile unsigned int lolen, hilen;
volatile static byte cameCounter = 0; 
volatile static int cameCode = 0; 

void setup()
{
 DDRB |= (1 << PB1); //шестая ножка- выход                          
 MCUCR =_BV(ISC01) | _BV(ISC00);
 GIMSK = _BV(INT0);
}

void loop() {
}

ISR(INT0_vect) { 
if (PINB&(1<<0))                                
lolen = micros() - prevtime;
else
hilen = micros() - prevtime;
prevtime = micros();

if (!(PINB&(1<<0)))         
{
if (CheckValue(320, hilen) && CheckValue(640, lolen)) 
{
cameCode = (cameCode << 1) | 1;
cameCounter++;
}
else if (CheckValue(640, hilen) && CheckValue(320, lolen)) 
{
cameCode = (cameCode << 1) | 0;
cameCounter++;
}
else cameCounter = 0;
} else 

if (lolen > 1000 && (cameCounter == 24)) 
{
cameCode = cameCode & 0xfff;
cameCounter = 0;
}
if (cameCode == 1234) 
{
 time1=millis()-time;
 if(time1>200) PORTB ^= (1<<1);
 time = millis();  
 cameCode = 0;
}
}

 

iopq
Offline
Зарегистрирован: 05.07.2016

нашел ошибки но не работает-

#include <avr/interrupt.h>
static unsigned long time = 0;
static unsigned long time1 = 0;
boolean CheckValue(unsigned int base, unsigned int value)
{
return ((value == base) || ((value > base) && ((value - base) < 200)) || ((value < base) && ((base - value) < 200)));
}
volatile unsigned long prevtime;
volatile unsigned int lolen, hilen;
volatile static byte cameCounter = 0; 
volatile static int cameCode = 0; 

void setup()
{
  DDRB |= (1 << PB0); //пятая ножка- выход                          
  PORTB |= (1 << PB0);//высокий уровень на выходе
 
  DDRB &= ~(1 << PB1);//шестая ножка- вход

  MCUCR =_BV(ISC01) | _BV(ISC00);
  GIMSK = _BV(INT0);
  sei();
}

void loop() {
}

ISR(INT0_vect) { 
if (PINB&(1<<1))                                
lolen = micros() - prevtime;
else
hilen = micros() - prevtime;
prevtime = micros();

if (!(PINB&(1<<1)))         
{
if (CheckValue(320, hilen) && CheckValue(640, lolen)) 
{
cameCode = (cameCode << 1) | 1;
cameCounter++;
}
else if (CheckValue(640, hilen) && CheckValue(320, lolen)) 
{
cameCode = (cameCode << 1) | 0;
cameCounter++;
}
else cameCounter = 0;
} else 

if (lolen > 1000 && (cameCounter == 24)) 
{
cameCode = cameCode & 0xfff;
cameCounter = 0;
}
if (cameCode == 1234) 
{
 time1=millis()-time;
 if(time1>200) PORTB ^= (1<<0);
 time = millis();  
 cameCode = 0;
}
}

 

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

строка 20 задает прерывание по Росту!!!!!!

а тебе нужно по чейнджу, то есть  так:

MCUCR = 0x01;

дальше не смотрел. читай даташит и все проверяй.

iopq
Offline
Зарегистрирован: 05.07.2016

wdrakula пишет:

строка 20 задает прерывание по Росту!!!!!!

а тебе нужно по чейнджу, то есть  так:

MCUCR = 0x01;

дальше не смотрел. читай даташит и все проверяй.

да у меня трудности как раз в паре мест. на PB0 у меня выход, а на PB1 вход.

значит-

void setup()
{
  DDRB |= (1 << PB0); //пятая ножка- выход                         
  PORTB |= (1 << PB0);//высокий уровень на выходе

  DDRB &= ~(1 << PB1);//шестая ножка- вход

  MCUCR = 0x01; //прерываеие по CHANGE
  GIMSK = _BV(INT0);
}
 
ISR(INT0_vect) { //внешнее прерывание на порту PB1

if (PINB&(1<<1)) //если лог 1
...
}
if (!(PINB&(1<<1)))//если лог 0
...
}

 

верно же? и насколько корректна частота 600 кгц ? (если ставить выше - код не влезает)

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

iopq пишет:

верно же? и насколько корректна частота 600 кгц ? (если ставить выше - код не влезает)

твоя программа, тебе виднее. А бред про 600КГц я не коментирую, уж прости. Ты понимаешь какого размера micros() будет на 600КГц? Микрос будет считать с точностью 427 микросекунд. Гы! работать у тебя все это будет забавно.

iopq
Offline
Зарегистрирован: 05.07.2016

wdrakula пишет:

iopq пишет:

верно же? и насколько корректна частота 600 кгц ? (если ставить выше - код не влезает)

твоя программа, тебе виднее. А бред про 600КГц я не коментирую, уж прости. Ты понимаешь какого размера micros() будет на 600КГц? Микрос будет считать с точностью 427 микросекунд. Гы! работать у тебя все это будет забавно.

пока она вообще никак не работает. какую частоту надо и как можно еще уменьшить размер кода?

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

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

Еще поменял. 1018 - все у тебя помещается.

 

#include <avr/interrupt.h>

unsigned long time = 0;
bool CheckValue(int base, int value)
     {
      int x = base - value;
      //return ((value == base) || ((value > base) && ((value - base) < 200)) || ((value < base) && ((base - value) < 200)));
      return ((x >= 0)?(x < 200):(-x < 200));
     }

unsigned long prevtime;
unsigned int lolen, hilen;
byte cameCounter = 0; 
uint16_t cameCode = 0; 


void setup()
{
 cli();

 DDRB |= (1 << PB1); //шестая ножка- выход                          
 MCUCR =0x01;
 GIMSK = _BV(INT0);
 
 sei();
}

void loop() {
}

ISR(INT0_vect) 
  { 
  uint32_t  cm = micros();
  uint32_t cml = millis();

  if (!(PINB&(1<<0)))         
    {
    hilen = cm - prevtime;
    if (CheckValue(320, hilen) && CheckValue(640, lolen)) 
      {
      cameCode = (cameCode << 1) | 1;
      cameCounter++;
      }
    else if (CheckValue(640, hilen) && CheckValue(320, lolen)) 
      {
      cameCode = (cameCode << 1) | 0;
      cameCounter++;
      }
    else cameCounter = 0;
    }
  else
    lolen = cm - prevtime;   
  
  prevtime = cm;
  
  if (lolen > 1000 && (cameCounter == 24)) 
    {
    cameCode = cameCode & 0xfff;
    cameCounter = 0;
    }

  if (cameCode == 1234) 
    {
    if(cml -  time>200) PINB = (1<<1);
    time = cml;  
    cameCode = 0;
    }
}

 

iopq
Offline
Зарегистрирован: 05.07.2016

ваш код работает на ардуино а на тини13 нет. частоту установил в 9,6 мгц. сейчас хаотично мигает светодиод

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

1. Это не мой код, это твой код, немноого причесан.

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

хотя я за тобой не проверил, чорт возми! INT0 на PB1!!!!!

=========================================

5-я нога - диод, 6-ая нога вход от приемника!

==========================================

тогда диод цепляешь к PB0 код меняешь на такой: (9600 - это ты правильно угадал ;) )

#include <avr/interrupt.h>

unsigned long time = 0;
bool CheckValue(int base, int value)
     {
      int x = base - value;
      //return ((value == base) || ((value > base) && ((value - base) < 200)) || ((value < base) && ((base - value) < 200)));
      return ((x >= 0)?(x < 200):(-x < 200));
     }

unsigned long prevtime;
unsigned int lolen, hilen;
byte cameCounter = 0; 
uint16_t cameCode = 0; 


void setup()
{
 cli();

 DDRB |= (1 << PB0); //ПЯТАЯ!!! ножка- выход                          
 MCUCR =0x01;
 GIMSK = _BV(INT0);
 
 sei();
}

void loop() {
}

ISR(INT0_vect) 
  { 
  uint32_t  cm = micros();
  uint32_t cml = millis();

  if (!(PINB&(1<<1)))         
    {
    hilen = cm - prevtime;
    if (CheckValue(320, hilen) && CheckValue(640, lolen)) 
      {
      cameCode = (cameCode << 1) | 1;
      cameCounter++;
      }
    else if (CheckValue(640, hilen) && CheckValue(320, lolen)) 
      {
      cameCode = (cameCode << 1) | 0;
      cameCounter++;
      }
    else cameCounter = 0;
    }
  else
    lolen = cm - prevtime;   
  
  prevtime = cm;
  
  if (lolen > 1000 && (cameCounter == 24)) 
    {
    cameCode = cameCode & 0xfff;
    cameCounter = 0;
    }

  if (cameCode == 1234) 
    {
    if(cml -  time>200) PINB = (1<<0);
    time = cml;  
    cameCode = 0;
    }
}

 

iopq
Offline
Зарегистрирован: 05.07.2016

хаотичное мигание пропало но и не работает

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

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

Схему, описание и что хочешь получить. ОК?

Посмотрю, если будет время. Откуда у тебя эти значения для 0 и 1? Что означает "на ардуино работает"? - на какой? -  при какой схеме? - короче пиши все подробно, форум терпит, а я завтра посмотрю.

Все.... чакры промыл, пора спать....

iopq
Offline
Зарегистрирован: 05.07.2016

начало тут http://arduino.ru/forum/programmirovanie/prochitat-kod-pulta-arduino

схема из ардуино нано, трех проводков и приемника 433,92 мгц выглядит так-

в ней записан этот код-

#include <avr/interrupt.h>
#define in  PD2
#define out PB5
unsigned long time = 0;
bool CheckValue(int base, int value)
{
  int x = base - value;
  return ((x >= 0)?(x < 200):(-x < 200));
}
unsigned long prevtime;
unsigned int lolen, hilen;
byte cameCounter = 0; 
uint16_t cameCode = 0; 
 
void setup()
{
  DDRB |=(1<<out);                            
  EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (CHANGE << ISC00); 
  EIMSK |= (1 << INT0);                                               
}
 
void loop() 
{
}
 
ISR(INT0_vect) 
  uint32_t  cm = micros();
  uint32_t cml = millis();
if (!(PIND&(1<<in)))         
{
  hilen = cm - prevtime;
if (CheckValue(320, hilen) && CheckValue(640, lolen)) 
{
  cameCode = (cameCode << 1) | 1;
  cameCounter++;
}
else if (CheckValue(640, hilen) && CheckValue(320, lolen)) 
{
  cameCode = (cameCode << 1) | 0;
  cameCounter++;
}
else cameCounter = 0;
}
else
  lolen = cm - prevtime;   
  prevtime = cm;
if (lolen > 1000 && (cameCounter == 24)) 
{
 cameCode = cameCode & 0xfff;
 cameCounter = 0;
}
if (cameCode == 1234) 
{
if(cml -  time>200) PINB = (1<<out);
  time = cml;  
  cameCode = 0;
}
}
работает отлично- нажимаю на пульте кнопку- загорается светодиод на 13 пине ардуино нано. при повторном нажатии гаснет. хочу управлять реле- мой пульт имеет 2 кнопки из которых всего одна открывает ворота на паркинге а вторая не используется. вот решил сделать включение света в прихожей (открывая ключами дверь нажимаем на кнопку и свет загорается) ну и практика программирования заодно. т.к использовать для этих целей ардуино нано нецелесообразно и габаритно решил перевести этот код на тини13 что в самый раз. соответственно прошиваю тини13, припаиваю вместо ардуины - не работает. кстати ваш последний код через раз но зажигает светодиод, но это так нестабильно что бывает дребезг
wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

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

1. Убедись, что ты программируешь для тиньки на максимальной частоте 9.6 МГц.

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

вот так:

void setup() {
  

}

void loop() {
static uint32_t old_us = micros();
uint32_t cur_us = micros();
static uint32_t mymillis=0;



if (cur_us - old_us > 1000)
  {
    mymillis++;
    old_us = cur_us;
  }
if (mymillis == 30000)
   {
    mymillis = 0;
    PINB = 1;
   }
}

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

если не получится - ничего страшного! что-нить придумаем.

4. ты не разместил фотографию с тинькой. Ты уверен, что не накосячил с пайкой там?

iopq
Offline
Зарегистрирован: 05.07.2016

скетч что то не мигает. даже в протеусе

на тинни мигает с частотой 1 раз в 30 сек

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

Я настаиваю на том, чтобы не использовать при общении со мной ссылки на тестирование  в Протеусе. и даже наименовние не использовать.

Только нормальное железо.

=============================

Этот скетч был ТОЛЬКО для тиньки!

Проверь на точность 30 сек. с секундомером, в каждой мобиле есть секундомер.

iopq
Offline
Зарегистрирован: 05.07.2016

понял. 

в железе на тинни13 мигает с вашим скетчем 1 раз в 30 сек. 

еще раз записал код-

#include <avr/interrupt.h>

unsigned long time = 0;
bool CheckValue(int base, int value)
     {
      int x = base - value;
      //return ((value == base) || ((value > base) && ((value - base) < 200)) || ((value < base) && ((base - value) < 200)));
      return ((x >= 0)?(x < 200):(-x < 200));
     }

unsigned long prevtime;
unsigned int lolen, hilen;
byte cameCounter = 0; 
uint16_t cameCode = 0; 


void setup()
{
 cli();

 DDRB |= (1 << 4); //третья!!! ножка- выход                          
 MCUCR =0x01;
 GIMSK = _BV(INT0);
 
 sei();
}

void loop() {
}

ISR(INT0_vect) 
  { 
  uint32_t  cm = micros();
  uint32_t cml = millis();

  if (!(PINB&(1<<1)))         
    {
    hilen = cm - prevtime;
    if (CheckValue(320, hilen) && CheckValue(640, lolen)) 
      {
      cameCode = (cameCode << 1) | 1;
      cameCounter++;
      }
    else if (CheckValue(640, hilen) && CheckValue(320, lolen)) 
      {
      cameCode = (cameCode << 1) | 0;
      cameCounter++;
      }
    else cameCounter = 0;
    }
  else
    lolen = cm - prevtime;   
  
  prevtime = cm;
  
  if (lolen > 1000 && (cameCounter == 24)) 
    {
    cameCode = cameCode & 0xfff;
    cameCounter = 0;
    }

  if (cameCode == 1234) 
    {
    if(cml -  time>200) PINB = (1<<4);
    time = cml;  
    cameCode = 0;
    }
}

частота 9,6 мгц. фотография-

не работает

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

а вариант для нано работает? так?

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

по таймингам из другой темы посчитай ТОЧНО среднее для хай и лоу. Я, все-таки, полагаю, что нужно поменять константы в твоем алгоритме.... для нанки с 16 МГц прокатывает, а для тиньки с 9.6Мгц - уже грубо получается.... попробуй подобрать:.  сделай 600 и 300 для начала.

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

iopq
Offline
Зарегистрирован: 05.07.2016

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

 

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

вместо 1000-100 и вместо 30000-3000

примерно в 2 раза чаще мигает нано 

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

ну попробуй на тиньке 300 тысяч раз по 100 мкс. Посмотри, что выйдет.

iopq
Offline
Зарегистрирован: 05.07.2016

wdrakula пишет:

ну попробуй на тиньке 300 тысяч раз по 100 мкс. Посмотри, что выйдет.

не совсем понял

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

iopq пишет:

wdrakula пишет:

ну попробуй на тиньке 300 тысяч раз по 100 мкс. Посмотри, что выйдет.

не совсем понял

void setup() {
  

}

void loop() {
static uint32_t old_us = micros();
uint32_t cur_us = micros();
static uint32_t mymillis=0;



if (cur_us - old_us > 100)
  {
    mymillis++;
    old_us = cur_us;
  }
if (mymillis == 300000)
   {
    mymillis = 0;
    PINB = 1;
   }
}

 

iopq
Offline
Зарегистрирован: 05.07.2016

1 минута

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

iopq пишет:

1 минута

это время горения?

тогда давай пробовать характерные времена твоего протокола:

100000 раз по 300 мкс и 50000 раз по 600 мкс.

и кинь ссылку на то ядро тиньки 13, которое ты используешь. Их много в сети. Я погляжу.

iopq
Offline
Зарегистрирован: 05.07.2016

wdrakula пишет:

iopq пишет:

1 минута

это время горения?

тогда давай пробовать характерные времена твоего протокола:

100000 раз по 300 мкс и 50000 раз по 600 мкс.

и кинь ссылку на то ядро тиньки 13, которое ты используешь. Их много в сети. Я погляжу.

горит минуту, потом не горит минуту. ядро скачал и переустановил отсюда последнее https://sourceforge.net/projects/ard-core13/files/

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

ладно. снова давай до завтра, и скажи, что вышло с 300 и 100000, и с 600 и 50000? Потому, как не может на нанке работать, а на тиньке нет!

На тиньке 9600 точность микрос - 27 мкс, много, но не страшно. Если что-то упирается в это - будем думать.

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

Если с утра "здоров" буду, то до мастерской добреду... с Б..жей помощью.

Чет меня заело, почему у тебя на нанке работает, а на тиньке нет.

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

....ладно - все умное - на завтра. бай.

DIVGENY
Offline
Зарегистрирован: 23.08.2016

    cameCode = cameCode & 0xfff;
    cameCounter = 0;
    }

  if (cameCode == 1234) 
    {
    if(cml -  time>200) PINB = (1<<0);
    time = cml;  
    cameCode = 0;
    }
}

    cameCode == 432

и почему тогда if (cameCode == 1234) для тиньки

я игрался в библиотеке RCSwitch длиной импульса 300->310->320->330->340, прием стабильный

iopq
Offline
Зарегистрирован: 05.07.2016

300-100000 - 28 сек

600-50000 - 28 сек

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

#define txPin 2
#define Te 320

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

void loop()
{
  SendCame(0b0011111001011000110110000);
}

void SendCameBit(byte b)
{
  delayMicroseconds(Te);
  if (!b) digitalWrite(txPin,HIGH);
  delayMicroseconds(Te);
  digitalWrite(txPin,HIGH);
  delayMicroseconds(Te);
  digitalWrite(txPin,LOW);
}

void SendCame(long Code)
{     
  for (byte i=25;i>0;i--){
  SendCameBit(bitRead(Code, i-1)); 
}
  delay(16);
}

DIVGENY пишет:

    cameCode = cameCode & 0xfff;
    cameCounter = 0;
    }

  if (cameCode == 1234) 
    {
    if(cml -  time>200) PINB = (1<<0);
    time = cml;  
    cameCode = 0;
    }
}

    cameCode == 432

и почему тогда if (cameCode == 1234) для тиньки

я игрался в библиотеке RCSwitch длиной импульса 300->310->320->330->340, прием стабильный

да я эмулятором посылаю что бы за пультом не бегать туда сюда и отправляю 1234

DIVGENY
Offline
Зарегистрирован: 23.08.2016

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

зачем в начале темы давать один код, потом другой. что подразумевается под словом эмулятор.?

или я что-то не пойму. как ты отправляешь 1234 - покажи..

iopq
Offline
Зарегистрирован: 05.07.2016

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

и есть рациональность- смысл в 328 меге если используется всего 2 пина? в конце концов никто же не кипятит 100 литров воды что бы выпить кружку чая

DIVGENY
Offline
Зарегистрирован: 23.08.2016

значит ты изменил старый бинарный код на новый с учетом инверсии в строке

cameCode = cameCode & 0xfff

 и как он выглядит

iopq
Offline
Зарегистрирован: 05.07.2016

DIVGENY пишет:

значит ты изменил старый бинарный код на новый с учетом инверсии в строке

cameCode = cameCode & 0xfff

 и как он выглядит

Я написал sendcame(1234);

DIVGENY
Offline
Зарегистрирован: 23.08.2016

1234 -10011010010 твой последний 0 программа воспринимает как начало задержки

про обработку этой строки явообще молчу

if (lolen > 1000 && (cameCounter == 24))

 

iopq
Offline
Зарегистрирован: 05.07.2016

DIVGENY пишет:

1234 -10011010010 твой последний 0 программа воспринимает как начало задержки

про обработку этой строки явообще молчу

if (lolen > 1000 && (cameCounter == 24))

 

что то не пойму - дело сейчас в пульте а не в тини? Странно но ведь я проверял - писал sendcame(432); и в порт приходило 432

 

сейчас все перепроверил-

#define txPin 2
#define Te 320

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

void loop()
{
  SendCame(432);
}

void SendCameBit(byte b)
{
  delayMicroseconds(Te);
  if (!b) digitalWrite(txPin,HIGH);
  delayMicroseconds(Te);
  digitalWrite(txPin,HIGH);
  delayMicroseconds(Te);
  digitalWrite(txPin,LOW);
}

void SendCame(long Code)
{     
  for (byte i=25;i>0;i--){
  SendCameBit(bitRead(Code, i-1)); 
}
  delay(16);
}

вот этот код выбрасывает именно 432 и никак иначе. а так - SendCame(1234); выбрасывается именно 1234

 

DIVGENY
Offline
Зарегистрирован: 23.08.2016

я проверял пульт на меге 328

код передатчика

// код передатчика
#define txPin 10
#define inPin 7
#define Te 320  // takt



void setup()
{
  pinMode(txPin, OUTPUT);
  pinMode(inPin, INPUT);
}

void loop()
{
  SendCame(0b1100000110100111001001111);
}

void SendCameBit(byte b)
{                             
  if (b) {digitalWrite(txPin,1); delayMicroseconds(2*Te);}   //если 1, выставляем высокий уровень
                                                             // и ждем 2 takt
                                                                 
  if (!b) {digitalWrite(txPin,0); delayMicroseconds(Te);     // если 0 устанавливаем низкий уровень на 1 takt
            digitalWrite(txPin,1);delayMicroseconds(Te);}    // устанавливаем высокий уровень на takt
            
  digitalWrite(txPin,0);                                     // такт между битами в нуле
  delayMicroseconds(Te);                                     // равен 1 takt

}

void SendCame(long Code)
{     
  for (byte i=25;i>0;i--){
  SendCameBit(bitRead(Code, i-1)); 
    }
    Pilot_time();
}    
 void Pilot_time()                 
{  
  delayMicroseconds(50*Te);                                 // пилотный период
  if (digitalRead(inPin) == HIGH) Pilot_time();

и код приемника на меге 328 из этого сообщения

с дописаным выводом в монитор значением , получилось 432

просто верни старые значения кода .....которые в конце прошлой темы и в начале этой

iopq
Offline
Зарегистрирован: 05.07.2016

Вы не поверите но на 328 меге  и у меня работают оба пульта (естественно меняю условия ). На Тини работать не хочет ни один пульт. Кстати попробую записать в Тини код передатчика. Интересно что получится

DIVGENY
Offline
Зарегистрирован: 23.08.2016

там кнопка на 7pin ардуины или 13 нога контроллера  повешена , притянута к + через 10к и замыкает на землю

нажата - код идет, отпущена - вечный


    Pilot_time();
}    
 void Pilot_time()                 
{  
  delayMicroseconds(50*Te);                                 // пилотный период
  if (digitalRead(inPin) == HIGH) Pilot_time();
DIVGENY
Offline
Зарегистрирован: 23.08.2016

 анализатором Logic 1.2.10 паказавает практически тоже из Вашего сообщения

 + - 50 милисекунд

iopq
Offline
Зарегистрирован: 05.07.2016

DIVGENY пишет:

 анализатором Logic 1.2.10 паказавает практически тоже из Вашего сообщения

 + - 50 милисекунд

а у вас тини13 нет случайно? Может у вас заработает?

DIVGENY
Offline
Зарегистрирован: 23.08.2016

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

и мои познания далеко не ушли

 

DIVGENY
Offline
Зарегистрирован: 23.08.2016

 я думаю, может не стоит оперировать с & 0xfff, мне не ясно, куда денется старшая единичка после сложения. может кто подскажет...? просто получается

SendCame(0b1100000110100111001001111) = SendCame (432)

так как на выходе и я и ты получили 432

 

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

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

1. Видео, как оно работает.

2. скетч для тиньки.

#include <avr/interrupt.h>

#define tous   (256000000UL/F_CPU) 
#define toms   (F_CPU/256000UL)
//#define tous    27
//#define toms    37 
#define DELTA    200
#define loTime   300


extern volatile unsigned long ovrf;

unsigned long time = 0;
bool CheckValue(int base, int value)
     {
      int x = base - value;
      //return ((value == base) || ((value > base) && ((value - base) < 200)) || ((value < base) && ((base - value) < 200)));
      return ((x >= 0)?(x < DELTA/tous):(-x < DELTA/tous));
     }

unsigned long prevtime=0;
unsigned int lolen=0; 
unsigned int hilen=0;
byte cameCounter = 0; 
uint32_t cameCode = 0; 



void setup()
{
 cli();

 DDRB |= (1 << PB0); //шестая ножка- выход                          
 MCUCR =0x01;
 GIMSK = _BV(INT0);
 
 sei();
}

void loop() {
}


ISR(INT0_vect) 
  { 
  uint32_t  cm = ovrf;
  uint32_t cml = cm;

  if (!(PINB&(1<<1)))         
    {
    hilen = cm - prevtime;
    if (CheckValue(loTime/tous, hilen) && CheckValue(2*loTime/tous, lolen)) 
      {
      cameCode = (cameCode << 1) | 1;
      cameCounter++;
      }
    else if (CheckValue(2*loTime/tous, hilen) && CheckValue(loTime/tous, lolen)) 
      {
      cameCode = (cameCode << 1) | 0;
      cameCounter++;
      }
    else cameCounter = 0;
    }
  else
    lolen = cm - prevtime;   
  
  prevtime = cm;
  
  if (lolen > 1000/tous && (cameCounter == 24)) 
    {
    cameCode = cameCode & 0xfff;
 
    cameCounter = 0;
    }

  if (cameCode == 1234) 
 
    {
    if(cml -  time>200*toms) PINB = (1<<0);
    time = cml;  
    cameCode = 0;
    }
}

3. код для передатчика на леонарде. это твой код, я не вмешивался, думая, что ты адекватно воспроизвел свой пульт.

#define txPin 12
#define Te 320

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

void loop()
{
  SendCame(1234ul);
  delay(1000);
}

void SendCameBit(byte b)
{
  delayMicroseconds(Te);
  if (!b) digitalWrite(txPin,HIGH);
  delayMicroseconds(Te);
  digitalWrite(txPin,HIGH);
  delayMicroseconds(Te);
  digitalWrite(txPin,LOW);
}

void SendCame(unsigned long Code)
{     
  for (byte i=25;i>0;i--){
  SendCameBit(bitRead(Code, i-1)); 
}
  delay(16);
}

 

iopq
Offline
Зарегистрирован: 05.07.2016

Добрый вечер. это работает. спасибо. а что же у нас неправильно было? я заметил вы добавили пару констант?

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

Не ломай голову. Разберешься -хорошо, нет так нет. Это же не твоя профессия.

iopq
Offline
Зарегистрирован: 05.07.2016

wdrakula пишет:
Не ломай голову. Разберешься -хорошо, нет так нет. Это же не твоя профессия.

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

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

Это потому, что я микрос и миллис заменил на внешнюю переменную - счетчик циклов таймера ovrf. Поэтому линкер выкинул математику - умножение и деление.
Стало понятнее? Я с телефона из машины. Неудобно. Позже или завтра. Ты все вопросы собери в кучу. Я отвечу.

iopq
Offline
Зарегистрирован: 05.07.2016
вопросы-
#define tous   (256000000UL/F_CPU) 
#define toms   (F_CPU/256000UL)
extern volatile unsigned long ovrf;
F_CPU - это как я понял наши 9,6 мгц? эту константу мы задаем фьюзами? 
256000000 - почему именно это число?
ovrf это наверное как раз и есть счетчик циклов таймера (регистр?) о нем в гугле совсем нет информации
wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Ну что? Утро красит нежным светом...? ;) Всем бобра!

Отвечаю:

1. F_CPU это константа, задаваемая компилятору. Нет, к фьюзам не имеет прямого отношения. И фьюзы и эта константа задаются средой.

2. 256000000 это 256 миллионов ;), цикл таймера - 256 циклов тактовой частоты процессора. "tous" читается как "в микросекунды" = сколько микросекунд в единице ovrf. по простому это 256тактов / 9.6МГц = 27 мкс. "toms"  - в миллисекунды и равна 37 тикам на миллисекунду.

3. ovrf - это счетчик полных оборотов таймера конкретно и только в тиньке! Подробности смотри в файле  wiring.c в своем ядре.

-----

микрос и миллис используют  ovrf * 27 для микрос и ovrf / 37  для миллис. Отсюда нужда в длинной математике.

Я не использовал в программе делений и умножений, только НА ЭТАПЕ КОМПИЛЯЦИИ, для числовых констант, то есть в программе нет нужды добавлять функции для умножения и деления, вот код и похудел.

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