Во всю тему не вникал.
Получение по 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;
}