ATTiny85 Calibration

Hey everyone,

I’ve been trying for some time to get serial communication working on the ATtiny85.
Iv’e been receiving garbage in the serial monitor and read that sometimes calibration may be necessary.

I decided to try Coding Badly’s TinyTuner2 for the task but am running into some issues.

My setup is identical to the one described here, with the addition of a jumper wire connecting pin 3 on the UNO with pin 3 (aka PB4) on the ATtiny85 as instructed here.

I’m using the ATtinyCore.

I was able to burn the UNO with the TinyISP sketch, but am having trouble with compiling the PrintUsingSerial and PrintUsingKnockBang sketches.

For PrintUsingSerial The compilation fails with the following error:

C:\Users\DANARA~1\AppData\Local\Temp\arduino_modified_sketch_617253\PrintUsingSerial.ino: In function 'void setup()':

PrintUsingSerial:36:3: error: '_delay_ms' was not declared in this scope

   _delay_ms( 1000 );

   ^~~~~~~~~

C:\Users\DANARA~1\AppData\Local\Temp\arduino_modified_sketch_617253\PrintUsingSerial.ino:36:3: note: suggested alternative: 'delay'

   _delay_ms( 1000 );

   ^~~~~~~~~

   delay

exit status 1
'_delay_ms' was not declared in this scope

I was able to compile and upload by either:

  • Changing the _delay_ms(1000) statement to a delay(1000) statement.
  • Adding #include <util/delay.h> like in PrintUsingKnockBang

In both cases I get nothing in the serial monitor (I’ve tried setting it to both 19200 as instructed here, and to 250000, which is what I’ve seen inside the sketch).

For the PrintUsingKnockBang I get different compilation errors:

C:\Users\DANARA~1\AppData\Local\Temp\cc8gXqHK.s: Assembler messages:

C:\Users\DANARA~1\AppData\Local\Temp\cc8gXqHK.s:43: Error: unknown opcode `delay_fine'

C:\Users\DANARA~1\AppData\Local\Temp\cc8gXqHK.s:45: Error: unknown opcode `delay_fine'

C:\Users\DANARA~1\AppData\Local\Temp\cc8gXqHK.s:148: Error: unknown opcode `delay_roug'

C:\Users\DANARA~1\AppData\Local\Temp\cc8gXqHK.s:151: Error: unknown opcode `delay_roug'

C:\Users\DANARA~1\AppData\Local\Temp\cc8gXqHK.s:188: Error: unknown opcode `delay_roug'

C:\Users\DANARA~1\AppData\Local\Temp\cc8gXqHK.s:191: Error: unknown opcode `delay_fine'

