ATTiny84 & SoftwareSerial

Go To Last Post
21 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm working with an ATTiny84 in Arduino IDE 1.8.5 with ATTinycore installed.

 

I'm trying to use softwareserial to talk to a serial LCD, but am having some problems.  I decided to strip things back to the simplest form I could and test communication to my PC.

 

Based on comments in another thread, I have setup my program to send out a stream of "U"s and measured the frequency on the serial port with an oscilloscope.  Frequency stays around 4.926Khz, but will occasionally drift to 4.464 or 4.237. (See UsOsc.jpg attached)

 

In my terminal window, I see a constant stream of U's as expected. (See UsTerm.jpg attached)  The problem starts when I try to send anything else.  For instance, if I change the code to send "B" instead of "U" I get garbage in the terminal. (See BsTerm.jpg) Or if I try to use Serial.println("TEST"), I just get garbage. (See TestTerm.JPG)  Granted, it's the same garbage string repeated over and over.  Having it send a U every 5 seconds gives the results in U5sTerm.jpg

 

Code for all tests is below.  The "digitalWrite"s are for some LEDs I was using to make sure I had the pin numbers correct and track where my code was during execution.

 

Any suggestions?

 

Test code for for stream of U's:

/*
 * Define TX/RX pins for software serial.
 */
#define RX  0   // Physical 13
#define TX  1   // Physical 12
#define TEST_PIN1 8  // Physical 5
#define TEST_PIN2 9  // Physical 3

#include <SoftwareSerial.h>

SoftwareSerial myserial(RX, TX);

void setup() {
  pinMode(TEST_PIN1,OUTPUT);
  pinMode(TEST_PIN2,OUTPUT);
  delay(1000);
  
  digitalWrite(TEST_PIN1, HIGH);
  delay(500);
  digitalWrite(TEST_PIN1,LOW);
  delay(500);
  digitalWrite(TEST_PIN1, HIGH);
  delay(1000);
  digitalWrite(TEST_PIN1,LOW);
  delay(1000);
  digitalWrite(TEST_PIN2, HIGH);
  delay(500);
  digitalWrite(TEST_PIN2,LOW);
  delay(500);
  digitalWrite(TEST_PIN2,HIGH);
  delay(1000);
  digitalWrite(TEST_PIN2,LOW);
  delay(1000);
 
  pinMode(RX, INPUT);
  pinMode(TX, OUTPUT);
  digitalWrite(TX, HIGH);
  delay(10);
  OSCCAL-=4;
  myserial.begin(9600);
  //myserial.println("TEST");

}


void loop() {
  //myserial.println("TEST");
  //delay(5000);
    myserial.print("U");

}

Test code for Stream of B's:

/*
 * Define TX/RX pins for software serial.
 */
#define RX  0   // Physical 13
#define TX  1   // Physical 12
#define TEST_PIN1 8  // Physical 5
#define TEST_PIN2 9  // Physical 3

#include <SoftwareSerial.h>

SoftwareSerial myserial(RX, TX);


void setup() {
  pinMode(TEST_PIN1,OUTPUT);
  pinMode(TEST_PIN2,OUTPUT);
  delay(1000);
  
  digitalWrite(TEST_PIN1, HIGH);
  delay(500);
  digitalWrite(TEST_PIN1,LOW);
  delay(500);
  digitalWrite(TEST_PIN1, HIGH);
  delay(1000);
  digitalWrite(TEST_PIN1,LOW);
  delay(1000);
  digitalWrite(TEST_PIN2, HIGH);
  delay(500);
  digitalWrite(TEST_PIN2,LOW);
  delay(500);
  digitalWrite(TEST_PIN2,HIGH);
  delay(1000);
  digitalWrite(TEST_PIN2,LOW);
  delay(1000);
 
  pinMode(RX, INPUT);
  pinMode(TX, OUTPUT);
  digitalWrite(TX, HIGH);
  delay(10);
  OSCCAL-=4;
  myserial.begin(9600);
  //myserial.println("TEST");

}


void loop() {
  //myserial.println("TEST");
 // delay(5000);
    myserial.print("B");

}

Test code for "TEST" String:

 

/*
 * Define TX/RX pins for software serial.
 */
