How to minimize CPU overhead of I2C 128x64 display? Interrupts ?

Status
Not open for further replies.

Darcy

Well-known member
Hi,

I am thinking of porting my 'up-and-running' project from AVR's to Teensy3.2 (3.6 should be here soon!)

I have 6 arduino's that share the workload, and want to reduce my system & code complexity by substituting a single Teensy in place of a Mega (2560) and ProMini (328).

The Mega is the Master to a five slave RS485 bus, and also services three streams of data between two Desktop computers using one and a half RS232 ports (2 off Rx, 1 off Tx). It also has I2C FRAM logging, and Analogue and I2C sensors.

I tried to add an I2C display (I was only shooting for 1fps updates), but found I was getting lots of transmission drop-outs even with extended Uart buffers, so off-loaded this to a ProMini. All good!

So does anybody think the 3.2 (or 3.6) could do the workload of the Mega-ProMini combination, or do you think that the U8glib or Adafruit drivers are too CPU intensive/blocking to do any high speed mission critical comms stuff also?

I did get the display working with the teensy, but to me the loop times while obviously considerably better than the Promini, as far as I remember, didn't look very good.

Any thoughts/suggestions/heckles much appreciated, but please be gentle, the last code I wrote was on a Sinclair: 10 PRINT <obscenity> , 20 GOTO 10...

Darcy.
 
The limiting factor is the I2C Bus-Speed, which is not very fast. I'd use the I2C_t3 library, it is written for the Teensy.
You did'nt tell anything about your project, but i think it will work.

Maybe it is possible to let the Teensy 3.6 do work of all 6 AVRs ?
What do they do ?
 
Not sure of your display but you might play with:

Wire1306.setClock(400000UL); // Set I2C frequency to 400kHz

This was for the SSD1306 OLED and it would not go faster IIRC. But for another Onehorse bubble display I found this to work - where I could put this display on a separate I2C bus and stepped up the speed 4x - higher didn't work - but the display update time went down a great deal so I could tend to other things.:

Code:
#include <i2c_t3.h>
#define WireHT Wire1
// ...
  WireHT.begin();
  WireHT.setClock(1600000UL); // Set I2C frequency to 400kHz

Another thing is to process your incoming Serial# data with serialEvent#() - anytime you drop a yield() call [or exit loop()] you can process/empty incoming buffers - if your display update takes any time and you can yield() there.

And perhaps you can up your baud rates as well with more processing power at hand and hardware FIFO on Serial[1 and 2] - assuming the RS485 delivers to those ports?
 
Also - not knowing your display or how tied you are to it. There is a higher res 128x128 SPI display ILI9163C that is Super fast color LED that is cheap.

See this thread for details - this post shows full color bar graph updating 200+ fps:
ILI9163C-128x128-TFT-driver?
 
I'm not sure what display you are using, but PJRC sells a 320x240 TFT screen for $8 + s/h (http://www.pjrc.com/store/display_ili9341.html) or a version with a touch screen for $12 + s/h (http://www.pjrc.com/store/display_ili9341_touch.html). Note, these are SPI displays (using pins 11, 12, 13 by default, plus one chip select pin -- typically 10 -- for each SPI device), and not i2c devices.

