Raw IR Code Transmission - ATTiny13a Inaccurate Oscillator?

Hello all, I’ve been doing Arduino projects for a while now, and I’ve just started using ATTiny microchips.
A project I’ve been working on is a simple IR code transmitter en route to a more useful application within my projects. I’ve started with trying to control TVs.

My work is based off of AdaFruit’s IR Sensor tutorial here. All ATTiny programming is done using Arduino as ISP.

I gathered the code for a “Nakamichi” TV remote power button. Uploading this code to an Arduino Mega 2560, I made it turn on and off successfully.

//#include "avr/eeprom.h" //I'm not sure if this is needed
#include "avr/pgmspace.h"
 
int IRledPin = 4;    // LED connected to digital pin 4

int tvONsignal[] PROGMEM = {
// ON, OFF (in 10's of microseconds)
316, 272,
74, 120,
74, 122,
74, 124,
72, 124,
70, 124,
72, 124,
72, 220,
70, 126,
72, 126,
70, 124,
72, 124,
70, 124,
72, 222,
68, 126,
70, 224,
62, 232,
60, 380,
58, 2236,
296, 292,
50, 146,
48, 146,
52, 146,
50, 146,
48, 146,
50, 146,
50, 242,
50, 146,
52, 146,
48, 146,
48, 148,
48, 146,
52, 242,
48, 146,
52, 242,
48, 244,
50, 390,
50, 0
};

int ONcodeLength = sizeof(tvONsignal)/(2*sizeof(int));

// The setup() method runs once, when the sketch starts
 
void setup()   {                
//  Serial.begin(9600);
  // initialize the IR digital pin as an output:
  pinMode(IRledPin, OUTPUT);
}
 
void loop()                     
{
//  Serial.println("Sending IR signal");
 
  SendTVONCode_P();
 
  delay(3*1000);  // wait three seconds (3 seconds * 1000 milliseconds)
}
 
// This procedure sends a 38KHz pulse to the IRledPin 
// for a certain # of microseconds. We'll use this whenever we need to send codes
void pulseIR(int microsecs) {
  // we'll count down from the number of microseconds we are told to wait
 
  //cli();  // this turns off any background interrupts
 
  while (microsecs > 0) {
    // 38 kHz is about 13 microseconds high and 13 microseconds low
   digitalWrite(IRledPin, HIGH);  // this takes about 3 microseconds to happen
   delayMicroseconds(10);         // hang out for 10 microseconds, you can also change this to 9 if its not working
   digitalWrite(IRledPin, LOW);   // this also takes about 3 microseconds
   delayMicroseconds(10);         // hang out for 10 microseconds, you can also change this to 9 if its not working
 
   // so 26 microseconds altogether
   microsecs -= 26;
  }
 
  //sei();  // this turns them back on;
}
 void SendTVONCode_P()
 {
   // All the delays are multiplied by 10 because the array values represent delays in 10's of microseconds

     for (int i = 0; i < ONcodeLength; i++)
     {
      pulseIR(10*pgm_read_word(&tvONsignal[2*i]));
      delayMicroseconds(10*pgm_read_word(&tvONsignal[2*i + 1]));
     }
     delay(65); // delay and send code again
     for (int i = 0; i < ONcodeLength; i++)
     {
      pulseIR(10*pgm_read_word(&tvONsignal[2*i]));
      delayMicroseconds(10*pgm_read_word(&tvONsignal[2*i + 1]));
     }
 }

As you can see, I used PROGMEM to try to save RAM, especially when using a smaller ATTiny13a. I also made a for-loop to cycle through the pulses and delays stored in an array instead of explicitly flashing each one directly. This saved space (memory overflow before), and helped with compatibility with other controls. I also didn’t turn off background interrupts (I tried before and it didn’t do anything).

When uploading this same code to my ATTiny13a, however, the two blinks of code transmission are much faster. Perhaps half of the time it took my Arduino Mega 2560 to transmit the same code. I tried it on my TV anyway, and it didn’t work.

I tried to figure out what was wrong with it for a long time. Almost 3 days of nonstop Google-ing, and I’ve narrowed it down, but haven’t gotten it working yet. First, I made sure that accessing the codes from program memory was going successfully, I did this by blinking an LED a certain number of times (from the code I was trying to transmit) divided by 10. For example, I made the LED blink a number of times equal to pgm_read_word(&tvONcode[0])/10. This is 316/10 = 31 times (integer division), and indeed it was accessing the array as expected, even after trying several values.

