Attiny85 и прерывание библиотеки RCSwitch.h

Добрый день. Делаю приемник кода пультов на ATtuny85 и выводом на OLED дисплей. Использую библиотеки RCSwitch.h и Tiny4kOLED.h. По отдельности они работают, но пин РВ2 - SDA используется и для прерывания в приемнике библиотеки RCSwitch.
mySwitch.enableReceive(0); // Receiver on interrupt 0 => that is pin #2
Хочу прерывания для RCSwitch переназначить на пин РВ1
Читал и здесь и здесь
Понял, что надо

GIMSK=1<<PCIE; PCMSK=1<<PCINT1; // обработчик прерывания:

ISR (PCINT1_vect){// подпрограмма обслуживания прерываний
}

Как заставитьmySwitch.enableReceive работать по прерыванию PCINT1?

#include <RCSwitch.h>

#define LED  PB0 

RCSwitch mySwitch = RCSwitch();

void pin_change_interrupt(){
    GIMSK|= (1<<PCIE);
    PCMSK|= (1<<PCINT1);
}

void setup(){ 
  
//  pin_change_interrupt();
// ISR (PCINT1_vect){// подпрограмма обслуживания прерываний
//}
         
  mySwitch.enableReceive(0);  // Receiver on interrupt 0 => that is pin #2
  
  pinMode(LED,OUTPUT);
  digitalWrite(LED,HIGH);
  delay(100);
  digitalWrite(LED,LOW);
}

void loop(){
   if(mySwitch.available()){
      digitalWrite(LED,HIGH);
      mySwitch.resetAvailable();
      delay(100);
      } 
   else {digitalWrite(LED,LOW);}
}

Как заставитьmySwitch.enableReceive работать по прерыванию PCINT1?

Надо идти в библиотеку и править код,
заменить вызовы attachInterrupt и detachInterrupt на установку флага разрешения прерывания и сброс флага разрешения прерывания PCIE.

2 лайка

“Как пройти в библиотеку?” У меня тини45 вроде безо всяких прерываний трудится. Ну да, удалил #define RCSwitchDisableReceiving, само собой, и ничё.

скачать правильную библиотеку не пробовали, на ней всё компилируется и под 0 прерывание и под первое

А потом окажется, что один хрен в память всё не влезет ибо только шрифт почти всё сожрёт. :grinning:

Тоже закоментировал

, но как без прерываний? А как же строка в приемнике

mySwitch.enableReceive(0); // Receiver on interrupt 0 => that is pin #2

Это работа через прерывание INT0.

Извиняюсь, а какая правильная библиотека? И чем RCSwitch.h не правильная.

С Tiny4kOLED.h всё очень даже влезает, на краяняк есть TinyOzOled

где это скомпилируется видимо, а еще лучше что и работать будет )))

mySwitch.enableReceive(1);
1 лайк