#define RX  0   // Physical 13
#define TX  1   // Physical 12
#define TEST_PIN1 8  // Physical 5
#define TEST_PIN2 9  // Physical 3

#include <SoftwareSerial.h>

SoftwareSerial myserial(RX, TX);

void setup() {
  pinMode(TEST_PIN1,OUTPUT);
  pinMode(TEST_PIN2,OUTPUT);
  delay(1000);
  
  digitalWrite(TEST_PIN1, HIGH);
  delay(500);
  digitalWrite(TEST_PIN1,LOW);
  delay(500);
  digitalWrite(TEST_PIN1, HIGH);
  delay(1000);
  digitalWrite(TEST_PIN1,LOW);
  delay(1000);
  digitalWrite(TEST_PIN2, HIGH);
  delay(500);
  digitalWrite(TEST_PIN2,LOW);
  delay(500);
  digitalWrite(TEST_PIN2,HIGH);
  delay(1000);
  digitalWrite(TEST_PIN2,LOW);
  delay(1000);
 
  pinMode(RX, INPUT);
  pinMode(TX, OUTPUT);
  digitalWrite(TX, HIGH);
  delay(10);
  OSCCAL-=4;
  myserial.begin(9600);
  //myserial.println("TEST");
}


void loop() {
  myserial.println("TEST");
  delay(5000);
//    myserial.print("B");
}

 

Attachment(s): 

Last Edited: Fri. Jan 19, 2018 - 04:18 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm working with an ATTiny84

Is this an Arduino board or a chip on a self built board? Is the chip running at 16MHz which, I believe, is what the code expects?

 

What is OSCCAL=4; doing if you have a crystal?
 

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

js wrote:

I'm working with an ATTiny84

Is this an Arduino board or a chip on a self built board? Is the chip running at 16MHz which, I believe, is what the code expects?

 

What is OSCCAL=4; doing if you have a crystal?
 

 

The ATTiny84 is a chip that I'm programming with the Arduino IDE.  The chip is running from it's internal 8Mhz oscillator.  Based on the prior thread I linked in the original post I had the chip send out a stream of U's and monitored the frequency with the oscilloscope and adjusted OSCCAL until I was as close to 4.8khz as I could get.

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sigh.

I refuse to comment any further on the combination of RC oscillator and uart.

Paul van der Hoeven.
Bunch of old projects with AVR's:
http://www.hoevendesign.com

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Paulvdh wrote:

Sigh.

I refuse to comment any further on the combination of RC oscillator and uart.

 

Well, I am absolutely brand new to Arduino and AVR.  I know it's not as stable as a crystal, but I thought I might be able to get some serial out of it, even if it were only 300bps.  The project I'm building doesn't require the serial, I'm really just trying to teach myself a new skill, and get familiar with a new tool.  I know the basics of using an oscilloscope, but have never had access to one before, so it's new too.  I'm kinda learning to swim by jumping into the deep end with a shark just out of sight.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok, I'll bite.

 

RC oscillator is about 3% accurate over the temperature range, pending on proper calibration.

uart needs better than approx 1.5% for reliable operation.

So you have about 50% chance it works (reliably).

This is under the assumption that the "other side" of the cable has an accurate clock.

 

This is independent of the used baud rate.

 

What I can  (and really want to) recommend though is to buy a cheap logic analyser.

Search for "24MHz 8ch" on Ali / Ebay.

These boxes cost about USD 5 and are (arguably) more useful for debugging uC circuits than a USD 300 Rigol Scope.

They work pretty well with Pulseview / Sigrok.

https://sigrok.org/

https://www.youtube.com/watch?v=...

 

Unfortunately its sometimes a bit difficult to get Pulseview working on your PC.

 

These boxes also work with the Salaea software.

Salaea has the marketing strategy to sell the hardware and give the software away for free.

I'm not sure what their viewpoint is on using this box with their software.

They used to sell the same hardware as the "24MHz 8ch" for USD 100 in a fancy aluminimum box.

The cheapest hardware they sell now is USD400 for an 8 channel logic analyser.

Such a price will be unacceptable for a hobbyist, most "professionals" will opt for a full blown MSO scope of about the same price...

I'm sure they are nice people (heard good rumours) and I wish them well, but I can't see this working for very long.

I suspect they are going the same way as USBee.