Since I suspected the internal clock for the ATTiny13a wasn’t operating the same as the Arduino Mega 2560 (from the faster blinking), I wanted to test it in another way to make sure it wasn’t my code that was buggy. I uploaded the basic blink sketch to see if the interval was indeed 1 second exactly. Lo and behold, it was not. It was about 1.25 seconds (hand-timed by me). I made sure it was accurate by blinking at 10 second intervals, and I got about 12.6 seconds.

To try to fix it, I tried multiplying the delays by 1/1.26, but that didn’t work either. It also took a lot more space, since non-integers are stored as floating point numbers, and it ended up overflowing.

My attempts to fix this include changing the boards.txt file in the ATTiny13a core files.

###########################################################################
attiny13int.name=Attiny13 @ 128 KHz (internal watchdog oscillator)
attiny13int.upload.using=arduino:arduinoisp
attiny13int.upload.maximum_size=1024
attiny13int.upload.speed=250 # important for not losing connection to a slow processor
attiny13int.bootloader.low_fuses=0x7B
attiny13int.bootloader.high_fuses=0xFF
attiny13int.bootloader.unlock_bits=0x3F
attiny13int.bootloader.lock_bits=0x3F
attiny13int.build.mcu=attiny13
attiny13int.build.f_cpu=128000
attiny13int.build.core=core13

###############################################################

attiny13at4.name=ATtiny13 @ 4.8MHz (internal 4.8 MHz clock)
attiny13at4.upload.using=arduino:arduinoisp
attiny13at4.bootloader.low_fuses=0x69
attiny13at4.bootloader.high_fuses=0xff
attiny13at4.upload.maximum_size=1024
attiny13at4.build.mcu=attiny13
attiny13at4.build.f_cpu=600000
attiny13at4.build.core=core13
###############################################################

attiny13.name=ATtiny13 @ 9.6MHz (interne 9.6 MHz clock)
attiny13.upload.using=arduino:arduinoisp
attiny13.bootloader.low_fuses=0x7a
attiny13.bootloader.high_fuses=0xff
attiny13.upload.maximum_size=1024
attiny13.build.mcu=attiny13
attiny13.build.f_cpu=9600000
attiny13.build.core=core13
###############################################################

I tried 128kHz, 600kHz, 1MHz, 1.2MHz, 4MHz, 4.8MHz, 8MHz, 9.6MHz, 10MHz, 12MHz, and 16MHz by changing the number in the last block from 9600000 to each one of the frequencies I wanted to try. This didn’t work. I also tried changing to each frequency AND burning the bootloader then testing my code, and still no luck. Each time, the blinking speed would change. Maybe I have to reprogram the fuse bits (which might change the hex numbers in the board.txt file), but I don’t know how to safely do any of that. I have nothing left.

So, if anyone has any ideas, please help me out and I will be very thankful. If anyone has any questions, just post here and I will reply as soon as possible.

PS: Sorry for the long post; I just wanted to be very thorough.

Use delay_us instead of delayMicroseconds.

Use delay_ms instead of delay.

Start with the highest possible processor speed (9.6MHz).

Please let us know if that works.

Thanks for your reply, Coding Badly.

I tried changing all the delayMicroseconds() to _delay_us(), and the delay() to _delay_ms() after adding the <util/delay.h> library.

I tried using my Arduino Mega 2560 for the new sketch, and it still worked on my TV. It actually started flashing a lot faster than before. It still worked just fine for turning my TV on and off.

However, when trying to upload the sketch to my ATTiny13a, I get the “Sketch too big” error. I guess there’s no way to test it unless I optimize space, even though it’s tough to get much smaller than this. Maybe I could change int to byte?

Error code:

Arduino: 1.0.6 (Windows NT (unknown)), Board: "ATtiny13 @ 9.6MHz (interne 9.6 MHz clock)"
Binary sketch size: 2,132 bytes (of a 1,024 byte maximum)