Да, точно. Запамятовал.(

  rc.enableReceive(digitalPinToInterrupt(RX));

А вот это дело. Спасибо. Получается , что если я сменю пин прерывания на РВ1

GIMSK=1<<PCIE; PCMSK=1<<PCINT1; 

Мне достаточно строки

mySwitch.enableReceive(digitalPinToInterrupt(РВ1))

А вызов ISR (PCINT1_vect) не нужен?

Увы такой вариант тоже не работает.

[code]
#include <RCSwitch.h>

#define LED  PB0 

RCSwitch mySwitch = RCSwitch();

void pin_change_interrupt(){
    GIMSK|= (1<<PCIE);
    PCMSK|= (1<<PCINT1);
}

void setup(){ 
  
  pin_change_interrupt();
 
         
  mySwitch.enableReceive(digitalPinToInterrupt(1));  // Receiver on interrupt pin PB1
  
  pinMode(LED,OUTPUT);
  digitalWrite(LED,HIGH);
  delay(100);
  digitalWrite(LED,LOW);
}

void loop(){
   if(mySwitch.available()){
      digitalWrite(LED,HIGH);
      mySwitch.resetAvailable();
      delay(100);
      } 
   else {digitalWrite(LED,LOW);}
}
[/code]

Как я понимаю, библиотека работает с INT только. А у тини85 только INT0 - всё.

1 лайк

Не дело. Про это я Вам написал в самом первом ответе. Потом заметил, что это тинька и удалил ответ, т.к. был неправ. Это не для PCINT1 а для INT1, а у тиньки его нету. - так можно было с 328-ой делать.

1 лайк

Во всю тему не вникал.
Получение по RCSwitch температуры с внешнего датчика и отображение ее на дисплее.
Attiny85

Спойлер
#include <TinyOzOLED.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <RCSwitch.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 - SDA
#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
#define PB1_OUT sbi(DDRB,PB1)
#define PB1_IN cbi(DDRB,PB1)
#define PB1_HIGH sbi(PORTB,PB1)
#define PB1_LOW cbi(PORTB,PB1)
// PB2 pin 7 - SCL
#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 - DS18B20
#define DS_BIT PB3
#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 - RC RxD
#define PB4_OUT sbi(DDRB,PB4)
#define PB4_IN cbi(DDRB,PB4)
#define PB4_HIGH sbi(PORTB,PB4)
#define PB4_LOW cbi(PORTB,PB4)
#define PB4_READ bitRead(PINB,PB4)

unsigned long showBufTime = 0;
boolean inRX = false;

byte roomTemp = 0;

boolean flTempPart1 = false;
unsigned long showTempTime = 177000;
unsigned long getTempTime;
unsigned long showStreetTemp = 0;

RCSwitch mySwitch = RCSwitch();

unsigned long lu = 0; // last time get street temp
byte streettemp = 99; // street temp 0..60
word mas_str_temp[10];
byte med_str_pos = 0;
byte med_str_cnt = 0;
boolean minus_str_temp = false;

void setup () {
  OzOled.init();
  OzOled.setNormalDisplay();
  OzOled.setPageMode();
  OzOled.sendCommand(0xA1);
  OzOled.sendCommand(0xC8);
  // -
  PB1_OUT; PB1_LOW;
  PB4_IN; PB4_HIGH;
  // -
  //mySwitch.enableReceive(0);
  // -
  sbi(GIMSK, PCIE);
  sbi(PCMSK, PCINT4);
  //-
  OzOled.setPowerOn();
  OzOled.printChar('S', 5, 5);
}

void loop () {
  unsigned long currMil = millis();
  if ((currMil - showTempTime) >= 180007) {
    showTempTime = currMil;
    GetTempPart1();
    flTempPart1 = true;
    getTempTime = currMil;
  }
  if (((currMil - getTempTime) >= 1200) && (flTempPart1)) {
    getTempTime = currMil;
    flTempPart1 = false;
    roomTemp = GetTempPart2() / 100;
    roomTemp = constrain(roomTemp, 0, 99);
  }
  // receive street temp
  if (mySwitch.available()) {
    unsigned long receivedCode =  mySwitch.getReceivedValue();
    mySwitch.resetAvailable();
    if ((receivedCode >= 11500UL) && (receivedCode <= 14750UL)) {
      receivedCode -= 11500;
      if (((receivedCode >= 2000UL) && (receivedCode <= 2600UL)) || ((receivedCode >= 0UL) && (receivedCode <= 400UL))) {
        if ((receivedCode <= 400UL)) {
          receivedCode = 2000UL - receivedCode;
        }
        lu = millis();
        // correct temp
        if (receivedCode <= 1900UL) {
          receivedCode -= 12UL; // 1.2 degree
        } else {
          if (receivedCode <= 1950UL) {
            receivedCode -= 8UL; // 0.8 degree
          }
          else {
            if (receivedCode <= 1999UL) {
              receivedCode -= 5UL; // 0.5 degree
            }
          }
        }
        // --
        mas_str_temp[med_str_pos] = (word)(receivedCode);
        if ((++med_str_pos) >= 10) {
          med_str_pos = 0;
        }
        if ((++med_str_cnt) >= 10) {
          med_str_cnt = 10;
        }
        word sum_temp = 0;
        for (int i = 0; i < med_str_cnt; ++i) {
          sum_temp += mas_str_temp[i];
        }
        sum_temp /= med_str_cnt;
        if (sum_temp < 2000) {
          minus_str_temp = true;
          sum_temp = 2000 - sum_temp;
        } else {
          minus_str_temp = false;
          sum_temp -= 2000;
        }
        sum_temp /= 10;
        streettemp = (byte)(sum_temp);
      }
    }
  }
  // show street temp
  if ((currMil - showStreetTemp) >= 10000) {
    showStreetTemp = currMil;
    if ((currMil - lu) < 5940000UL) {
      if (minus_str_temp) {
        OzOled.printChar('_', 2, 2);
        OzOled.printChar('_', 3, 2);
        OzOled.printChar('_', 4, 2);
      } else {
        OzOled.printChar(' ', 2, 2);
        OzOled.printChar(' ', 3, 2);
        OzOled.printChar(' ', 4, 2);
      }
      char str[3];
      str[0] = '0' + streettemp / 10;
      str[1] = '0' + streettemp % 10;
      str[2] = 0;
      OzOled.printBigNumber(str, 5, 0);
      OzOled.printChar('`', 14, 0);
      OzOled.printChar('C', 15, 0);
      byte mm = ((currMil - lu) / 1000 / 60);
      mm = constrain(mm, 0, 99);
      OzOled.printChar('0' + mm / 10, 0, 6);
      OzOled.printChar('0' + mm % 10, 1, 6);
      OzOled.printChar('m', 2, 6);
    } else {
      OzOled.clearDisplay();
    }
    // show inttemp
    if ((roomTemp > 10) && (roomTemp < 45)) {
      OzOled.printChar('0' + roomTemp / 10, 14, 6);
      OzOled.printChar('0' + roomTemp % 10, 15, 6);
    }
  }
  //OzOled.setPowerOff();
}

ISR(PCINT0_vect) {
  mySwitch.handleInterrupt();
}

// OneWire функции:

void OneWireReset()
{
  PORTB &= ~_BV(DS_BIT);
  DDRB |= _BV(DS_BIT);
  _delay_us(500);
  DDRB &= ~_BV(DS_BIT);
  _delay_us(500);
}

void OneWireOutByte(uint8_t d)
{
  uint8_t n;
  for (n = 8; n != 0; n--)
  {
    if ((d & 0x01) == 1)
    {
      PORTB &= ~_BV(DS_BIT);
      DDRB |= _BV(DS_BIT);
      _delay_us(5);
      DDRB &= ~_BV(DS_BIT);
      _delay_us(60);
    }
    else
    {
      PORTB &= ~_BV(DS_BIT);
      DDRB |= _BV(DS_BIT);
      _delay_us(60);
      DDRB &= ~_BV(DS_BIT);
    }
    d = d >> 1;
  }
}

uint8_t OneWireInByte()
{
  uint8_t d, n, b;
  for (n = 0; n < 8; n++)
  {
    PORTB &= ~_BV(DS_BIT);
    DDRB |= _BV(DS_BIT);
    _delay_us(5);
    DDRB &= ~_BV(DS_BIT);
    _delay_us(5);
    b = ((PINB & _BV(DS_BIT)) != 0);
    _delay_us(50);
    d = (d >> 1) | (b << 7);
  }
  return (d);
}

void GetTempPart1() {
  OneWireReset();
  OneWireOutByte(0xcc);
  OneWireOutByte(0x44);
  PORTB |= _BV(DS_BIT);
  DDRB |= _BV(DS_BIT);
}

word GetTempPart2() {
  uint8_t DSdata[2];
  DDRB &= ~_BV(DS_BIT);
  PORTB &= ~_BV(DS_BIT);
  OneWireReset();
  OneWireOutByte(0xcc);
  OneWireOutByte(0xbe);
  DSdata[0] = OneWireInByte();
  DSdata[1] = OneWireInByte();
  word TReading = (word)(DSdata[1] << 8) + DSdata[0];
  if ((word)(TReading & 0x8000) == (word)(0x8000)) {
    TReading = (~TReading) + (word)1;
    TReading = (((word)6 * TReading) + TReading / (word)4) / (word)10;
  } else {
    TReading = (((word)6 * TReading) + TReading / (word)4) / (word)10 + (word)2000;
  }
  return TReading;
}
2 лайка

Спасибо конечно, но это сложно для меня.

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

начните тогда с попроще МК, к которому все библиотеки без костылей сразу подходят.

1 лайк

для начала вы бы выложили откуда берёте библиотеку, может она уже понимает PCINT

1 лайк

Такие скетчи надо в теме 1001 применение attiny85 выкладывать )))

они там есть.

два ковида (возможно три) не прошли даром, иногда открываю свои комментарии и дивлюсь, я ли это писал )))

У меня работает приемник пультов на ардуинке. Но использовать её для этих целей расточительство. Поэтому решил использовать ATtiny85. Но столкнулся, что с тем, что SCL I2C и INT0 висят на одном пине PB2. И их надо как то развести.
Сейчас читаю про TinyRF. Может на ней получится.

Отсюда

Сочувствую.