Adafruit sells a similar TFT display (https://www.adafruit.com/products/1651).

If you buy these displays (or similar displays with the same IL19341 chipset), PJRC provides an optimized library (https://github.com/PaulStoffregen/ILI9341_t3). This thread contains timings and details: https://forum.pjrc.com/threads/26305-Highly-optimized-ILI9341-(320x240-TFT-color-display)-library.

Note, just in case you did not do it, when you are setting up i2c devices on Teensy, you MUST use external pull-up resistors (separate resistor between each of the SDA and SCL pins and 3.3v) at least once on the bus. Typically for a Teensy, 2.2K Ohm resistors are used for the bus. You can use larger resistors like the 4.7K Ohm resistors that are standard for 5v buses, but as I understand it, a larger resistor might mean you can't achieve the fastest speeds.

The base i2c speed is 100kHz. With the i2c_t3 library you can increase the speed of the i2c bus (depending on whether your devices can handle faster i2c devices). In addition, the Teensy 3.2 has a second i2c bus, and the forthcoming 3.5 has 3 i2c buses, and 3.6 has 4 i2c buses. You could spread out the devices on the different buses. Note, you typically will have to modify the library to use the correct i2c bus. On the Teensy 3.2, you will need to solder pads 29 and 30 underneath the Teensy (and on the 3.5/3.6 you need to solder the underneath pads to get to i2c bus #2 and i2c bus #3 as well). If you go for extra i2c buses, you will need pull-up resistors as well for each i2c bus.

And if you have a real complex i2c bus, this document should help you figure out the appropriate resistors to use for the fastest i2c bus: http://www.ti.com.cn/cn/lit/an/slva689/slva689.pdf.
 
Last edited:
Thanks all for your input.

Frank, I'm pretty stuck with multiple controllers as they each run I2C sensors that are a distance from each other greater than I2C allows, a single teensy would have made my life a lot easier though!

Defragster and Michael, I'm currently on a ssd1306, (2.42" white OLED ebay sourced one) and have been running the AVR's i2c at 400KHz, but I probably was only running 100khz with the teensy. I must give this a try.

I was using 4.7k so will drop to 2.2k - thanks I'd not picked up on this difference.

I'm not sure I'm ready to move to a colour display, the danger is my user interface will forever be a work-in-progress if I get to choose colours as well as pixels!

I'll do some more testing and try to decide if I should bite the bullet and go for one of those 2 ILI controller displays.

Many Thanks,

Darcy
 
Frank, I'm pretty stuck with multiple controllers as they each run I2C sensors that are a distance from each other greater than I2C allows, a single teensy would have made my life a lot easier though!

Over at tindie, I noticed there is an i2c and power extender that uses ethernet cables to allow for longer distances (according to the page it was tested to 365ft at 100kHz and 165ft at 400kHz):

I was using 4.7k so will drop to 2.2k - thanks I'd not picked up on this difference.
As I understand it, 4.7k is the standard resistor used for 5v systems, 2.2k or 2.4k is the standard resistor for 3.3v systems. Since a lot of the guides were written for the 5v Arduino Uno, that's why they use 4.7K.
 
Last edited:
FYI :: I just took off the 4K resistors on my SSD1306 mount board and put on 2.2K.

Then I put the SSD1306 code in a sketch and swapped out the WIRE for #include <i2c_t3.h> in ( sketch and adafruit_ssd1306.cpp )

Code:
//#include <Wire.h>
#include <i2c_t3.h>
Wire1306.setClock(2400000UL); // Set I2C frequency to 400kHz

In "Adafruit_SSD1306\examples\ssd1306_128x64_i2c" I used micros() to see Speed for setup() modified to reduce delays to 1 or 2 millis() I see::

33,898,954 us Default speed
10,919, 999 us for :: Wire1306.setClock(400000UL); // Set I2C frequency to 400kHz
4,584,007 us for :: Wire1306.setClock(2400000UL); // set to 2.4 MHz
When I tried it at set to 3.2 MHz it sorta ran, with lots of screen errors.

Note above is on a Teensy 3.6 clocked at 240 MHz - On the Teensy 3.6 at 72 MHz it still runs fine but a bit slower
6,405,038 us for :: Wire1306.setClock(2400000UL); // set to 2.4 MHz

<UPDATE>:
For some reason the 2.4 MHz fails on T_3.6 at 180, and 120 and 96 MHz - where it works at 240 and 72 and some others. It did work at 2.2 MHZ at 180? Not sure if it has any bad spots on the T_3.2?
This is at :: F_CPU =180000000 F_PLL =180000000 F_BUS =60000000 F_MEM =25714286
If I bump the F_BUS up to 90000000 then it works at 180?
F_CPU =180000000 F_PLL =180000000 F_BUS =90000000 F_MEM =25714286

BTW: It turns out I was running the bus at 120 when CPU was at 240
F_CPU =240000000 F_PLL =240000000 F_BUS =120000000 F_MEM =30000000
At default 60 MHz bus when at 240 it fails there too:
F_CPU =240000000 F_PLL =240000000 F_BUS =60000000 F_MEM =30000000
Though at 80 MHz bus it works:
F_CPU =240000000 F_PLL =240000000 F_BUS =80000000 F_MEM =30000000
 
Last edited:
So does anybody think the 3.2 (or 3.6) could do the workload of the Mega-ProMini combination, or do you think that the U8glib or Adafruit drivers are too CPU intensive/blocking to do any high speed mission critical comms stuff also?
There is no need for the transmission to block. The i2c_t3 library can do asynchronous transfers in the background. It wouldn't be too difficult to modify the SSD1306 library to use asynchronous transfers.

With the Teensy you can afford to waste RAM, so just make the I2C buffer large enough to hold a full screen. Then you modify the display routine to use an asynchronous transfer - minimal changes required.

Since the display data gets copied synchronously into the I2C transmit buffer in the display routine, you can use screen draw commands while the actual I2C transmission runs in the background without any problems.

Just make sure not to make other I2C requests while the transfer is running.
 
Put the SSD1306 on a T_3.1 and have found it to look good at 2.4 MHz :: Wire1306.setClock(2400000UL); // Set I2C frequency to 2,400kHz

Very fast and clean doing a version of the Adafruit demo code with the delays removed and the falling stars made re-entrant.

Runtime on a 96 MHz T_3.1 for the same tests shows 10 seconds versus 3.5 seconds to complete.
400 elapsed Micros=10,179,315
Wire1306.getClock() =400000
2,400 elapsed Micros=3,568,434
Wire1306.getClock() =2400000
 
Many Thanks,
just tested "Wire1306.getClock() =2400000" at 96 MHz T_3.2 and the OLED is really fast.

Something that I noticed when testing this with 3 different USB power supplies: PC and wallwart worked fine, but 3rd supply was a 240V domestic wall socket with integrated 5v USB ports and at 2400000 I get some small glitches and then the adafruit snowflakes start rising up the screen instead of falling! My uneducated assumption would be that this supply is noisy and it is interfering with I2C at this higher speed... although I'm surprised by the 'inverted display' result!

darcy.
 
The glitch probably got the controller to flip the drawing direction internally.

Probably not a healthy supply to feed the teensy?

So great it is working that fast for you too.
 
Status
Not open for further replies.
Back
Top