processing.app.debug.RunnerException: Sketch too big; see http://www.arduino.cc/en/Guide/Troubleshooting#size for tips on reducing it.

	at processing.app.Sketch.size(Sketch.java:1653)

	at processing.app.Sketch.build(Sketch.java:1586)

	at processing.app.Sketch.exportApplet(Sketch.java:1608)

	at processing.app.Sketch.exportApplet(Sketch.java:1594)

	at processing.app.Editor$DefaultExportHandler.run(Editor.java:2382)

	at java.lang.Thread.run(Thread.java:619)

Does this fit…

//#include "avr/eeprom.h" //I'm not sure if this is needed
#include "avr/pgmspace.h"
#include <util/delay.h>

static int const IRledPin = 4;    // LED connected to digital pin 4

typedef void (*delay_p)( void );

typedef union
{
  struct 
  {
    uint16_t pulse;
    delay_p quiet;
  };
  uint32_t aslong;
}
pair_t, *pair_p;

static void delay_0( void ) { }
static void delay_120( void ) { _delay_us( 120*10 ); }
static void delay_122( void ) { _delay_us( 122*10 ); }
static void delay_124( void ) { _delay_us( 124*10 ); }
static void delay_126( void ) { _delay_us( 126*10 ); }
static void delay_146( void ) { _delay_us( 146*10 ); }
static void delay_148( void ) { _delay_us( 148*10 ); }
static void delay_220( void ) { _delay_us( 220*10 ); }
static void delay_222( void ) { _delay_us( 222*10 ); }
static void delay_224( void ) { _delay_us( 224*10 ); }
static void delay_232( void ) { _delay_us( 232*10 ); }
static void delay_242( void ) { _delay_us( 242*10 ); }
static void delay_244( void ) { _delay_us( 244*10 ); }
static void delay_272( void ) { _delay_us( 272*10 ); }
static void delay_292( void ) { _delay_us( 292*10 ); }
static void delay_380( void ) { _delay_us( 380*10 ); }
static void delay_390( void ) { _delay_us( 390*10 ); }
static void delay_2236( void ) { _delay_us( 2236*10 ); }

static pair_t const tvONsignalX[] PROGMEM = 
{
  { 3160, delay_272 },
  { 740, delay_120 },
  { 740, delay_122 },
  { 740, delay_124 },
  { 720, delay_124 },
  { 700, delay_124 },
  { 720, delay_124 },
  { 720, delay_220 },
  { 700, delay_126 },
  { 720, delay_126 },
  { 700, delay_124 },
  { 720, delay_124 },
  { 700, delay_124 },
  { 720, delay_222 },
  { 680, delay_126 },
  { 700, delay_224 },
  { 620, delay_232 },
  { 600, delay_380 },
  { 580, delay_2236 },
  { 2960, delay_292 },
  { 500, delay_146 },
  { 480, delay_146 },
  { 520, delay_146 },
  { 500, delay_146 },
  { 480, delay_146 },
  { 500, delay_146 },
  { 500, delay_242 },
  { 500, delay_146 },
  { 520, delay_146 },
  { 480, delay_146 },
  { 480, delay_148 },
  { 480, delay_146 },
  { 520, delay_242 },
  { 480, delay_146 },
  { 520, delay_242 },
  { 480, delay_244 },
  { 500, delay_390 },
  { 500, delay_0 },
};

static int const ONcodeLength = sizeof(tvONsignalX) / sizeof(tvONsignalX[0]);

/* rmv
static int const tvONsignal[] PROGMEM = {
// ON, OFF (in 10's of microseconds)
316, 272,
74, 120,
74, 122,
74, 124,
72, 124,
70, 124,
72, 124,
72, 220,
70, 126,
72, 126,
70, 124,
72, 124,
70, 124,
72, 222,
68, 126,
70, 224,
62, 232,
60, 380,
58, 2236,
296, 292,
50, 146,
48, 146,
52, 146,
50, 146,
48, 146,
50, 146,
50, 242,
50, 146,
52, 146,
48, 146,
48, 148,
48, 146,
52, 242,
48, 146,
52, 242,
48, 244,
50, 390,
50, 0
};

int ONcodeLength = sizeof(tvONsignal)/(2*sizeof(int));
*/

// The setup() method runs once, when the sketch starts
 
