SpenceKonde / ATTinyCore

Arduino core for ATtiny 1634, 828, x313, x4, x41, x5, x61, x7 and x8
Other
1.57k stars 306 forks source link

ATtinycore, ATtiny85, Serial and PinChangeInterrupt.h #499

Closed mrWheel closed 3 years ago

mrWheel commented 3 years ago

Hi Spence,

Setup: ATtiny85 (optiboot, 8MHz) ATtinycore (1.4.1) attachPCINT(digitalPinToPCINT(_PIN_PB3), ISRgetByte, RISING); using builtin Serial @19200 baud (AIN0 / PB0) RX switched off as in documentation

    //--- disable RX
    ACSR &=~(1<<ACIE);
    ACSR |=~(1<<ACD);

The ISRgetByte function collects bits from _PIN_IN and makes a char out of every 8 bits and then sets bool hasChar to true

In the "main loop" every time hasChar is true it will print the char to Serial

And thats where it goes terribly wrong.

As long as there's no interrupt fired the output comes out just fine! But as soon as there is an interrupt (which is constantly!) the output to Serial gets garbidged.

Same sketch with a Arduino UNO works just fine so it has to do with Serial getting messed-up with interrupts (or visa versa).

Is this a known problem? How can I get this to work?

Output from ATtiny85:

15:51:41.847 -> 
15:51:41.847 -> ===== ATtinyPLL2 =====
15:51:43.314 -> ........................................
15:52:42.197 -> ......S,X⸮`„
15:52:51.216 -> S,X⸮`„
15:52:52.146 -> S,X⸮`„
15:52:53.093 -> S,X⸮`„
15:52:54.044 -> S,X⸮`„
15:52:54.993 -> S,X⸮`„
15:52:55.910 -> ST̘0`⸮⸮&P0`‚⸮⸮⸮@pԸ&⸮0d⸮rFL⸮4`⸮⸮R⸮
15:52:58.351 -> B`⸮ @..........
15:53:14.808 -> .........................

On the Arduino UNO the output looks like this:

15:21:41.847 -> 
15:21:41.847 -> ===== ATtinyPLL2 =====
15:21:43.314 -> ........................................
15:22:42.197 -> ......SSSSSSSS*000000A900A885FA8570A2028672A50085FBA601A57049FF85/1200
15:23:14.808 -> .........................
SpenceKonde commented 3 years ago

Well, you haven't posted your code so I can't comment definitively, but it sounds to me like you are trying to decode a continuous datastream using timing-critical interrupts at the same time that you are outputting via a serial (UART) port...

That requires a hardware UART, which can transmit in the background without the CPU's attention.

The ATtiny85 does not have one of those. We provide a software serial implementation named Serial for convenience (and it doesn't grab onto all the PCINTs like the SoftwareSerial if you want to receive), and name it Serial for convenience - but it's still a software serial port. It requires the processor's full attention while transmitting or receiving. While either transmitting or receiving, it will disable interrupts (the lengths of the bits are timed by counting CPU clock cycles). And yes - that kind of sucks. I hate software serial, and a desire for Arduino support for a good ATtiny with hardware serial is how I got into these cores in the first place.

To make that work on a tinyAVR device, you'd need to go to different hardware .

Staying in the world of classic AVRs, the ATtiny841 would be a good bet; they're the cheapest classic tiny with hardware serial (they also have two hardware serial ports, and are generally incredibly capable parts - the peripheral loadout is more typical of the smaller ATmega parts!). This will run the existing code likely with virtually no modifications. The ATtiny841 is supported by ATTinyCore. Other options would be the '4313, '167/87, '828, or '1634 - but the '841 is the one you want I reckon)

Stepping into the world of modern (post-2016, modern peripherals, AVRxt instruction set variant - also cheaper), the ATtiny402 or 412 would be able to do it in an 8-pin package if your code will fit in 4k of flash (sadly, they didn't make an 8k one in the 8-pin package) - otherwise one of the parts in 14-pin package (1604 (or 804) or the 1614 (or 814); the ATtiny1614 is pretty much my go-to microcontroller these days - incredibly capable, and dirt cheap). These have a hardware serial port as well. This may require code modifications depending on how low-level the pin interrupt code is. The ATtiny412 and the rest of the tinyAVR 0/1-series are supported by megaTinyCore. All parts it supports would be capable of the task as I understand it.

mrWheel commented 3 years ago

Thanks Spence, I have some experience with ATtiny841. Will give that one a try.

SpenceKonde commented 3 years ago

Cool, yeah - they're a great part. They're not post-2016 grade, those are just next level - but moving to the new parts definitely takes a bit of adjustment.