Hey guys,
I'm trying to build a simple code generator with a AT Tiny 13 microcontroller. I originally designed and tested the project on an Arduino Uno, with the intention of porting it to the Attiny13 with the microcore library (GitHub - MCUdude/MicroCore: A light-weight Arduino hardware package for ATtiny13).
Basically all the microcontroller has to do is lookup a value from a byte array, and change the state of an output pin to match, once every millisecond. The next millisecond it moves to the next byte in the array, and changes the output to suit. The byte array is 32 bytes long (1 value for each bit, the data stream code I want to output is just the same 4 bytes repeated over and over). Once it reaches the end of the array, it starts again from the start.
It also checks the state of an input pin (high or low), and if it is found to be low for a certain amount of code loops, it stops outputting the code.
I have written the code and it works perfectly on a uno with atmega328. However after compiling it for the attiny13, burning the bootloader (which is only to set fuses on the attiny13), and programming with a uno as ISP programmer, the attiny13 outputs gibberish data. The fuses all report as being written correctly, and the compiled data uploads to the attiny13, but it doesn't work properly. Sometimes it outputs gibberish for a few seconds and the gets stuck high, like its in an endless loop or something.
I have stripped the code down to find the problem. It no longer includes checking for the state of the input pin. It is meant to simply output 8 different values, 1 per millisecond, over and over. Again this works perfectly on the uno but not on the attiny.
#define DATA_RATE 1000 //microseconds between data bits (1000 = 1 bit per second)
#define DATA_LENGTH 7 //length of data packet in bits (0 based)
#define PIN_OUTPUT 4 //Output pin
const byte data[] = {1, 0, 1, 0, 1, 1, 1, 0}; //1 = HIGH, 0 = LOW
byte currentDataBit = 0;
unsigned long lastDataTime = 0;
//int loopCount = 0;
void setup() {
//Serial.begin(115200);
pinMode(PIN_OUTPUT, OUTPUT);
lastDataTime = micros();
}
void loop() {
//loopCount++;
if (micros() > (lastDataTime + DATA_RATE)) {
lastDataTime = micros();
digitalWrite(PIN_OUTPUT, data[currentDataBit]);
currentDataBit++;
if (currentDataBit > DATA_LENGTH) {
currentDataBit = 0;
}
//Serial.println(loopCount);
//loopCount = 0;
}
}
To use this with Microcore I had to enable the micros() function in the core_settings.h file. The Microcore github page says micros() is a working function.
I am using the 9.6mHz internal oscillator of the attiny. The uno (atmega328) running at 16mhz, with the loopCount parts in the code not commented out, reports 140 loops between each change of data (140 loops per millisecond) even with the overhead to write to serial for me to see. I would assume the code is not too fast for the attiny.
I have attached an image showing the output measured with an oscilloscope (Picoscope 4425). You can see the atmega328 outputting the same correct thing over and over. Whatever the attiny is outputting is not what the code ive written says it should be.
The above (cut down) code compiles for the attiny and says it uses 598 bytes (58%) of storage space, and 17 bytes (26%) of dynamic memory.
The complete code (with the extra output data, checking input pin etc) says it uses 712 bytes (69%) of storage space and 44 bytes (68%) of dynamic memory.
I'm thinking maybe I should be using an interrupt on the attiny, instead of constantly checking micros(), but Ive got no experience with them.
Thanks in advance