void setup()   {                
//  Serial.begin(9600);
  // initialize the IR digital pin as an output:
  pinMode(IRledPin, OUTPUT);
}
 
void loop()                     
{
//  Serial.println("Sending IR signal");
 
  SendTVONCode_P();
 
  _delay_ms(3*1000);  // wait three seconds (3 seconds * 1000 milliseconds)
}
 
// This procedure sends a 38KHz pulse to the IRledPin 
// for a certain # of microseconds. We'll use this whenever we need to send codes
void pulseIR(int microsecs) {
  // we'll count down from the number of microseconds we are told to wait
 
  //cli();  // this turns off any background interrupts
 
  while (microsecs > 0) {
    // 38 kHz is about 13 microseconds high and 13 microseconds low
   digitalWrite(IRledPin, HIGH);  // this takes about 3 microseconds to happen
   _delay_us(10);         // hang out for 10 microseconds, you can also change this to 9 if its not working
   digitalWrite(IRledPin, LOW);   // this also takes about 3 microseconds
   _delay_us(10);         // hang out for 10 microseconds, you can also change this to 9 if its not working
 
   // so 26 microseconds altogether
   microsecs -= 26;
  }
 
  //sei();  // this turns them back on;
}
 void SendTVONCode_P()
 {
  pair_t pair;

   // All the delays are multiplied by 10 because the array values represent delays in 10's of microseconds

     for (int i = 0; i < ONcodeLength; i++)
     {
       pair.aslong = pgm_read_word(&tvONsignalX[i]);
       pulseIR(pair.pulse);
       pair.quiet();
//      pulseIR(10*pgm_read_word(&tvONsignal[2*i]));
//      delayMicroseconds(10*pgm_read_word(&tvONsignal[2*i + 1]));
     }
     _delay_ms(65); // delay and send code again
     for (int i = 0; i < ONcodeLength; i++)
     {
       pair.aslong = pgm_read_word(&tvONsignalX[i]);
       pulseIR(pair.pulse);
       pair.quiet();
//      pulseIR(10*pgm_read_word(&tvONsignal[2*i]));
//      delayMicroseconds(10*pgm_read_word(&tvONsignal[2*i + 1]));
     }
}

Yes, it fits (taking up only 856 bytes although it looks a lot longer lol). However, it doesn't work, as the LED just stays lit the whole time. I would try to find an error, but I don't know what pair_t is, so I can't be of any help there.

tincanman8: Yes, it fits (taking up only 856 bytes although it looks a lot longer lol).

Excellent.

However, it doesn't work, as the LED just stays lit the whole time.

How does the code behave running on the Arduino Mega 2560.

I would try to find an error, but I don't know what pair_t is, so I can't be of any help there.

Do either of these help... http://playground.arduino.cc/Code/Struct http://www.cplusplus.com/doc/tutorial/structures/

Thanks for the links. The code does the exact same things on the Arduino Mega 2560. Sorry for the late replies; time zone difference :sleeping:

Give this one a try (on the 2560)…

//#include "avr/eeprom.h" //I'm not sure if this is needed
#include "avr/pgmspace.h"
#include <util/delay.h>

static int const IRledPin = 4;    // LED connected to digital pin 4

typedef void (*delay_p)( void );

typedef union
{
  struct 
  {
    int16_t pulse;
    delay_p quiet;
  };
  uint32_t aslong;
}
pair_t, *pair_p;

static void delay_0( void ) { }
static void delay_120( void ) { _delay_us( 120*10 ); }
static void delay_122( void ) { _delay_us( 122*10 ); }
static void delay_124( void ) { _delay_us( 124*10 ); }
static void delay_126( void ) { _delay_us( 126*10 ); }
static void delay_146( void ) { _delay_us( 146*10 ); }
static void delay_148( void ) { _delay_us( 148*10 ); }
static void delay_220( void ) { _delay_us( 220*10 ); }
static void delay_222( void ) { _delay_us( 222*10 ); }
static void delay_224( void ) { _delay_us( 224*10 ); }
static void delay_232( void ) { _delay_us( 232*10 ); }
static void delay_242( void ) { _delay_us( 242*10 ); }
static void delay_244( void ) { _delay_us( 244*10 ); }
static void delay_272( void ) { _delay_us( 272*10 ); }
static void delay_292( void ) { _delay_us( 292*10 ); }
static void delay_380( void ) { _delay_us( 380*10 ); }
static void delay_390( void ) { _delay_us( 390*10 ); }
static void delay_2236( void ) { _delay_us( 2236*10 ); }

