core13: An Arduino core for the Attiny13 *testers wanted*

I am writing [have written] an Arduino core for the Attiny13.
It will [does] support a subset of the Arduino functions and is of relatively small size.
So far it seems to work but I have not tested it completely.
I have not tested it thoroughly and I only tested it with 128khz internal oscillator.
Supports 128KHz, 600KHz, 1MHz, 1.2MHz, 4MHz, 4.8MHz, 8MHz, 9.6MHz, 10MHz, 12MHz and 16MHz clock speeds (Although not all are tested) - More frequency support soon
If anyone gets a chance give it a try.
Although programming a microcontroller with this little flash space with a Arduino core is alittle impractical, it helps the beginners greatly. Core13 is optimized for size so you have more space for user code.

For the most part, I read the Arduino core source code and rewrote most of it from scratch.
It may work for other 8 pin Attiny series but I cannot promise.
Currently supported functions:

  • = Partial support
map()
random()
randomSeed()
millis()
micros()
delay()
delayMicroseconds() *
analogRead()
analogWrite()
pinMode()
digitalRead()
digitalWrite()
pulseIn() (Untested)
shiftIn() (Untested)
shiftOut() (Untested)

edit: fixed bugs and attached new version.
edit: Added support for 4, 4.8Mhz and improved support for 9.6Mhz
edit: Released 0.15 that fixes bugs
edit: Released 0.19 and removed old version attached. Please download from sourceforge
edit: Released 0.20 which improves delayMicroseconds() considerably