USBee went broke a few years ago.

The old "24MHz 8ch" from Salaea has the same hardware as the USBee SX, a Cypress CY7C68013A-56PVXC

(Almost any box with that cypress processor is supported by Sigrok. Look at their supported hardware page. )

 

https://www.discovery.com/tv-sho...

 

I'll stop ranting, I'm afraid i'm drifting too far off topic here...

Paul van der Hoeven.
Bunch of old projects with AVR's:
http://www.hoevendesign.com

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Paul's, no worries about rambling. I greatly appreciate the information. I got a Hantek DSO3254 for Christmas. It has a 16 channel logic analyzer built in. (4-channel 250mhz scope, 16 channel logic analyzer, function generator, the works) I've done troubleshooting on old arcade games and pinball machines, but only played with Basic Stamps 15 years ago as far as micross controllers go.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Dr.Arclight wrote:
I got a Hantek DSO3254 for Christmas

Hmm, yes. You should be able to measure a baudrate with that.

Paul van der Hoeven.
Bunch of old projects with AVR's:
http://www.hoevendesign.com

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

On the B test, try putting a delay of 110 microseconds { delayMicroseconds(110); } after writing the character.  This will pause the system long enough to fully transmit the character.  This prevents the buffer getting overwritten.  That would be the result from having the loop() function repeatedly write the 'B' char to the SoftwareSerial function as fast as possible.  SoftwareSerial on a Tiny AVR that has no hardware UART is tricky in assembler, never mind in C++.   I don't recommend fooling around with Tiny AVRs if one is a beginner.  Get a couple of Arduino Nano or UNO boards (they are about $3-5 each on eBay) because they are stable, reliable, tested,  documented, and have good hardware (and libraries) to handle interfacing like I2C, UART, and SPI.  Tiny AVRs save money when making 100+ quantities of an individual design, but their lack of peripherals in hardware makes them infuriating for beginners to use.

 

As far as the OSCCAL issue goes, if you have adjusted the frequency to show 9600/2 Hz on the scope with a "U" sequence, then it should be transmitting and receiving OK at 9600 baud. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well, I have added a crystal, and the results have not changed.  I can still transmit a constant stream of U's, but when I try to send anything else, I get garbage.  Have tried with 8Mhz, 16Mhz, and 20Mhz crystals, and set fuses to dump clock to PB2 so I can monitor on the scope.  Got a bit of ringing on the clock signal from being on a breadboard, but the frequency stays steady.

 

I've tried the logic analyzer portion of my Hantek scope, and basically, it's DOA.  Either that or the instructions are completely wrong.  

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Dr.Arclight wrote:

  The problem starts when I try to send anything else.  For instance, if I change the code to send "B" instead of "U" I get garbage in the terminal.

 

You've used your scope to verify that the cpu clock is correct and steady.

 

Now use the scope on the Tx output pin to capture the serial output that causes the LCD to display garbage.

 

Instead of a continuous stream of chars, it helps in reading the chars on the scope to put a 3ms delay between the characters.

 

With the scope you can see just what the hardware/software is generating.

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Chuck99 wrote:

Dr.Arclight wrote:

  The problem starts when I try to send anything else.  For instance, if I change the code to send "B" instead of "U" I get garbage in the terminal.

 

You've used your scope to verify that the cpu clock is correct and steady.

 

Now use the scope on the Tx output pin to capture the serial output that causes the LCD to display garbage.

 

Instead of a continuous stream of chars, it helps in reading the chars on the scope to put a 3ms delay between the characters.

 

With the scope you can see just what the hardware/software is generating.

 

 

 

Yeah, I tried that.  Unfortunately, the software that goes with this Hantek scope is, well, crap.  Great for viewing viewing a static waveform, but recording or analyzing digital data just doesn't work.  I've already taken the LCD out of the equation and just connected directly to my serial port on my PC and tried sending data there to be sure the LCD wasn't just screwy.

 

At this point I've decided to just scrap the serial portion of this project.  I don't really need it anyway.  It was just going to provide some extra debugging data on the bench.  I am mounting a gimbal on a drone that doesn't have a native interface to control the gimbal, but does have a signal line for sending photo and video start/stop commands to a camera.  The cameras I have are all wifi control and don't use those signals so I'm using an ATTiny84 to translate those commands into gimbal up/down commands.  The serial was just going to be used to debug on the workbench, but I can just use LED blinks instead.

 