static pair_t const tvONsignalX[] PROGMEM = 
{
  { 3160, delay_272 },
  { 740, delay_120 },
  { 740, delay_122 },
  { 740, delay_124 },
  { 720, delay_124 },
  { 700, delay_124 },
  { 720, delay_124 },
  { 720, delay_220 },
  { 700, delay_126 },
  { 720, delay_126 },
  { 700, delay_124 },
  { 720, delay_124 },
  { 700, delay_124 },
  { 720, delay_222 },
  { 680, delay_126 },
  { 700, delay_224 },
  { 620, delay_232 },
  { 600, delay_380 },
  { 580, delay_2236 },
  { 2960, delay_292 },
  { 500, delay_146 },
  { 480, delay_146 },
  { 520, delay_146 },
  { 500, delay_146 },
  { 480, delay_146 },
  { 500, delay_146 },
  { 500, delay_242 },
  { 500, delay_146 },
  { 520, delay_146 },
  { 480, delay_146 },
  { 480, delay_148 },
  { 480, delay_146 },
  { 520, delay_242 },
  { 480, delay_146 },
  { 520, delay_242 },
  { 480, delay_244 },
  { 500, delay_390 },
  { 500, delay_0 },
};

static int const ONcodeLength = sizeof(tvONsignalX) / sizeof(tvONsignalX[0]);

/* rmv
static int const tvONsignal[] PROGMEM = {
// ON, OFF (in 10's of microseconds)
316, 272,
74, 120,
74, 122,
74, 124,
72, 124,
70, 124,
72, 124,
72, 220,
70, 126,
72, 126,
70, 124,
72, 124,
70, 124,
72, 222,
68, 126,
70, 224,
62, 232,
60, 380,
58, 2236,
296, 292,
50, 146,
48, 146,
52, 146,
50, 146,
48, 146,
50, 146,
50, 242,
50, 146,
52, 146,
48, 146,
48, 148,
48, 146,
52, 242,
48, 146,
52, 242,
48, 244,
50, 390,
50, 0
};

int ONcodeLength = sizeof(tvONsignal)/(2*sizeof(int));
*/

// The setup() method runs once, when the sketch starts
 
void setup()
{
/*
  Serial.begin(115200);
  
  pair_t pair;

  Serial.print( F( "ONcodeLength = " ) );
  Serial.print( ONcodeLength );
  Serial.println();
  
  for (int i = 0; i < ONcodeLength; i++)
  {
    pair.aslong = pgm_read_dword(&tvONsignalX[i]);

    pulseIR(pair.pulse);
    pair.quiet();
  }
*/

/**/
  // initialize the IR digital pin as an output:
  pinMode(IRledPin, OUTPUT);
/**/
}
 
void loop()                     
{
/*
//  Serial.println("Sending IR signal");
 
  SendTVONCode_P();
 
  _delay_ms(3*1000);  // wait three seconds (3 seconds * 1000 milliseconds)
*/
}
 
// This procedure sends a 38KHz pulse to the IRledPin 
// for a certain # of microseconds. We'll use this whenever we need to send codes
void pulseIR(int microsecs) {
  // we'll count down from the number of microseconds we are told to wait
 
  //cli();  // this turns off any background interrupts
 
  while (microsecs > 0) {
    // 38 kHz is about 13 microseconds high and 13 microseconds low
   digitalWrite(IRledPin, HIGH);  // this takes about 3 microseconds to happen
   _delay_us(10);         // hang out for 10 microseconds, you can also change this to 9 if its not working
   digitalWrite(IRledPin, LOW);   // this also takes about 3 microseconds
   _delay_us(10);         // hang out for 10 microseconds, you can also change this to 9 if its not working
 
   // so 26 microseconds altogether
   microsecs -= 26;
  }
 
  //sei();  // this turns them back on;
}
 void SendTVONCode_P()
 {
  pair_t pair;

   // All the delays are multiplied by 10 because the array values represent delays in 10's of microseconds

     for (int i = 0; i < ONcodeLength; i++)
     {
       pair.aslong = pgm_read_dword(&tvONsignalX[i]);
       pulseIR(pair.pulse);
       pair.quiet();
//      pulseIR(10*pgm_read_word(&tvONsignal[2*i]));
//      delayMicroseconds(10*pgm_read_word(&tvONsignal[2*i + 1]));
     }
     _delay_ms(65); // delay and send code again
     for (int i = 0; i < ONcodeLength; i++)
     {
       pair.aslong = pgm_read_dword(&tvONsignalX[i]);
       pulseIR(pair.pulse);
       pair.quiet();
//      pulseIR(10*pgm_read_word(&tvONsignal[2*i]));
//      delayMicroseconds(10*pgm_read_word(&tvONsignal[2*i + 1]));
     }
 }