C:\Users\DANARA~1\AppData\Local\Temp\cc8gXqHK.s:193: Error: unknown opcode `delay_roug'

lto-wrapper.exe: fatal error: C:\Users\Dan Arad\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7/bin/avr-gcc returned 1 exit status

compilation terminated.

c:/users/dan arad/appdata/local/arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/../lib/gcc/avr/7.3.0/../../../../avr/bin/ld.exe: error: lto-wrapper failed

collect2.exe: error: ld returned 1 exit status

exit status 1
Error compiling for board ATtiny25/45/85 (No bootloader).

Any help would be appreciated.

I don't currently have code to calibrate the internal oscillator available - it's something I've wanted to do, but there just aren't enough hours in the day.

including util/delay.h is far more likely to work than delay(1000).

I never liked the look of any of that code, and accordingly never played with it.

Regarding the original problem of garbage on serial monitor:

Have you verified that you have fuses configured correctly? Upload blink (modified to point to whichever pin you have an LED on, if necessary) and make sure it blinks about once a second. If it is blinking much slower, or twice as fast, reburn bootloader to set fuses and try again.

Do you have ground connected to serial adapter, in addition to tx/rx? You need that.

Are you trying to send and receive at the same time (echoing each character counts!)? This will not work, software serial is half duplex, not full duplex. The naive echo implementation (eg, if (Serial.available()) {Serial.print(Serial.read());} works for the first character, but subsequent characters get misread. Don't do this.

Assuming it's not one of those, you've found an ATtiny that's not close enough to 8MHz for serial at room temp and 5v (a while back I tried to find one so I could try to make a calibration sketch; went through my bin and all of them worked without cal!) - here's the quick and dirty way to make serial output work - ditch all that wacky shit, and just use SoftwareSerial, or (preferably) ATTinyCore's builtin software serial instance named Serial (it's still got most of the constraints of software serial, but it doesn't eat all your PCINTs)... when you call Serial.begin(), just use a value a few % higher or lower than the baud rate you want :stuck_out_tongue:

Have you verified that you have fuses configured correctly? Upload blink (modified to point to whichever pin you have an LED on, if necessary) and make sure it blinks about once a second. If it is blinking much slower, or twice as fast, reburn bootloader to set fuses and try again.

I preformed the blink test and it seems to blink once a second.

Do you have ground connected to serial adapter, in addition to tx/rx? You need that.

Can you explain it a bit more? In my case what is the "serial adapter"? In the simplest case I connect only 3 pins between the UNO and the ATtiny - VCC (5V), GND and the pin 0 of the ATtiny (TX) to pin 0 of the UNO (RX).

Are you trying to send and receive at the same time (echoing each character counts!)? This will not work, software serial is half duplex, not full duplex. The naive echo implementation (eg, if (Serial.available()) {Serial.print(Serial.read());} works for the first character, but subsequent characters get misread. Don't do this.

I don't do this. Here's my code:

void setup() {
    Serial.begin(9600);
}

void loop() {
    Serial.print("It's alive!");
    delay(1000);
}

Assuming it's not one of those, you've found an ATtiny that's not close enough to 8MHz for serial at room temp and 5v (a while back I tried to find one so I could try to make a calibration sketch; went through my bin and all of them worked without cal!) - here's the quick and dirty way to make serial output work - ditch all that wacky shit, and just use SoftwareSerial, or (preferably) ATTinyCore's builtin software serial instance named Serial (it's still got most of the constraints of software serial, but it doesn't eat all your PCINTs)... when you call Serial.begin(), just use a value a few % higher or lower than the baud rate you want :stuck_out_tongue:

As you can see from my code I'm already using ATTinyCore's builtin SoftwareSerial.
I tried 2 ATtinys so far, but I've bought them in a batch so I have 8 more. I'll try some of the others out.

As a side question: If I have an application that requires 2 way communication, how do I manage that (given what you said about Serial.available)? In my case I know when to expect input, and the output are just debug strings.

I assume you're running an "echo" sketch on the Uno then? At 9600 baud? And serial monitor is set to 9600 baud? that should work... It's fighting the TX line of the serial adapter built into the Uno, but that has a 1k resistor in series with it, so the tiny should easily be able to overcome that.

I just wanted to make sure you weren't connecting to a serial adapter via just TX and RX (or just RX) while the device was externally powered.

A better approach still using the uno would be to connect reset of uno to ground (so the uno is in reset, and all pins are tristated) and connecting the TX of tiny to "TX" pin of Uno. That pin on the uno will be tristated, and it's connected directly to RX of serial adapter on the Uno, so that will take anything the uno is doing out of play.

I would suggest using a proper serial adapter though - they're dirt cheap (like $1-2 each for low end ones), and it takes a bunch of stumbling blocks out of the equation. An Uno is a very bulky, very expensive, sub-optimal serial adapter :stuck_out_tongue:

But yeah, try values a little higher than 9600, and a little lower. Also there's a report of strange problems with low speeds that I haven't had time to investigate. 19200 might be a better choice in general.

A better approach still using the uno would be to connect reset of uno to ground (so the uno is in reset, and all pins are tristated) and connecting the TX of tiny to "TX" pin of Uno. That pin on the uno will be tristated, and it's connected directly to RX of serial adapter on the Uno, so that will take anything the uno is doing out of play.

Worked like a charm! Thank you very much!

Out of curiosity, I would still be happy to understand a bit more of what you replied:

I assume you're running an "echo" sketch on the Uno then?

Actually, no. I burned the ArduinoISP sketch to the UNO, so I could program the ATtiny, and then programmed the ATtiny with the code I showed. I didn't reprogram the UNO again afterwards. I thought data would be automatically transferred to the serial monitor if I send it to the UNO's RX pin (0), and since I saw garbage being printed about once a second, I didn't have a reason to question it.

Should I burn a sketch to the UNO? How do I interact with the data coming from pin 0 (The builtin Serial communicates through the USB going to the computer so I probably can't use that)?

Another question, as I asked before: How do you manage a bidirectional channel to the ATtiny?
If I understand you correctly, the following won't work:

if (Serial.available()) {Serial.print(Serial.read());}

Is this because there is more than 1 byte to process? If so, I just have to make sure to send 1 byte at a time, right?
In this case, assuming I know I want a string, can I use readString()? Do I need to know it's size beforehand?