I just hate letting a problem win.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Why employ a tiny84 and then have to implement soft-UART? You can buy a million different 8 bit micros that have a real UART in them if your design has the requirement for a UART. Why make it hard on yourself?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
if your design has the requirement for a UART. Why make it hard on yourself?

+999

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

First can the PC talk with the display?

 

Are you sure that the levels are correct, it could be that you need to invert the signal! (since you use a SW uart it should be simple).

 

I don't know anything about the SW uart you use is it ISR driven ?

 

And do you use other ISR's at the same time it could be a problem depending of the uart  implementation.

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/libraries/SoftwareSerial/src/SoftwareSerial.cpp

 

ca line 430 ;: ISR are desabled during transmit.

seems level inverting is taken care of (cannot find lines : at line ~150, _inverse_logic is tested and comments hint inverting levels is possible)

hope github link  is the same SoftwareSerial, the official one OP uses

 

 

If a Xal is added, it eats pins, on a tiny chip....

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 2

If you just add a one, you get two for free wink.

 

I mean, ATtiny841 is the successor of '84. It comes with two hardware USART's, a better RC oscillator and a lot of other goodies.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

Why employ a tiny84 and then have to implement soft-UART?...

snigelen wrote:

If you just add a one, you get two for free wink.

 

I mean, ATtiny841 is the successor of '84. It comes with two hardware USART's, a better RC oscillator and a lot of other goodies.

+1000

"void transmigratus(void) {transmigratus();} // recursio infinitus" - larryvc

"It's much more practical to rely on the processing powers of the real debugger, i.e. the one between the keyboard and chair." - JW wek3

"When you arise in the morning think of what a privilege it is to be alive: to breathe, to think, to enjoy, to love." -  Marcus Aurelius

"Make XMEGA Great Again!"  - Greg Muth

Last Edited: Wed. Jan 24, 2018 - 05:27 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
Why employ a tiny84 and then have to implement soft-UART?

I guess it's like banging your head against a brick wall - it's so nice when you stop!

 

cheeky

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

First:

Why waste your time on software uart Especially when #17 & #18 ?

 

Why wate 7s on each startup?

 

 

  delay(1000);
  
  digitalWrite(TEST_PIN1, HIGH);
  delay(500);
  digitalWrite(TEST_PIN1,LOW);
  delay(500);
  digitalWrite(TEST_PIN1, HIGH);
  delay(1000);
  digitalWrite(TEST_PIN1,LOW);
  delay(1000);
  digitalWrite(TEST_PIN2, HIGH);
  delay(500);
  digitalWrite(TEST_PIN2,LOW);
  delay(500);
  digitalWrite(TEST_PIN2,HIGH);
  delay(1000);
  digitalWrite(TEST_PIN2,LOW);
  delay(1000);

 

The soft serial, just as the hardware version, is probably interrupt based.

So if you put it in a loop it will overwrite it's own data or do other strange stuff.

Wait at least 100ms or so after starting up a communication before a retry.

 

Screenshots of a terminal showing garbage is useless.

Why don't you put your scope to the serial port?

Paul van der Hoeven.
Bunch of old projects with AVR's:
http://www.hoevendesign.com

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Why do I wait 7 seconds on startup?  Because I wanted the lights to blink that way.  There was no point in it, other than making sure I had the correct physical pin to Core pin mappings.

 

Why use an AtTiny84?  Because I had some in my spare parts bin from some other project I don't remember and it does everything I need it to do.  This is a one-off project and a learning project.  I don't care about the UART because, once I know the chip is behaving correctly on my workbench I intend to delete all the serial stuff anyway.  I started with an ATTiny85, but had to use the SoftwareServo library instead of the "Servo" library and was having compiling issues.

 

Can the PC Talk to the LCD? Yes.  PC can talk to the LCD just fine.  Attiny84 can't talk to either PC or LCD unless it's a stream of U's  The LCD also speaks SPI, but I was unable to get the ATTiny84 to speak to the LCD as a SPI master either.

 

Thanks to all that replied, but for the time being I've put this project to bed.  Too cold to fly my drone anyway.