Hello. The last sketch doesn't work either; the LED doesn't blink or anything. The sketch size is 256 bytes (maybe the compiler is removing a lot of it?).

Commented-out the important bit. Yikes. Sorry about that. Give this a try…

//#include "avr/eeprom.h" //I'm not sure if this is needed
#include "avr/pgmspace.h"
#include <util/delay.h>

static int const IRledPin = 4;    // LED connected to digital pin 4

typedef void (*delay_p)( void );

typedef union
{
  struct 
  {
    int16_t pulse;
    delay_p quiet;
  };
  uint32_t aslong;
}
pair_t, *pair_p;

/**/
static void delay_0( void ) { }
static void delay_120( void ) { _delay_us( 120*10 ); }
static void delay_122( void ) { _delay_us( 122*10 ); }
static void delay_124( void ) { _delay_us( 124*10 ); }
static void delay_126( void ) { _delay_us( 126*10 ); }
static void delay_146( void ) { _delay_us( 146*10 ); }
static void delay_148( void ) { _delay_us( 148*10 ); }
static void delay_220( void ) { _delay_us( 220*10 ); }
static void delay_222( void ) { _delay_us( 222*10 ); }
static void delay_224( void ) { _delay_us( 224*10 ); }
static void delay_232( void ) { _delay_us( 232*10 ); }
static void delay_242( void ) { _delay_us( 242*10 ); }
static void delay_244( void ) { _delay_us( 244*10 ); }
static void delay_272( void ) { _delay_us( 272*10 ); }
static void delay_292( void ) { _delay_us( 292*10 ); }
static void delay_380( void ) { _delay_us( 380*10 ); }
static void delay_390( void ) { _delay_us( 390*10 ); }
static void delay_2236( void ) { _delay_us( 2236*10 ); }
/**/

/**
static void delay_0( void ) { Serial.print( 0 ); }
static void delay_120( void ) { Serial.print( 120 ); }
static void delay_122( void ) { Serial.print( 122 ); }
static void delay_124( void ) { Serial.print( 124 ); }
static void delay_126( void ) { Serial.print( 126 ); }
static void delay_146( void ) { Serial.print( 146 ); }
static void delay_148( void ) { Serial.print( 148 ); }
static void delay_220( void ) { Serial.print( 220 ); }
static void delay_222( void ) { Serial.print( 222 ); }
static void delay_224( void ) { Serial.print( 224 ); }
static void delay_232( void ) { Serial.print( 232 ); }
static void delay_242( void ) { Serial.print( 242 ); }
static void delay_244( void ) { Serial.print( 244 ); }
static void delay_272( void ) { Serial.print( 272 ); }
static void delay_292( void ) { Serial.print( 292 ); }
static void delay_380( void ) { Serial.print( 380 ); }
static void delay_390( void ) { Serial.print( 390 ); }
static void delay_2236( void ) { Serial.print( 2236 ); }
**/

