I searched around and didn't see any mention of this anywhere, so I thought I'd ask. Has anyone used the MIT Tiny cores from http://hlt.media.mit.edu/?p=1695, burned the 8Mhz Internal Oscillator bootloader (i.e. set the fuse bits) and then had it still run at 1Mhz? I was totally baffled by debugging some timing+interrupt heavy based code that I've been working with (GitHub - mchr3k/arduino-libs-manchester for 433mhz RF) and then I realized that my Tiny was running at 1Mhz. Reburned the bootloader, still no love. Hooked up my oscillator and just sent a pulse in my loop, nothing more than
digitalWrite(4, HIGH);
digitalWrite(4, LOW);
and it spikes once per uS, which is, unless I'm delusional, 1Mhz. Anyone else run into this?
and it spikes once per uS, which is, unless I'm delusional, 1Mhz. Anyone else run into this?
You're making an awful lot of assumptions there.
digitalWrite() takes more than one clock cycle to execute. You're doing two digitalWrites per pulse so it will take twice as long as that for one cycle (I'm very amazed you got 1MHz - the Tiny85 library must be quite well optimized!)
That will flip the output pin once per clock cycle (apart from when it goes back to the start of the loop). Two flips makes one complete pulse so you should see a 4mHz signal if you're running at 8mHz.
Had I thought a little bit more, I would have put 2Mhz. That's what I get for trying to multi-task.
You're definitely right about the number of cycles per instruction, many thanks for reminding me about that! I've got the following code showing me 4 spikes per uS, hence 8Mhz if my math is right?
void setup()
{
DDRB |= 0x1; // setup pin 1 in data direction register as output
}
void loop()
{
while(true) {
PORTB |= 0x1; // set pin 1 so that it is at vcc
PORTB &= 0xFE; // clear pin 1 so that it is grounded
PORTB |= 0x1; // set pin 1 so that it is at vcc
PORTB &= 0xFE; // clear pin 1 so that it is grounded
PORTB |= 0x1; // set pin 1 so that it is at vcc
PORTB &= 0xFE; // clear pin 1 so that it is grounded
PORTB |= 0x1; // set pin 1 so that it is at vcc
PORTB &= 0xFE; // clear pin 1 so that it is grounded
}
}
So, my timing problems are of my own making, which is a consolation. If I can ask a secondary question then (and if I should set up another thread, I'd be happy to) I'm setting a timer interrupt on TIMER1, would this somehow affect the timing in my sketch (other than introducing another method to run at an interval)? The gist is below (and, I'd be happy to post more code if you'd like). I'm not sure how the Tiny core works but I didn't see any indication that it's using Timer1 and I'd assume it's using Timer0 for delay() and delayMicroseconds().
void start() {
TCCR1 = _BV(CTC1) | _BV(CS12);
OCR1A = 1; // we're checking every other count
TIMSK = _BV(OCIE1A); // Turn on interrupt
TCNT1 = 0; // Set counter to 0
}
ISR(TIMER1_COMPA_vect) {
// check the input pins and try to do
// manchester decoding.
}
Thanks much for the suggestions and the help, it's much appreciated.
joshuajnoble:
You're definitely right about the number of cycles per instruction, many thanks for reminding me about that! I've got the following code showing me 4 spikes per uS, hence 8Mhz if my math is right?
void loop()
{
while(true) {
PORTB |= 0x1; // set pin 1 so that it is at vcc
PORTB &= 0xFE; // clear pin 1 so that it is grounded
}
}
I'd say no...
"PORTB |= 0x1;" is a read of port B followed by an or and a write. That's going to be at least two clock cycles.
This is why my code used PINB - to avoid the read.
joshuajnoble:
I'm not sure how the Tiny core works but I didn't see any indication that it's using Timer1 and I'd assume it's using Timer0 for delay() and delayMicroseconds().
I believe you're right...
If I'm not, and delay() stops working, use Timer0..
"PORTB |= 0x1;" is a read of port B followed by an or and a write. That's going to be at least two clock cycles.
This is why my code used PINB - to avoid the read.
Interesting, ok. I've always used PORTB for writing, guess I didn't actually know what it was doing. Thanks for the info.
If I'm not, and delay() stops working, use Timer0..
The delay() method keeps working, but my read timing seems very inconsistent. If I'm reading the data sheet correctly page 92-92, table 12-5 says that setting the CS12 of TCCR1 pre-scales the clock to PCK/8, which should be 1Mhz, so reading on the overflow of OCR1A I should be triggering this method around 500khz. It seems to be actually reading much more slowly than that, around 100khz. I'm wondering if this is caused by what's in my interrupt routine, which is essentially just reading from the pin my RF receiver is connected to and then comparing that to the last read to find encoded bits. The code is below if anyone is interested in taking a peruse. Please do let me know if you see something horribly wrong in there. Thanks,
ISR(TIMER1_COMPA_vect) {
rx_sample = digitalRead(RxPin);
boolean transition = (rx_sample != rx_last_sample);
if(simpleRXMode == 2 || simpleRXMode == 1) {
rx_count++;
}
// Receive data
if (transition)
{
if(simpleRXMode == 0) {
simpleRXMode = 1;
return;
}
if((simpleRXMode == 1 && rx_sample == 1) && (rx_count >= MinCount && rx_count <= MaxCount)) {
transitionCount++;
if(transitionCount == 2) {
simpleRXMode = 2;
return;
}
}
if(rx_count >= MinLongCount && rx_count <= MaxLongCount) // was the previous bit a double bit?
{
rx_count = 0;
AddManBit(&rx_manBits, &rx_numMB, &rx_curByte, rx_data, rx_last_sample);
bitsRead++;
}
else if( rx_count >= MinCount && rx_count <= MaxCount )
{
rx_count = 0;
// Add the current bit
AddManBit(&rx_manBits, &rx_numMB, &rx_curByte, rx_data, rx_sample);
bitsRead++;
}
if (bitsRead > 7) // for simplicity, only sending 8 bits at a time
{
rx_mode = RX_MODE_MSG; // say we're done
simpleRXMode = 0; // go back to beginning
rx_data = 0; // clear data
bitsRead = 0; // no bits read
transitionCount = 0;
}
}
else if( (simpleRXMode == 1 || simpleRXMode == 2) && rx_count > MaxLongCount) // no transition & it's been too long
{
rx_count = 0; // clear data
simpleRXMode = 0; // go back to beginning
rx_data = 0; // clear data
bitsRead = 0; // no bits read
transitionCount = 0;
}
// Get ready for next loop
rx_last_sample = rx_sample;
}
joshuajnoble:
I'm setting a timer interrupt on TIMER1, would this somehow affect the timing in my sketch (other than introducing another method to run at an interval)? ...Tiny core...
Hi, thanks for clarifying that. I'm actually using the MIT version from Mellis https://github.com/damellis/attiny/zipball/Arduino1 because it seems like it's being developed more actively. Hence, I was trying to work with a timer overflow interrupt on Timer1.