Thursday, June 13, 2013

Serial Communication on a ATtiny85 with the SoftwareSerial Library.

"Serial is giving me errors on my ATtiny! What can I do?" We have a solution.

Serial communication is not difficult on an ATtiny thanks to the SoftwareSerial Library. While the ATtiny85 does not have the hardware of a "real" Arduino, it can still function in similar fashion. If you're just getting started with using an ATtiny, here are some resources you might need.

  • Information on programming them from High-Low Tech. You can also look back at my previous posts.
  • My nifty programming adapter. A few minutes of soldering made my life much easier.
  • My USBtinyISP is discussed in THIS post. It also makes life easier.
  • Previous posts on Running Servos and the NewPing Library on an ATtiny.
  • THIS previous post mentioning my USB to UART converter cable
Now we are ready to go. First things first, I am using Arduino 1.0.4. The SoftwareSerial Library is included as a default library, so there is no reason to get a 3rd party library.


Step One: Wire it up. With my USB to UART cable it is as follows.
  • Black: Ground
  • Green: Tx (using Tx as pin 4)
  • White: Rx (using Rx as pin 3)
  • Red: 5v (this is optional if you have an external power supply)
Connect an LED with appropriate resistor to pin 1.

Step Two: Ensure that your ATtiny is burned to run at 8MHz. Now load THIS sketch onto the ATtiny. Note that parseInt() works with the SoftwareSerial Library.

Step Three: Open the Serial Monitor and set it to the correct Baud rate. To reset the ATtiny, bridge the reset pin to ground momentarily. When you see the connected message, enter an integer and count the flashes.

That's all there is to it. I you don't have a USB UART cable, this is easily adaptable to communication with another Arduino with a USB port. See THIS post for code. If you want to see a practical application of serial communication on an ATtiny85, check out my serial sonar controller HERE.

Hope this works for you all. As usual, if there are any questions, just let me know.
-Matthew