static pair_t const tvONsignalX[] PROGMEM = 
{
  { 3160, delay_272 },
  { 740, delay_120 },
  { 740, delay_122 },
  { 740, delay_124 },
  { 720, delay_124 },
  { 700, delay_124 },
  { 720, delay_124 },
  { 720, delay_220 },
  { 700, delay_126 },
  { 720, delay_126 },
  { 700, delay_124 },
  { 720, delay_124 },
  { 700, delay_124 },
  { 720, delay_222 },
  { 680, delay_126 },
  { 700, delay_224 },
  { 620, delay_232 },
  { 600, delay_380 },
  { 580, delay_2236 },
  { 2960, delay_292 },
  { 500, delay_146 },
  { 480, delay_146 },
  { 520, delay_146 },
  { 500, delay_146 },
  { 480, delay_146 },
  { 500, delay_146 },
  { 500, delay_242 },
  { 500, delay_146 },
  { 520, delay_146 },
  { 480, delay_146 },
  { 480, delay_148 },
  { 480, delay_146 },
  { 520, delay_242 },
  { 480, delay_146 },
  { 520, delay_242 },
  { 480, delay_244 },
  { 500, delay_390 },
  { 500, delay_0 },
};

static int const ONcodeLength = sizeof(tvONsignalX) / sizeof(tvONsignalX[0]);

/* rmv
static int const tvONsignal[] PROGMEM = {
// ON, OFF (in 10's of microseconds)
316, 272,
74, 120,
74, 122,
74, 124,
72, 124,
70, 124,
72, 124,
72, 220,
70, 126,
72, 126,
70, 124,
72, 124,
70, 124,
72, 222,
68, 126,
70, 224,
62, 232,
60, 380,
58, 2236,
296, 292,
50, 146,
48, 146,
52, 146,
50, 146,
48, 146,
50, 146,
50, 242,
50, 146,
52, 146,
48, 146,
48, 148,
48, 146,
52, 242,
48, 146,
52, 242,
48, 244,
50, 390,
50, 0
};

int ONcodeLength = sizeof(tvONsignal)/(2*sizeof(int));
*/

// The setup() method runs once, when the sketch starts
 
void setup()
{
/**
  Serial.begin(115200);
  
  pair_t pair;

  Serial.print( F( "ONcodeLength = " ) );
  Serial.print( ONcodeLength );
  Serial.println();
  
  for (int i = 0; i < ONcodeLength; i++)
  {
    pair.aslong = pgm_read_dword(&tvONsignalX[i]);

    Serial.print( i );
    Serial.print( F( " --> " ) );
    Serial.print( pair.pulse );
    
    Serial.print( F( ", " ) );
    pair.quiet();
    Serial.println();
  }
**/

/**/
  // initialize the IR digital pin as an output:
  pinMode(IRledPin, OUTPUT);
/**/
}
 
void loop()                     
{
//  Serial.println("Sending IR signal");

/**/
  SendTVONCode_P();
  _delay_ms(3*1000);  // wait three seconds (3 seconds * 1000 milliseconds)
/**/
}
 
// This procedure sends a 38KHz pulse to the IRledPin 
// for a certain # of microseconds. We'll use this whenever we need to send codes
void pulseIR(int microsecs) {
  // we'll count down from the number of microseconds we are told to wait
 
  //cli();  // this turns off any background interrupts
 
  while (microsecs > 0) {
    // 38 kHz is about 13 microseconds high and 13 microseconds low
   digitalWrite(IRledPin, HIGH);  // this takes about 3 microseconds to happen
   _delay_us(10);         // hang out for 10 microseconds, you can also change this to 9 if its not working
   digitalWrite(IRledPin, LOW);   // this also takes about 3 microseconds
   _delay_us(10);         // hang out for 10 microseconds, you can also change this to 9 if its not working
 
   // so 26 microseconds altogether
   microsecs -= 26;
  }
 
  //sei();  // this turns them back on;
}
 void SendTVONCode_P()
 {
  pair_t pair;

   // All the delays are multiplied by 10 because the array values represent delays in 10's of microseconds

     for (int i = 0; i < ONcodeLength; i++)
     {
       pair.aslong = pgm_read_dword(&tvONsignalX[i]);
       pulseIR(pair.pulse);
       pair.quiet();
//      pulseIR(10*pgm_read_word(&tvONsignal[2*i]));
//      delayMicroseconds(10*pgm_read_word(&tvONsignal[2*i + 1]));
     }
     _delay_ms(65); // delay and send code again
     for (int i = 0; i < ONcodeLength; i++)
     {
       pair.aslong = pgm_read_dword(&tvONsignalX[i]);
       pulseIR(pair.pulse);
       pair.quiet();
//      pulseIR(10*pgm_read_word(&tvONsignal[2*i]));
//      delayMicroseconds(10*pgm_read_word(&tvONsignal[2*i + 1]));
     }
 }

