Hi everyone,
I'd like to share my sketch for flashing a led in raw mode with attiny 85.
First of all, I'm a newbie and I don't pretend this to be elegant or efficient, but it works and I realized by myself! Everybody here knows what I mean: I'm proud of it!
I got IRTinyTX.h library from here http://tetalab.org/blog/librairie-ir-nec-pour-attiny85 .
This library has to be modified adding the part related to sendRaw function in IRTinyTX.h and IRTinyTX.cpp copying from IRremote.h and IRremote.cpp. From original library I also removed RX files (IRTinyRX.h IRTinyRXint.h and relevant cpp files) that are not used and therefore create some errors while compiling.
Basically your IRTinyTX.h should be like this
#ifndef IRTinyTX_h
#define IRTinyTX_h
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#define IRLED PB1 // (Used as OC0B) - pin 6 on ATtiny85
// Ensures that the compiler knows it's running at 16MHz, if it's not defined in the makefile or not using the Arduino IDE
//#ifndef F_CPU
#define F_CPU 16000000UL // 16 MHz
//#define F_CPU 8000000UL // 8 MHz
//#endif
// pulse parameters in usec - I tweaked the values for my setup
#define PANASONIC_HDR_MARK 3502
#define PANASONIC_HDR_SPACE 1750
#define PANASONIC_BIT_MARK 502-50
#define PANASONIC_ONE_SPACE 1244
#define PANASONIC_ZERO_SPACE 400+100
#define JVC_HDR_MARK 8000
#define JVC_HDR_SPACE 4000
#define JVC_BIT_MARK 600
#define JVC_ONE_SPACE 1600
#define JVC_ZERO_SPACE 550
#define PANASONIC_BITS 48
#define TOPBIT 0x80000000
#define NEC_HDR_MARK 9000
#define NEC_HDR_SPACE 4500
#define NEC_BIT_MARK 560
#define NEC_ONE_SPACE 1600
#define NEC_ZERO_SPACE 560
#define NEC_RPT_SPACE 2250
class IRsend
{
public:
IRsend() {}
void sendJVC(uint32_t data, uint8_t nbits, uint8_t repeat); // *Note instead of sending the REPEAT constant if you want the JVC repeat signal sent, send the original code value and change the repeat argument from 0 to 1. JVC protocol repeats by skipping the header NOT by sending a separate code value like NEC does.
void sendNEC(unsigned long data, int nbits);
void enableIROut(uint8_t khz);
void sendRaw(unsigned int buf[], int len, int hz);
private:
void mark(int16_t usec);
void space(int16_t usec);
};
#define USECPERTICK 50 // microseconds per clock interrupt tick
#define RAWBUF 100 // Length of raw duration buffer
// Marks tend to be 100us too long, and spaces 100us too short
// when received due to sensor lag.
#define MARK_EXCESS 100
#endif
and this should be your IRTinyTX.cpp
#include "IRTinyTX.h"
void IRsend::sendNEC(unsigned long data, int nbits)
{
enableIROut(38);
mark(NEC_HDR_MARK);
space(NEC_HDR_SPACE);
for (int i = 0; i < nbits; i++) {
if (data & TOPBIT) {
mark(NEC_BIT_MARK);
space(NEC_ONE_SPACE);
}
else {
mark(NEC_BIT_MARK);
space(NEC_ZERO_SPACE);
}
data <<= 1;
}
mark(NEC_BIT_MARK);
space(0);
}
void IRsend::sendJVC(uint32_t data, uint8_t nbits, uint8_t repeat)
{
//enableIROut(38);
data = data << (32 - nbits);
if (!repeat){
mark(JVC_HDR_MARK);
space(JVC_HDR_SPACE);
}
for (int i = 0; i < nbits; i++) {
if (data & TOPBIT) {
mark(JVC_BIT_MARK);
space(JVC_ONE_SPACE);
}
else {
mark(JVC_BIT_MARK);
space(JVC_ZERO_SPACE);
}
data <<= 1;
}
mark(JVC_BIT_MARK);
space(0); //Turn IR LED off
}
void IRsend::sendRaw(unsigned int buf[], int len, int hz)
{
enableIROut(hz);
for (int i = 0; i < len; i++) {
if (i & 1) {
space(buf[i]);
}
else {
mark(buf[i]);
}
}
space(0); // Just to be sure
}
void IRsend::mark(int16_t time) {
// Sends an IR mark for the specified number of microseconds.
// The mark output is modulated at the PWM frequency.
// Clear OC0A/OC0B on Compare Match when up-counting.
// Set OC0A/OC0B on Compare Match when down-counting.
TCCR0A |= _BV(COM0B1); // Enable pin 6 (PB1) PWM output
delayMicroseconds(time);
}
/* Leave pin off for time (given in microseconds) */
void IRsend::space(int16_t time) {
// Sends an IR space for the specified number of microseconds.
// A space is no output, so the PWM output is disabled.
// Normal port operation, OC0A/OC0B disconnected.
TCCR0A &= ~(_BV(COM0B1)); // Disable pin 6 (PB1) PWM output
delayMicroseconds(time);
}
void IRsend::enableIROut(uint8_t khz) {
// Enables IR output. The khz value controls the modulation frequency in kilohertz.
// The IR output will be on pin 6 (OC0B).
// This routine is designed for 36-40KHz; if you use it for other values, it's up to you
// to make sure it gives reasonable results. (Watch out for overflow / underflow / rounding.)
// TIMER0 is used in phase-correct PWM mode, with OCR0A controlling the frequency and OCR0B
// controlling the duty cycle.
// There is no prescaling, so the output frequency is 16MHz / (2 * OCR0A)
// To turn the output on and off, we leave the PWM running, but connect and disconnect the output pin.
// A few hours staring at the ATmega documentation and this will all make sense.
// See my Secrets of Arduino PWM at http://arcfn.com/2009/07/secrets-of-arduino-pwm.html for details.
DDRB |= _BV(IRLED); // Set as output
PORTB &= ~(_BV(IRLED)); // When not sending PWM, we want it low
// Normal port operation, OC0A/OC0B disconnected
// COM0A = 00: disconnect OC0A
// COM0B = 00: disconnect OC0B; to send signal set to 10: OC0B non-inverted
// WGM0 = 101: phase-correct PWM with OCR0A as top
// CS0 = 000: no prescaling
TCCR0A = _BV(WGM00);
TCCR0B = _BV(WGM02) | _BV(CS00);
// The top value for the timer. The modulation frequency will be SYSCLOCK / 2 / OCR0A.
OCR0A = F_CPU / 2 / khz / 1000;
OCR0B = OCR0A / 3; // 33% duty cycle
}
Notice that F_CPU is set to 16 Mhz. In fact, I got it worked flashing the bootloader Attiny 85 @ 16 Mhz internal PPL.
I have to power on an AC when the temperature increases above 26 °C and power off when decreases below 24°C.
Here is the sketch
#include <IRTinyTX.h>
float temp;
int tempPin = 3;
int on_off = 0;
unsigned int rawCodes[] = {8850, 4500, 600, 1650, 600, 1650, 600, 550, 600, 600, 550, 550, 600, 550, 600, 550, 600, 1700, 550, 550, 600, 1650, 600, 1650, 650, 550, 600, 550, 600, 550, 600, 550, 600, 550, 600, 550, 600, 550, 600, 1650, 600, 550, 650, 500, 600, 550, 600, 550, 600, 600, 600, 500, 650, 1650, 600, 500, 650, 550, 600, 550, 600, 550, 600, 1650, 600, 550, 600, 550, 600, 600, 550, 550, 600, 600, 600, 550, 600, 500, 600, 550, 600, 600, 600, 550, 600, 550, 600, 550, 600, 550, 600, 550, 600, 550, 600, 550, 600, 550, 600};
IRsend irsend;
void setup()
{
}
void loop()
{
temp = analogRead(tempPin);
temp = temp * 0.48828125;
if (temp > 26.00 && on_off == 0) {
irsend.sendRaw(rawCodes, 99, 38);
on_off = 1;
}
else if (temp < 24.00 && on_off == 1) {
irsend.sendRaw(rawCodes, 99, 38);
on_off = 0;
}
delay(5000);
}
I'm eager to read your thoughts !