28 comments:

  1. Hi Matthew,

    Thank you for this post.

    I am having problems with the baud rate.

    In my serial monitor I am getting data (as 'yyyy')

    But i have both the attiny85 at 9600 and my monitor at the same.

    Any ideas in what to do to debug this?


    Thanks

    ReplyDelete
  2. Hi William. Thanks for reading and commenting.


    I forgot to mention that the ATtiny needs to be running at 8MHz. If I had to guess a problem that would be it.


    Otherwise I would wiggle the wires, restart the ATtiny, and reinstall the UART drivers. If none of that works, comment again and we will see what we can do.

    ReplyDelete
  3. I am getting this error: 'class SoftwareSerial' has no member named 'parseInt'
    I don not understand because I am running the attiny85 at 8MHz and I am using Arduino Uno as the ISP. Please help.

    ReplyDelete
  4. I am getting this error: 'class SoftwareSerial' has no member named 'parseInt'

    I don not understand because I am running the attiny85 at 8MHz and I am using Arduino Uno as the ISP. Please help.

    ReplyDelete
  5. Hi Tom,

    Check out this link http://forum.arduino.cc/index.php?topic=185122.0

    You may just need a different core. Try this one https://code.google.com/p/arduino-tiny/



    Also, make sure you have a recent IDE version.


    Is this one of the examples? If not, check for typos and make sure your include is right. If you could, comment back with the results whatever they are. It helps to see and document what kind of problems people may encounter

    ReplyDelete
  6. I'm having the same problem. Using IDE versions 1.0.3 and 1.0.5, and I would try the beta version 1.5.2 except that I can't figure out how to get the ATtiny chips to show up in that version. They show in the stable releases though, so that's not my problem. I'm also using the example code SoftwareSerialBlink.ino that I downloaded from this page.

    It's the same parseInt problem that Tom is/was having.

    Also thank you very much for writing up this how to and example code, I'm really looking forward to getting it working!!

    ReplyDelete
  7. I'm not sure what the problem is. It compiles just fine for me on both 1.0.3 and 1.0.5. No chance the library has been changed or something, right? I am no expert, but the way I understand it SoftwareSerial inherits parseInt from Stream.h. Does parseInt work with your regular Serial library?


    Before you dig too much into that I would download a fresh copy of 1.0.5 and drop in a fresh copy of the ATtiny core from Google code.


    if all that fails, you could do a simple read() and then combine them into an int in code. I know there are various methods of doing that online.

    ReplyDelete
  8. Hi Mathew.
    I just found your writeup.
    If I need serial communication and also need 2x digital (or analog) inputs, is it possible using this Attiny45 ?
    If so, which pins I can use as inputs ?

    Sincerely
    -bino-

    ReplyDelete
  9. Yes that is possible. See the pinout chart above. As far as I know, any of the IO pins can be used with SoftwareSerial. Then you can use whichever ones you don't need for other things. If you need serial and more than 3 IO pins, you could also use the reset pin as an IO. http://projectsfromtech.blogspot.com/2013/04/using-reset-pin-as-io-on-attiny8545.html


    Hope that helps

    ReplyDelete
  10. Does this require the Software SERVO library or is that a typo and you mean Software Serial?

    ReplyDelete
  11. Yes that was a typo. Projects running together. I updated the post.
    Thanks for pointing that out.

    ReplyDelete
  12. is attiny85 have minimum system ?

    ReplyDelete
  13. I'm not sure I understand your question. Can you please rephrase it?

    ReplyDelete
  14. yes "minimum system" , the minimum system to use attiny85.
    something like arduino uno (minimum system of atmega328), there is some component like crystal, capasitor, resistor, etc

    ReplyDelete
  15. Ok. Well from your example the ATtiny would be like the atmega328 in an Arduino. I think it is the "minimum system" you are looking for. If you want to run it at 8MHz, you don't need a crystal. Just connect it to 5V and Ground (assuming the fuses are set correctly).


    That is all you really need. A decoupling capacitor might be nice if you are using a messy power supply. You might look at my ATtiny label if you want more information on using an ATtiny with the Arduino IDE.

    ReplyDelete
  16. On a fresh 1.0.5 install with the core from the link provided (https://code.google.com/p/arduino-tiny/), I also get the ParseInt-error.. the person with the same problem on the arduino forum got his problem fixed, but didn't care to share the actual solution..

    ReplyDelete
  17. So that didn't fix the problem. Well it could be that I actually used the high-low tech ATtiny core for this post. It's hard for me to keep up with it, but I don't think I used that one for very long. I would just suggest you triple check that you are running at 8MHz and have everything installed correctly. If you find a solution, let us know though.


    If it turns out to be really bothersome, I might just go with a serial.read and combine them myself.

    ReplyDelete
  18. I also get the error ‘class SoftwareSerial’ has no member named ‘parseInt’ with 1.0.5. Looked around the internet and tried a few things but no luck. Why don't you change your example program so it doesn't use parseInt()? It would be so nice if your download just worked for everyone.

    ReplyDelete
  19. Well I didn't change it originally because I didn't know any better. Unfortunately for the reader this blog has to follow my own learning path. I didn't realize it was a widespread problem.

    I changed it a bit so that it doesn't use parseInt(). I don't have time to test it right now, but I will post it so you can try it. Let me know if it works (or doesn't).

    https://drive.google.com/file/d/0B6s_UhmkBLQfa0Nwc3hwUHpwZjQ/edit?usp=sharing

    ReplyDelete
  20. When I look at Stream.cpp in the tiny core the parseInt() and other parse functions are not present. My guess is this was done to keep the image size small for the tiny chips. So it is a mystery how it could work for anyone using the tiny core because the code is simply not there. With that said, the easiest approach is to copy the class methods necessary to support parseInt() from the 1.0.5 core and fix them to compile as stand alone functions. It adds about 50 lines of code to the example and it compiles good but I will not be able to test it on my tiny85 until later this evening.

    ReplyDelete
  21. Tested and it works. I used ArduinoISP on my UNO to program the Tiny85 and then a PL2303 usb cable for the serial connection which I connected to with the serial port terminal program GtkTerm on Linux.

    /*

    Software serial multple serial test

    Receives an integer from the software serial, blinks an LED that number of times, and returns a confirmation.

    The circuit:

    * RX is digital pin 10 (connect to TX of other device)

    * TX is digital pin 11 (connect to RX of other device)

    Note:

    Not all pins on the Mega and Mega 2560 support change interrupts,

    so only the following can be used for RX:

    10, 11, 12, 13, 50, 51, 52, 53, 62, 63, 64, 65, 66, 67, 68, 69

    Not all pins on the Leonardo support change interrupts,

    so only the following can be used for RX:

    8, 9, 10, 11, 14 (MISO), 15 (SCK), 16 (MOSI).

    This code has been modified for use on an ATtiny.

    Created by Matthew on June 11, 2013

    http://projectsfromtech.blogspot.com/

    This example code is in the public domain.

    */

    #include <SoftwareSerial.h>

    SoftwareSerial TinySerial(3, 4); // RX, TX

    //-------------------------------------------------------------------

    /*

    The tiny core doesn't support SoftwareSerial.parseInt()

    so these methods are copied from the arduino 1.0.5 core

    Stream.cpp with very minor modifications so they will work

    outside the class as stand alone subroutines.

    */

    unsigned long startMillis; // used for timeout measurement

    int timedPeek(){

    int c;

    startMillis = millis();

    do {

    c = TinySerial.peek();

    if (c >= 0) return c;

    }

    while(millis() - startMillis < 1000);

    return -1; // -1 indicates timeout

    }

    int peekNextDigit(){

    int c;

    while (1) {

    c = timedPeek();

    if (c < 0) return c; // timeout

    if (c == '-') return c;

    if (c >= '0' && c <= '9') return c;

    TinySerial.read(); // discard non-numeric

    }

    }

    long parseInt(void){

    boolean isNegative = false;

    long value = 0;

    int c;

    c = peekNextDigit();

    // ignore non numeric leading characters

    if(c < 0)

    return 0; // zero returned if timeout

    do{

    if(c == '-')

    isNegative = true;

    else if(c >= '0' && c <= '9') // is c a digit?

    value = value * 10 + c - '0';

    TinySerial.read(); // consume the character we got with peek

    c = timedPeek();

    }

    while(c >= '0' && c <= '9');

    if(isNegative)

    value = -value;

    return value;

    }

    //-------------------------------------------------------------------

    void setup()

    {

    // Open serial communications and let us know we are connected

    TinySerial.begin(9600);

    TinySerial.println("Tiny Serial Connected via SoftwareSerial Library");

    pinMode(1, OUTPUT);

    }

    void loop()

    {

    if(TinySerial.available())

    {

    int received = parseInt(); // get an integer from serial input

    TinySerial.print("Received data...");

    TinySerial.println("Flashing LED");

    if(received >=30) //So it doesn't blink 150 times when you type 150 instead of 15

    received = 30;

    Blink(1, received); //Blink the LED on pin 1

    }

    }

    void Blink(byte led, byte times){ // poor man's display

    for (byte i=0; i< times; i++){

    digitalWrite(led,HIGH);

    delay (250);

    digitalWrite(led,LOW);

    delay (175);

    }

    }

    ReplyDelete
  22. I just tried it with fuses for ATtiny85 @ 16 MHz (internal PLL; 4.3 V BOD) and it works fine there also. Thanks Mathew, I would probably still be using the "poor man's display" if I hadn't found this page. :-)

    ReplyDelete
  23. Please tell us how did you fix it! I found the tiny core folder but I'm not sure what should I add there.

    ReplyDelete
  24. The fixed example source is listed above in my post, just use it as is. I don't recommend changing the core files.

    ReplyDelete
  25. @William turner
    I had the same. Use Arduino SoftwareSerial also on your Arduino Uno. http://arduino.cc/en/Tutorial/SoftwareSerialExample

    When I connect to the harware serial I got 'yyyyyyy', when connecting to software pins it's working!!!

    ReplyDelete
  26. Hi Mathew, Thanks for your valuable guidance. I have tried your instructions on ATTiny45. Everything was OK during programming stages and the HC06 bluetooth paired with the laptop bluetooth succesfuly. However, the comments sent by the ATTiny45 were received as a continuous stream of unrecognized characters on the Putty serial monitor and the LED does not blink either. The baud rate was 9600 which I had used before while communicating arduino uno with HC06 succesfuly. Is the problem related to ATTiny 45 or what else may be the reason for these unexpected characters? I would be very pleased if you could guide me to sort out this problem.

    ReplyDelete
  27. Well if your baud rates are the same on both the the ATtiny and the serial monitor I would reflash the ATtiny. Make sure it is at 8MHz. You might try just using the Arduino serial monitor too. I haven't used Putty much but I suppose it might have some different settings turned on.

    ReplyDelete
  28. Thanks for you kind comments Mathew. I have tried the Arduino serial monitor too, but I got the similar results. Later on, I have tried the ATtiny85 and now the LED is blinking, but the messages coming from ATTiny are received at the serial monitor as either 0, 80 or 128 in Hex (meaningless characters like €€ or <0> in ASCII). Moreover, the LED always blinks to the maximum value, whatever number I send from the serial monitor. This means that, the number I send is not recognized correctly by the ATTiny85 either. Do you think there is an encoding problem, or what else?

    ReplyDelete