(If you cannot download from SF (like because their site bloat hangs your machine :slight_smile: then PM me and I can provide a direct download)

Supports the old Arduino IDE (pre-1.0) and Arduino 1.0.x. Support for Arduino 1.5 is untested and may not work
From now on download from sourceforge.net for the newest release Core13 download | SourceForge.net
Licensing note: Core13 is under a mixed license (as marked at the top of each source file) this is because I included
some Arduino core files. Most of the code is under a very unrestricted license while a few files are under the standard Arduino core license

NULL

Dude. Patience. A large number of users only visit the forum weekly or less often. In addition, from an Arduino perspective, the core is for an esoteric processor.

For what it's worth, I plan to look it over this weekend.

Needs instructions for how to add it to the IDE...

Ok. I am not often a patient person.

In addition, from an Arduino perspective, the core is for an esoteric processor.

Limited but hardly esoteric.
[/quote]

westfw:
Needs instructions for how to add it to the IDE...

On windows it will usually go in

C:\arduino\arduino-<version>\hardware\arduino\cores\core13

in my case it would be

C:\arduino\arduino-0022\hardware\arduino\cores\core13

I added this to my boards.txt:

attiny13.name=Attiny 13A standalone

attiny13.upload.using=arduino:arduinoisp
attiny13.upload.maximum_size=1024
attiny13.upload.speed=19200

attiny13.bootloader.low_fuses=0x7B
attiny13.bootloader.high_fuses=0xFF
attiny13.bootloader.path=empty
attiny13.bootloader.file=empty

attiny13.bootloader.unlock_bits=0xFF
attiny13.bootloader.lock_bits=0xFF

attiny13.build.mcu=attiny13a
attiny13.build.f_cpu=128000
attiny13.build.core=core13

But be sure to change the fuses, f_cpu and programmer to match what you will be using.

I downloaded your file. Moved it into the Arduino directory. Selected ATTINY 13A Standalone as the board and Arduino as ISP for the programmer.

When I try and verify or upload the code, it says 'pinMode' was not declared in this scope.

I am sure it is something as simple as not including a file thats required but I thought I would ask here first before I start messing with stuff.

Also, thanks for taking the time to work on the Tiny13...

danimal1228:
I downloaded your file. Moved it into the Arduino directory. Selected ATTINY 13A Standalone as the board and Arduino as ISP for the programmer.

When I try and verify or upload the code, it says 'pinMode' was not declared in this scope.

I am sure it is something as simple as not including a file thats required but I thought I would ask here first before I start messing with stuff.

I failed to make the instructions clear enough.
You have to extract the zip file to

C:\arduino\arduino-<version>\hardware\arduino\cores\core13

Note: The folder core13 will not exist.
Note2: I have not tested this with IDE version 1.0 although it should work.

Also, thanks for taking the time to work on the Tiny13...

Most people are put off by only 1k of flash...

Nice work and thank you for taking on this project! I've been looking for Tiny13 core for a very small project and was agonizing over the decision to embark on writing my own :blush: - too small a project ... And finally I've found yours!

Anyhow, I've tried it with 0022 and 1.0 on Linux

I'm still looking into the code but the result so far as follows:

0022 complies the code fine though avrdude is not finding the MCU (I'm using AVRISP MKII programmer) - it looks for t13 but sees attiny13a and throws an error.

1.0 does not compile - it's not finding the core at either of the two possible locations:

~/sketchbook/hardware/arduino/codes/core13
or
~/arduino_directory/hardware/arduino/cores/core13

trying to burn a bootloader with the programmer on V1.0 does not go either - same error as on 0022 (wrong MCU name)

I'm still looking around but maybe you can see what I'm doing wrong here?

Cheers!

All right, thanks again, smeezekitty!

I am blinking some LEDs here using Arduino 1.0 (linux) with ATtiny13 :smiley:

The problem was indeed the file locations. As far as I can tell, it depends on which boards.txt file you are adding your ATtiny13 entry to. I already had the ATtiny libraries by Damellis installed (ATtiny13 is missing there) and therefore I was using the boards.txt located at ~/sketchbook/hardware/tiny/boards.txt
So, I just added an entry to the other ATTiny cores' boards.txt:

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

attiny13.name=Attiny13 @ 128 KHz (internal watchdog oscillator)

attiny13.upload.using=arduino:arduinoisp
# attiny13.upload.protocol=avrispv2 
# attiny2313at1.upload.using=pololu

attiny13.upload.maximum_size=1024
attiny13.upload.speed=19200

attiny13.bootloader.low_fuses=0x7B
attiny13.bootloader.high_fuses=0xFF
attiny13.bootloader.path=empty
attiny13.bootloader.file=empty

attiny13.bootloader.unlock_bits=0xFF
attiny13.bootloader.lock_bits=0xFF

attiny13.build.mcu=attiny13
attiny13.build.f_cpu=128000
attiny13.build.core=core13

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

In this case the smeezekitty's core had to be located at ~/sketchbook/hardware/tiny/cores/core13/

Additionally, since this is Arduino 1.0, a small Arduino.h file needs to be added. I just copied one from the other core package:

#ifndef Arduino_h
#define Arduino_h

#include <WProgram.h>

#endif

The timer seems a bit off (actually, runs twice as fast as far as I can tell) but that's a 128kHz oscillator, I haven't looked at the prescaler and also, it may just be very inaccurate. I'll look into it later.

That was pretty much it!

Anyhow, great job, smeezekitty!

ElectroNick:
The timer seems a bit off (actually, runs twice as fast as far as I can tell) but that's a 128kHz oscillator, I haven't looked at the prescaler and also, it may just be very inaccurate. I'll look into it later.

That was pretty much it!

Anyhow, great job, smeezekitty!

This could be a bug.
The 128khz oscillator is inaccurate but not that inaccurate. Its about +- 30%.
It seems to run about the correct speed here although I have not tested it on Linux or Arduino 1.0.
Please post the code you used to make it blink.
I will investigate this further.

I've also looked at it and it turns out that I had to use the "Burn Bootloader" feature in IDE 1.0 which for a Tiny simply means that the fuses are burned correctly. Until then the timer was not setup correctly. Also I've switched to the internal 9.6MHz calibrated oscillator is the timing is perfect now. Here are the fuses:

attiny13.bootloader.low_fuses=0x7a
attiny13.bootloader.high_fuses=0xff

Please note that I'm sort of integrating your core with Demellis'es . I honestly could not find a way to burn the fuses with yours - the bootloader file was missing or I simply failed to find it. How'd you do it?

Cheers!

ElectroNick:
I've also looked at it and it turns out that I had to use the "Burn Bootloader" feature in IDE 1.0 which for a Tiny simply means that the fuses are burned correctly. Until then the timer was not setup correctly. Also I've switched to the internal 9.6MHz calibrated oscillator is the timing is perfect now. Here are the fuses:

attiny13.bootloader.low_fuses=0x7a

attiny13.bootloader.high_fuses=0xff

Be sure to adjust F_CPU as well.

Please note that I'm sort of integrating your core with Demellis'es . I honestly could not find a way to burn the fuses with yours - the bootloader file was missing or I simply failed to find it. How'd you do it?

Cheers!

I did not include a bootloader file because the attiny13 is too small for a bootloader.
I burned the fuses with avr-dude on the command line prior to using the Arduino IDE.
BTW I uploaded a new version that fixes a few minor bugs relating to clock speed.

Sorry but the attiny 13 nave only 1 k of flash , and only the sketch blink is 1.2k , what worldwide you do whit the attiny 13 ?, thanks for the core

nikone:
Sorry but the attiny 13 nave only 1 k of flash , and only the sketch blink is 1.2k , what worldwide you do whit the attiny 13 ?, thanks for the core

1.2K is a lot of bytes for a blink! The code must be not well optimized or sometin' . You can do plenty of useful things with 1K of command space. For example, here is a code for a 10-LED light chaser (can convert it into Cylon eyes or some other such blinking toy) and it compiles into only 562 bytes. In fact, there might even be some saving there still, I just didn't have too much time to optimize it.

/*
  Charlieplexing example for ATtiny13
  This code is for a 10-LED bargraph display. You can increase the amount of LEDs controller by the Tiny to 20 if needed.
  Code by Elabz.com
http://elabz.com/
  This example code is in the public domain. If you end up using it in a project, please drop me a message, I'd be happy to
  know it was of some use. I'll also be happy to feature your project on my site, so send some pictures, too: http://elabz.com/site/contact/
  
//       ATMEL ATTINY13 / ARDUINO
//
//                 +-\/-+
// ADC0 (D 5) PB5 1|    |8 Vcc
// ADC3 (D 3) PB3 2|    |7 PB2 (D 2) ADC1
// ADC2 (D 4) PB4 3|    |6 PB1 (D 1) PWM1
//            GND 4|    |5 PB0 (D 0) PWM0
//                 +----+

  
  
 */
int j; // just a counter
boolean d; // direction forward=true
//int bitmap[]={1,2,1,4,1,8,2,4,2,4};
byte bitmap[]={B00000001,B00000010,B00000001,B00000100,B00000001,B00001000,B00000010,B00000100,B00000010,B00001000};
byte outModes[]={B00000011,B00000011,B00000101,B00000101,B00001001,B00001001,B00000110,B00000110,B00001010,B00001010};



void setup() { 
d=true;
  // initialize the digital pin as an output.
  // Pin 13 has an LED connected on most Arduino boards:
/*  for(int i=0;i<5;i++) {
    pinMode(i, OUTPUT);   
} */
 
}

void loop() {
  
 byte outModeNow =  outModes[j] ;
  byte bitmapNow=bitmap[j];
  if(j>8) 
  { d=false;
  }else if(j<1)
  { d=true;}
  if(d){j++;}else{j--;}
  DDRB = outModeNow;
 // PORTB = B00000000;
  PORTB = bitmapNow;
  delay(50);              // wait 

}

Hope this helps,

Cheers!

nikone:
Sorry but the attiny 13 nave only 1 k of flash , and only the sketch blink is 1.2k , what worldwide you do whit the attiny 13 ?, thanks for the core

Not sure what is going on here.
The standard blink sketch compiles to 370 bytes with my core.
Even with the standard Arduino core its a bit less then 1KB.
Which blink sketch, compiler, etc? Blink should certainly not be over 1KB.
@ElectroNick
You can most likely use a byte for "j" and operations on a byte may be slightly smaller
I also guess there is a better way to do this

if(j>8) 
  { d=false;
  }else if(j<1)
  { d=true;}
  if(d){j++;}else{j--;}

but I cannot think very well right now.

Excusme for my english but i'm italian, now i understand how your core work , it's vero interesting , at the moment i haven't some attiny 13 but i'll test the core when i can , Thanks you vero much for this core
Niko

smeezekitty, I seem to have hit a brick wall here :disappointed_relieved:, wonder if you have a few pointers for me.

delay() function seems to be acting up: if you call it as delay(500);, it works as expected. But if you're calling it as delay(someVariable); , the program just stops and sits there indefinitely. I've tried passing it int, long and byte type variables (in my case, looked up values from an array defined as either of those types) and it hangs on all of them except when you literally just type the value in ( i.e. delay(500); ).

I'm trying to modify my own light chaser sketch (code below) to include a sort of a pseudo-PWM brightness control. It compiles fine but when executed, the LED matrix sits dark. If you type in, say delay(100) instead of delay(onDelay) and do the same for delay(offDelay), the LEDs work but of course, the gradual brightness increase does not happen.

It's a rather simple change to an already working code and I just can't wrap my head around the issue. That's why the question about the delay() implementation came up. Any critique or tips would be appreciated.

Cheers!

int j; // just a counter
boolean d; // direction forward=true
byte bitmap[]={B00000001,B00000010,B00000001,B00000100,B00000001,B00001000,B00000010,B00000100,B00000010,B00001000};
byte outModes[]={B00000011,B00000011,B00000101,B00000101,B00001001,B00001001,B00000110,B00000110,B00001010,B00001010};
//byte waveforms[16] = {1,4,15,31,50,69,85,96,100,96,85,69,50,31,15,4}; // happens to be 1/2 of sine wave. Just for test - some other profile may look better.
int waves[]={25,50,100,50,25}; // even simpler waveform
int cycleDelay=100;

void setup() { 
d=true;
}

void loop() {
  
 byte outModeNow =  outModes[j] ;
  byte bitmapNow=bitmap[j];
  if(j>8) 
  { d=false;
  }else if(j<1)
  { d=true;}
  if(d){j++;}else{j--;}

  for(int x=0; x<5; x++){ // counter for the waveform
      int onDelay = waves[x];
      int offDelay = cycleDelay - onDelay;
      
      DDRB = outModeNow;
      PORTB = bitmapNow; // turn LED on
      delay(onDelay);   // then wait
      DDRB = B00000000; // turn everything off
      delay(offDelay); // wait for the off period
  }

}

ElectroNick:
smeezekitty, I seem to have hit a brick wall here :disappointed_relieved:, wonder if you have a few pointers for me.

delay() function seems to be acting up: if you call it as delay(500);, it works as expected. But if you're calling it as delay(someVariable); , the program just stops and sits there indefinitely. I've tried passing it int, long and byte type variables (in my case, looked up values from an array defined as either of those types) and it hangs on all of them except when you literally just type the value in ( i.e. delay(500); ).

I'm trying to modify my own light chaser sketch (code below) to include a sort of a pseudo-PWM brightness control. It compiles fine but when executed, the LED matrix sits dark. If you type in, say delay(100) instead of delay(onDelay) and do the same for delay(offDelay), the LEDs work but of course, the gradual brightness increase does not happen.

It's a rather simple change to an already working code and I just can't wrap my head around the issue. That's why the question about the delay() implementation came up. Any critique or tips would be appreciated.

Cheers!

int j; // just a counter

boolean d; // direction forward=true
byte bitmap[]={B00000001,B00000010,B00000001,B00000100,B00000001,B00001000,B00000010,B00000100,B00000010,B00001000};
byte outModes[]={B00000011,B00000011,B00000101,B00000101,B00001001,B00001001,B00000110,B00000110,B00001010,B00001010};
//byte waveforms[16] = {1,4,15,31,50,69,85,96,100,96,85,69,50,31,15,4}; // happens to be 1/2 of sine wave. Just for test - some other profile may look better.
int waves[]={25,50,100,50,25}; // even simpler waveform
int cycleDelay=100;

void setup() {
d=true;
}

void loop() {
 
byte outModeNow =  outModes[j] ;
 byte bitmapNow=bitmap[j];
 if(j>8)
 { d=false;
 }else if(j<1)
 { d=true;}
 if(d){j++;}else{j--;}

for(int x=0; x<5; x++){ // counter for the waveform
     int onDelay = waves[x];
     int offDelay = cycleDelay - onDelay;
     
     DDRB = outModeNow;
     PORTB = bitmapNow; // turn LED on
     delay(onDelay);   // then wait
     DDRB = B00000000; // turn everything off
     delay(offDelay); // wait for the off period
 }

}



T

he code you provided did not compile. I had to change all the Bxxxxxxxx values to 0Bxxxxxxxx format (added 0 prefix).
But after making that change, it seemed to work but I did not have to proper LED array hooked up to test it fully.
I also tested the delay in another test program and again it works with no problems with variable values.
Either there is a problem with Arduino IDE 1.0 or clock speeds other then 128khz.
I may have to break down and try IDE version 1.0.

I think I got the issue down to the ATtiny13 hardware limitation - with only 64 bytes of SRAM you really have to be very careful with sizes of the variables and arrays. I think the problem with my code was that the RAM would fill up really quickly.

I've tried to remove everything I could and had to do linear brightness increase, which isn't really a very attractive option :. I had to strip almost everything down (eliminate variables unless absolutely necessary, reduce int to byte where possible and so on) in order to get it to work and I had to give up trying to control the brightness with sine and other complex waveforms - the only way I could do it was to go 0-100% in the first quarter of the cycle and hold it for the rest of the cycle. The effect of the gradual brightness increase is almost imperceptible, but that was the best I could do. Hope someone could come up with a better code!
Here is it:

/*
  Charlieplexing example for ATtiny13 with some brightness control using pseudo-PWM
  This code is for a 10-LED bargraph display. You can increase the amount of LEDs controller by the Tiny to 20 if needed.
  Code by Elabz.com
  http://elabz.com/ 
  This example code is in the public domain. If you end up using it in a project, please drop me a message, I'd be happy to
  know it was of some use. I'll also be happy to feature your project on my site, so send some pictures, too.
  
  LED hookup can be gleaned from the bitmap[] array values. For example, first LED's value is B00000001 which means that
  to light the LED the D0 has to ho HIGH and D1 - LOW, so the LED's anode is facing D0. LED #2 is between the same legs but in reverse. 
  LED #3 is between D0 and D2, LED #4 is the same legs but in reverse and so on. 
  
//       ATMEL ATTINY13 / ARDUINO
//
//                 +-\/-+
// ADC0 (D 5) PB5 1|    |8 Vcc
// ADC3 (D 3) PB3 2|    |7 PB2 (D 2) ADC1
// ADC2 (D 4) PB4 3|    |6 PB1 (D 1) PWM1
//            GND 4|    |5 PB0 (D 0) PWM0
//                 +----+

  
  
 */
byte bitmap[]={0B00000001,0B00000010,0B00000001,0B00000100,0B00000001,0B00001000,0B00000010,0B00000100,0B00000010,0B00001000};
byte outModes[]={0B00000011,0B00000011,0B00000101,0B00000101,0B00001001,0B00001001,0B00000110,0B00000110,0B00001010,0B00001010};
boolean d; // direction forward=true
byte j=0; // just a counter
long periodPWM;
long periodNow;
int cycleDelay=3000;
void setup() { 
periodPWM = cycleDelay/200;
d=true;
}

void loop() {
int offDelay;

  for(byte x=0; x<50; x++){ // counter for the waveform
      offDelay = 50 - x;
      periodNow = millis();
      
      while(millis()-periodNow < periodPWM)
      {
      DDRB = 0B00000000; // turn everything off
      delayMicroseconds(offDelay); // wait for the off period
      DDRB = outModes[j];
      PORTB = bitmap[j]; // turn LED on
      delayMicroseconds(x);   // then wait
     }
  }
delay(cycleDelay*3/4);

  if(j>8) 
  { d=false;
  }else if(j<1)
  { d=true;}
  if(d){j++;}else{j--;}
 
}