Arduino like board with more than 2 UARTS

Krupski:
Are you using a character LCD or a graphical one?

Regardless, you should check out the Noritake VFD (vacuum florescent display) devices. They have character LCD drop-in replacements and also KS-108 compatible graphical displays.

Their displays have both parallel and serial interfaces. The serial interfaces are not RS-232, but SPI-like (just like SPI, but using only one line for both MISO and MOSI).

Here's a pic of a few of them. The one on top is a huge 20X4 character display, the one on the right is a 16X2, and the left one is a 128X64 graphics display.

There are also an Arduino driver library for these (the character displays are HD44780 compatible, so they will also work with the stock "LiquidCrystal" library).

Hope this helps...

(click pic for hi-res)
vfd_displays.jpg

(by the way, the orange/yellow tape on the display is a cover sheet to protect the glass. There's a protective sheet on all the displays - they don't come that way but since I use them "in the open" I've got protection for the glass).

Bottom left one looks cool. But the display I use is a full color TFT. You can check it here . The idea behind them is really cool. All the graphical processing is done on the displays own MCU. And it can refresh every element on screen at 40hz+

In a previous project, I tried using regular 2.4" TFT's, even when it's refreshing just a two digit 20 punto field you can see the flickering. My project required refreshing more than half of the pixels on the screen as fast as possible. I knew a normal 8bit arduino wouldn't have cut it.

I was either gonna use something like Teensy(with it's ridicilously fast TFT library) or a TFT which has it's own GPU. I picked the second option. Now I'm thinking maybe I was better off with Teensy....

The Nextion display itself is awesome. But the library and software for it is at best it's infancy. I'd bet good money that if someone like the creator of Teensy created a new library for Nextion, he could reduce the overhead by ten. I'm relatively new to microprocessor programming and even I managed to improve the original library to some extend.

Btw, I really wish capacitive touch TFT's would become the norm. I'm not even after the touch functionality, I just don't like the plastic on top of screen. It scratches too easy and looks like it's from 1980s.

Sparkfun has some capacitive TFT's, but I've only found out about that after I've bough 5 resistive touch TFTs of various sizes and makes off of ebay :confused: And once you are used to paying 3-4$ for something on ebay, spending 20$ is hard :wink:

softserial can be tuned to within 1 clock via nop instruction. uart within 2 clocks at best, so "terribad" in fact that reliable 115k is not possible @16mhz

Software serial is tunable to within a few instruction times. Hardware UART baud rates are limited to integer quotients of (F_CPU/8) and integers. For a 16MHz crystal and 115200bps, the closest you can get is 117647bps - about 2.1% off. That's normally "close enough" (in total, you usually need to be less than 5% difference in clock rates between the two sides. Normally you should have each side with 2.5%, but if the other side is "very accurate" you have additional leeway on the AVR side.)

But that's irrelevant since the main problem is the CPU load caused by SWSerial, and it's inability to receive characters while "unattended." For the HW Uart, the UART TX ISR has to respond within two BYTE times in order to avoid missing a character. For the SW Uart, the pin change interrupt has to respond within one or two BIT times!

westfw:
Software serial is tunable to within a few instruction times. Hardware UART baud rates are limited to integer quotients of (F_CPU/8) and integers. For a 16MHz crystal and 115200bps, the closest you can get is 117647bps - about 2.1% off. That's normally "close enough" (in total, you usually need to be less than 5% difference in clock rates between the two sides. Normally you should have each side with 2.5%, but if the other side is "very accurate" you have additional leeway on the AVR side.)

But that's irrelevant since the main problem is the CPU load caused by SWSerial, and it's inability to receive characters while "unattended." For the HW Uart, the UART TX ISR has to respond within two BYTE times in order to avoid missing a character. For the SW Uart, the pin change interrupt has to respond within one or two BIT times!

Hmm yes. I recognize some of those words :grin:

Joking aside,considering one side of the serial will be connected to computer, does it even matter if the baud is not exactly 115200 on the MCU's side? Can't I just set the baud from the PC side to 117647?

Btw, I've upped the buadrate of serial between the PC and Arduino to 250000. Seems to be working fine.

illusive:
Bottom left one looks cool. But the display I use is a full color TFT. You can check it here . The idea behind them is really cool. All the graphical processing is done on the displays own MCU. And it can refresh every element on screen at 40hz+

Mine does color too! Green.

:slight_smile:

"BTW, I may want to get a few "custom" boards (specifically, with the crystal not installed). "
Sure, I can assemble & leave the crystal off. You'll have to do your own bootload install then.

westfw:
Software serial is tunable to within a few instruction times. Hardware UART baud rates are limited to integer quotients of (F_CPU/8) and integers.

im not sure about standard "libraries" but the routines i write are tunable within one instruction (1 cpu clock, 62.5ns). definitely superior to uart which i think are better than you give credit if 2x bit is turned on.

you do hit on one of the softserial drawbacks which is background tasks. uart has a distinct advantage here but the question is how often required. in a poll some time ago on another site it was estimated background non-blocking rx was required in less than 3% of typical applications and tx much less often than that. this agrees pretty close with my own experiences.

other advantages include less code than hardware uart and the priceless benefit of being able to use any of the mcu pins. softserial doent work for all applications but where it does i am a huge fan.

ps. interrupts are for the birds. polling much more responsive.

john1993:
im not sure about standard "libraries" but the routines i write are tunable within one instruction (1 cpu clock, 62.5ns). definitely superior to uart which i think are better than you give credit if 2x bit is turned on.

you do hit on one of the softserial drawbacks which is background tasks. uart has a distinct advantage here but the question is how often required. in a poll some time ago on another site it was estimated background non-blocking rx was required in less than 3% of typical applications and tx much less often than that. this agrees pretty close with my own experiences.

other advantages include less code than hardware uart and the priceless benefit of being able to use any of the mcu pins. softserial doent work for all applications but where it does i am a huge fan.

ps. interrupts are for the birds. polling much more responsive.

Polling? How do softserial poll with just one thread? I think my application is in that 3% you mentioned. A basic flow chart is like this

C# Packets <=> Arduino UART, Data gets some parsing on Arduino <=> TFT's Serial(Touch data gets sent back)

As you can see I need full duplex communication all the way from C# to TFT Screen.

While I can pause C# from sending further packets to Arduino UART while the soft serial is keeping it busy , I can't stop user from inputting something via touchscreen and consequently causing a packet to go from TFT to arduino.

If this were to happen while SS is sending something , my understanding is the packet the TFT sents would get dropped.

Not to mention pausing communication between PC and Arduino is not something I'm eager to do. Currently 115200 baud can hardly keep up with all the data I send. And that's with UART's pooling.

that was more in response to westfw post on serial theory than your specific case. maybe you are in the 3% if all that is really required concurrently. at one point you mention only problem with softserial was garbage characters not throughput. also stating 115k is excessively fast for your app and then talk about 2.5megabits too so will be interesting to see what you finally settle on. many similar applications would make do with one uart and one softserial but maybe not this time.

john1993:
that was more in response to westfw post on serial theory than your specific case. maybe you are in the 3% if all that is really required concurrently. at one point you mention only problem with softserial was garbage characters not throughput. also stating 115k is excessively fast for your app and then talk about 2.5megabits too so will be interesting to see what you finally settle on. many similar applications would make do with one uart and one softserial but maybe not this time.

I've mentioned that If I kept the softserial at 9600 It would somewhat work. That is to say, the error detection algorithm I wrote could keep up with the garbled data. Any higher baudrate, there just isn't enough clock cycles for softserial.

A few days ago 57600 was enough for my app. Yesterday I've added some more functionality and even 115200 wasn't cutting it.After a quick and dirty optimization, i got it to work at 115200. Out of curiousity I tried 250000 and it seem to be working well with UART. Think I'll just use that.

Truth be told my code is starting to look remarkable like a plate full of spaghetti. Writing C# on PC, Arduino for the actual app and modifying the libraries at C++ all the while adding new and unplanned features...

I'm sure if I were to seriously optimize it, I could reduce the required clock cycles by half. Someone who's actually good at MCU programming could probably half even that. I don't think even then it'd be enough to run SoftSerial tho.

I'm planning on pushing all the code I wrote to github once it's not as embarrassing. Maybe some code guru would take a hammer to it.

CrossRoads:
"BTW, I may want to get a few "custom" boards (specifically, with the crystal not installed). "
Sure, I can assemble & leave the crystal off. You'll have to do your own bootload install then.

No problem. I rarely use a bootloader anyway. I edit with a text editor, compile using GCC and a Makefile and upload direct to the board using a MKII ISP.

john1993:
ps. interrupts are for the birds. polling much more responsive.

I heartily disagree with you. Interrupts are "da bomb" :slight_smile:

Krupski:
Interrupts are "da bomb" :slight_smile:

if you think interrupts have faster response than polling then what weeee have here is a failurrrre to communnnnnicate. i will agree that interrupts resemble explosive devices in that attempts to debug can blow up in your face.

john1993:
if you think interrupts have faster response than polling then what weeee have here is a failurrrre to communnnnnicate. i will agree that interrupts resemble explosive devices in that attempts to debug can blow up in your face.

I use interrupts all the time. I use them to generate accurate delays when other ISR's are running (as you know, soft delays slow down when CPU clocks are stolen by interrupts).

I use them to generate accurate OUTPUTS such as perfect 40.0 kHz pulses for IR transmitters.

I use several counters and busy flags inside one ISR to accurately time different things, or to generate multiple audio frequencies all at once or to generate accurate "soft serial" send and receive, without critical time delays and fudges needed.

I use them to capture edges and record the exact time between them (IR decode, tachometers, etc...).

I use them to ring-buffer serial data being sent as audio data to a DAC.

I think the reasons people don't like interrupts are:

  • They don't understand how they work.
  • They don't understand that the code inside an ISR must be short and sweet and complete LONG BEFORE the next interrupt comes along.
  • They don't realize what you can and cannot put inside an ISR (due to problem #1).
  • They don't understand the need for the volatile data type for ISR variables.
  • They are not aware of atomic read and write issues when using variables larger than 8 bit.

Polling is slow, and can very well miss critical, fast moving (or short lived) events.
Can you explain, in detail similar to above, why "polling is better"?

Krupski:
soft delays slow down when CPU clocks are stolen by interrupts

not just soft delays but ALL timing critical code is compromised by interrupts. so along with slow response, hard to understand, less code efficient, and lack of portability, just a few of the drawbacks compared to polling. all those other items on your list of why people avoid them too.

you seem to be confusing response time with need for concurrency which are not the same at all.

Krupski:
Polling is slow, and can very well miss critical, fast moving (or short lived) events.
Can you explain, in detail similar to above, why "polling is better"?

i didnt actually say polling was better (although it usually is from a performance viewpoint). my original point during that discussion with westfw was that it was FASTER. at least an order of magnitude faster than interrupts when you take into account context saving overhead. for example polling works flawlessly for high baud softserial start bit detection where an interrupt would fail miserably. 57k impossible let alone 115k 250k or 500k.

polling is slow? i see now what the problem is, apparently you use interrupts for everything but maybe less experience in the bit bang world. i get a huge kick out of those guys who use timers and interrupts for an led blink demo or interrupt driven ring buffers for hello world. lol

i also use interrupts but only when they serve a purpose as for true multi-tasking. sometimes background serial when code is particularly busy or blocked input just wont do. or things that need constant refresh like direct connected led array. or rtc/rtcc. none of these required that often.

most of the programs being written out there are much simpler and less demanding and kiss principle serves better. when you need interrupts you need them but not as often as you might think. response time and need for concurrency are two different subjects. polling for speed, irq for background.

john1993:
polling is slow? i see now what the problem is, apparently you use interrupts for everything but maybe less experience in the bit bang world. i get a huge kick out of those guys who use timers and interrupts for an led blink demo or interrupt driven ring buffers for hello world. lol

One thing I do is play mono audio files from an SD card (8000 hz sample rate, 8 bit WAV format - without the WAV header) from an SD card and dumped to an R2R ladder DAC.

Obviously, I cannot read a block of code from the SD card, then dump it to the DAC, then read another block, etc... The sound would play-stop-play-stop....

What I do is have a single 2K buffer. The address index is incremented once per pass through the ISR, and it's also calculated as "address % 2048" so that it keeps running in circles all by itself. It also sets or clears the busy flag based on "address % 1024" so that I know when to refill the bottom half or the top half of the buffer (that is, I refill the bottom while the top is being eaten, and refill the top when the bottom is being eaten).

It plays perfectly with absolutely no glitches.

I've wanted to try it with the Sparkfun "ScopeClock" board as well. The Scope clock is a mega 328p and an AD7302 two channel voltage output rail-to-rail DAC, plus an RTC and serial interface chip.

Since it's got a TWO channel DAC, I wanted to try playing stereo out of it. But the [CENSORED] "engineer" who designed it connected 1/2 of the DAC data bus to PORTC and the other half to PORTB. WHY??????????????

To use it, not only do I have to make TWO writes to TWO different ports, I also have to mask, bitshift and [CENSORED] with the data because bits 0 through 3 are used for both (meaning I have to shift 1/2 of a data byte down 4 times and stuff it into 1/2 of the DAC.

THEN, I have to do all this [CENSORED] TWICE for each sample because they wired the DACSEL (dac select) pin separately.

Wired CORRECTLY, it is possible to do a single 16 bit write and load BOTH registers at the same time.

Anyway... enough rant. The point is that all of the [CENSORED] around required to send it data takes too long and chokes the ISR (at least at 16 mhz... haven't tried higher).

A lot of Sparkfun stuff is like that. For example, they sell (or sold) a cool little digital clock kit using a 328p and a 4 digit LED 7 segment display. So far, so good.

BUT, they ruined any chance of re-purposing the kit into anything else (like a voltmeter or tachometer) by connecting the segments and digits to the wrong pins (consuming all of the PORTC pins which could have been used as analog inputs) and instead wasted a full 8 bit port (PORTD) on pushbuttons and a buzzer. The alarm control switch goes to PB0 which is the one and only INPUT CAPTURE pin on the 328, making it difficult to build a decent frequency counter or tachometer (unless you want to bit-bang it and use soft delays - UGH!).

Lastly, I 100% agree with, believe in and always follow the KISS principal... which is the very reason I use interrupt driven code in the first place. No worries about accurate delays or times. An ISR is always perfect, and it's very easy to tell if it's close to being overloaded. Just put a simple LED blink (with soft delay) into the main loop and look at it on a scope. The blink speed you SHOULD be getting and the speed you ARE getting is a very good indicator of how much percent CPU time the ISR is using.

Krupski:
One thing I do is play mono audio files from an SD card (8000 hz sample rate, 8 bit WAV format - without the WAV header) from an SD card and dumped to an R2R ladder DAC.

Obviously, I cannot read a block of code from the SD card, then dump it to the DAC, then read another block, etc... The sound would play-stop-play-stop....

i am very fond of projects like that and find its rare case where using interrupts can make life easier. mainly because with polling (actually mostly cpu delay) you have to count cycles which can get wicked tedious. it is possible though with that low sample rate. you dont have to read the entire sector at once but just one byte at a time from sd ram. cant go much faster than 10khz mono though because request for the next sector takes few dozen clocks and sd hundred or so more to fetch. having done it both ways i will admit bit bang took many times longer than int. ints absolutely required for mp3 software decode as ive recently learned the hard way.

another similar project ive been working on so long hard to believe. first version used 6800 because 6502 was not available yet. dds/sampler audio synth (hal chamberlain?). went from microprocessor to 8048, to 8051, to pic, and finally avr. that last was like i died and went to heaven.

after couple years on m8 then m128 i got interrupt version up to 4ch ~8khz (thats right, i stooped so low as to use HARDWARE uart for midi). getting rid of interrupts bought me another 2ch and couple khz. latest m2560 8ch 16khz w/effects. yamaha grand actually competes with the $120k real thing.

one big obstacle and disappointment with avr was, unlike pic and the others, avr int is non-deterministic. depending on instruction that gets interrupted timing may be off 1-4 cycles. not a big problem with audio because the ear tolerates but requires real trickery for apps like vga or ntsc. thankfully in many cases using timers and oc avoids the jitters.

ps. also big fan of r2r. pwm/rc is for sissies!

john1993:
i am very fond of projects like that and find its rare case where using interrupts can make life easier. mainly because with polling (actually mostly cpu delay) you have to count cycles which can get wicked tedious. it is possible though with that low sample rate. you dont have to read the entire sector at once but just one byte at a time from sd ram. cant go much faster than 10khz mono though because request for the next sector takes few dozen clocks and sd hundred or so more to fetch. having done it both ways i will admit bit bang took many times longer than int. ints absolutely required for mp3 software decode as ive recently learned the hard way.

another similar project ive been working on so long hard to believe. first version used 6800 because 6502 was not available yet. dds/sampler audio synth (hal chamberlain?). went from microprocessor to 8048, to 8051, to pic, and finally avr. that last was like i died and went to heaven.

after couple years on m8 then m128 i got interrupt version up to 4ch ~8khz (thats right, i stooped so low as to use HARDWARE uart for midi). getting rid of interrupts bought me another 2ch and couple khz. latest m2560 8ch 16khz w/effects. yamaha grand actually competes with the $120k real thing.

one big obstacle and disappointment with avr was, unlike pic and the others, avr int is non-deterministic. depending on instruction that gets interrupted timing may be off 1-4 cycles. not a big problem with audio because the ear tolerates but requires real trickery for apps like vga or ntsc. thankfully in many cases using timers and oc avoids the jitters.

ps. also big fan of r2r. pwm/rc is for sissies!

I started with microcontroller and small CPU programming on a Radio Shack Color Computer II, then COCO-III which both use the Motorola 6809 processor.

I've also done Intel ASM (ugh) and of course AVR (better, but still ugh).

I have yet to use a processor that is so easy to use and is so loaded with GOOD features and NO bloat like the 6809 is.

There's also the Motorola 68HC11 which is ALMOST as nice as the 6809, but it lacks some of the most awesome features of the 6809 (indirect extended addressing, full 16 bit long relative jumps and calls, push and pop all the registers with one opcode, etc...

And of course, I think the fully memory mapped Von Neumann architecture that Motorola uses is much nicer than the Harvard that AVR, Intel and others use.

Also, little-endiness VS big-endiness is (IMHO) better in Motorola. For example, a 32 bit value of 0x12345678 in Motorola is (at ascending addresses):

12 34 56 78

But in AVR, Intel, etc... it's (again IMHO) bass-ackwards:

78 56 34 12

One thing that REALLY bugs me about the AVR is the lack of correspondence between opcodes, values and actual machine code. For example, in Motorola if you wanted to load the "A" register with the value 0x78, you enter this in the assembler:

[b]
    ldaa #$78[/b]

...and it generates the code "86 78" where "86" is "load A immediate" and "78" is the operand. Even Intel works like this. Calling a DOS interrupt "INT 21" results in simply
** **CD 21** **

But, code for the AVR baffles me. Look at this weird code snippet:

[b]ISR (INT0_vect) // INT0 handler - arrive here when button pressed
{
 156:   1f 92           push    r1
 158:   0f 92           push    r0
 [color=red]15a:   0f b6           in  r0, 0x3f    ; 63[/color]
 15c:   0f 92           push    r0
 15e:   11 24           eor r1, r1
 160:   8f 93           push    r24
    GIMSK &= ~_BV (INT0); // disable hardware INT0
 [color=red]162:   8b b7           in  r24, 0x3b   ; 59[/color]
 [color=red]164:   8f 7b           andi    r24, 0xBF   ; 191[/color]
 [color=red]166:   8b bf           out 0x3b, r24   ; 59[/color][/b]

Look at the stuff in red... the line "in r0, 0x3f" assembles to "0F B6"???? What the heck? Neither 0F, nor B6 are 0x3F.

In the last 3 lines, IF I assume that the opcode comes before the operand, then it seems that both "in" and "out" from a register to a port are opcode "8B".

Thank goodness I didn't learn ASM programming on the AVR first... I would still be lost.

Krupski:
And of course, I think the fully memory mapped Von Neumann architecture that Motorola uses is much nicer than the Harvard that AVR, Intel and others use.

actually intel is 100% vn just like motorola and fully able to use memory for data or code. maybe you are mistaking the memory mapped io or risc for cisc which is the real difference to avr.

anyway there are huge performance advantages to separate data/code at the microcode level which is why processors like arm, mips, and avr beat the crap out of both intel and motorola. im annoyed at the inability to do things like load and run from ram or self modifying code but willing to tolerate in order to gain some execution speed benefit.

Krupski:
But in AVR, Intel, etc... it's (again IMHO) bass-ackwards:
78 56 34 12

i agree. its true avr does have lsb first. ie "sts 0x1234,r23" assembles to 70,93,34,12

unfortunately in the hexdecimal/binary world we live in msd always precede lsd (0x10=00010000, not 00000001). most significant bytes in a word always come first too (0x1234). so seems consistent to carry that over to multi-byte arrays. i wish they were all msb first like that.

Krupski:
One thing that REALLY bugs me about the AVR is the lack of correspondence between opcodes,
...
Thank goodness I didn't learn ASM programming on the AVR first... I would still be lost.

you probably mean "hand coding" or "machine language". asm is hll by comparison and not really concerned with bit fields.

i also disliked that apparent chaos but after writing a few assemblers and disassemblers realized this is a 16 bit cpu and the opcode/register/operand fields are still there just not aligned for an 8 bit machine but instead split across what we humans call bytes. according to sondheim inventors there are distinct performance advantages at the microcode level so again im willing to tolerate.

just be glad you didnt start out on a 12 bit computer like i did with dec pdp8.

speaking of which both motorola and avr were modeled after pdp11 load/store instruction set which i thank the lord for every day. so glad to have left behind the intel queerness and microchip based on... god knows what. very happy to have 32 accumulators instead of just one or two. i do miss zero page addressing of 6800/6502/tms9900. however better 32 powerful, flexible, symmetric than 256 "almost" math capable.

ps REAL men prefer assembler. lol

john1993:
actually intel is 100% vn just like motorola and fully able to use memory for data or code. maybe you are mistaking the memory mapped io or risc for cisc which is the real difference to avr.

ps REAL men prefer assembler. lol

How is Intel von Neumann? It has separate memory IO and peripheral IO (MOV vs IN/OUT)?

A big difference between Motorola and Intel is that Motorola is a state machine. It's just a bunch of gates and flip-flops that execute opcodes based on where their bit patterns direct the hardware gates, while Intel uses "microcode"... basically software acting like an Intel processor.

As far as AVR, I really do like all of the registers. Intel X86 doesn't have many and Motorola has even less.

Oh, and yes I agree with you. REAL men prefer assembler (and redheads!) :slight_smile:

Krupski:
How is Intel von Neumann? It has separate memory IO and peripheral IO (MOV vs IN/OUT)?

the terms have nothing to do with io. vn code/data all in same memory, harvard separate.

i considered motorola memory mapped io far more elegant. fewer hardware signals and instructions to deal with. moving into 16/32bit realm i also had a strong preference for motorola linear memory space vs zilog/intel bank select. again all that extra hardware and code complication just rubbed me the wrong way.

unfortunately one thing kept smacking me in the head, in benchmarks motorola always came in last. eventually i figured out it was more efficient to manipulate 8 and 16 bit numbers than 32 bit. motorola eventually came around too. oh well... cant win em all. still think i was right about intels stupid separate io map though. avr designers seem to agree.

fyi in a previous life i was for a (short) time designer of worlds fastest microprocessor based minicomputer thanks to dual 68000 motherboard. soon intel and zilog chips became available and competition left us in the dust. however i still have a place in my heart for that wonderful 64 pin dip.