Hello,

This code works on my Arduino Mega 2560, but not the ATTiny13a. The blinks seem to be identical, but the ATTiny doesn't do anything to the TV.

Is the version in Reply #9 at least smaller than the original?

Bummer. That means the most likely culprit is timing. From the factory, the internal oscillator is ±10%. The processor could be running anywhere between... 9.6-(9.6*0.10) = 8.64 MHz 9.6+(9.6*0.10) = 10.56 MHz

Fortunately, AVR internal oscillators are fairly easy to tune.

How are you programming the t13a?

Hello.

Yes, the code in reply #9 is smaller by about 8 bits. The problem is that the code is manually loaded into functions, and not just accessed from an array. This makes compatibility a bit tougher.

From my testing of timing in the ATTiny13a, I got about 12.6 seconds on what was supposed to be a 10 second blink. I think this is a significant difference. I do believe that timing is the big issue, and setting the correct fuses could make the difference. That's just my guess.

I don't know what a t13a is. Sounds like a chip. I've never worked with one before, though.

tincanman8: Yes, the code in reply #9 is smaller by about 8 bits.

Bummer. There are some things that can be done to reduce the size but that is an exercise for another time.

The problem is that the code is manually loaded into functions, and not just accessed from an array.

Yeah but it is trivial to build the array using Excel.

From my testing of timing in the ATTiny13a, I got about 12.6 seconds on what was supposed to be a 10 second blink. I think this is a significant difference. I do believe that timing is the big issue

Yes, that is a problem. That is very likely [u]the[/u] problem.

...and setting the correct fuses could make the difference. That's just my guess.

Can't be (just) a fuse problem.

I don't know what a t13a is. Sounds like a chip. I've never worked with one before, though.

"t13a" is an abbreviation for "ATtiny13a".

This question should now make more sense... How are you programming the t13a?

Oh, woops. I thought you meant "how are you with programming the t13a" as if it were something else lol. My bad.

As stated in my first post, I am using Arduino as ISP to program the ATTiny13a. The Arduino is a Mega 2560.

Are you currently using the [u]ATtiny13 @ 9.6MHz (interne 9.6 MHz clock)[/u] board entry?

Did you use Tools / Burn Bootloader to change the fuses after selecting that board entry?

Yes, I did. It's still not working :'(

The fuses look correct.

tincanman8: From my testing of timing in the ATTiny13a, I got about 12.6 seconds on what was supposed to be a 10 second blink.

Post your code.

How did you measure the 10 seconds? Wall clock?

No lol. I used online-stopwatch. In turn, I measured the 10 seconds from a blink sketch uploaded to my Arduino Mega 2560, and it gave me like 10.06 seconds. Of course, the 0.06 sec was probably the error with my timing, but I'm just trying to demonstrate that I am sure that the 12.6 seconds was approximately 12.6 seconds, not just a slow hand :P

EDIT: My code for testing the blink delays was the simple blink but with the output pin changed and the first delay changed to 10000.

/*
  Blink
  Turns on an LED on for one second, then off for one second, repeatedly.

  Most Arduinos have an on-board LED you can control. On the Uno and
  Leonardo, it is attached to digital pin 13. If you're unsure what
  pin the on-board LED is connected to on your Arduino model, check
  the documentation at http://arduino.cc

  This example code is in the public domain.

  modified 8 May 2014
  by Scott Fitzgerald
 */


// the setup function runs once when you press reset or power the board
void setup() {
  // initialize digital pin 13 as an output.
  pinMode(4, OUTPUT);
}

// the loop function runs over and over again forever
void loop() {
  digitalWrite(4, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(10000);              // wait for a second
  digitalWrite(4, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);              // wait for a second
}

EDIT2: I uploaded the sketch from reply #9 to both my Arduino Mega 2560 and ATTiny13a, and used a red LED to look for speed differences. I took a slow-mo video (/8) and there is a clear difference. The video is here. Again, using online-stopwatch, there's a factor of ~1.2 difference. Arduino Mega 2560: ~5.1 seconds (in the slow-mo video). ATTiny13a: ~6.3 (in the slow-mo video). Ratio: 6.3/5.2 = ~1.24 which is what we observed.