Friday, June 5, 2015

Driving multiple displays with the Arduino

Over the four months or so since I got my Arduino, I have purchased several different small displays that utilize various hardware control methods: A 16x2 character LCD module that uses the Hitachi HD44780 parallel interface, a 20x4 character LCD module with an I2C board connected to its internal HD44780 interface, a Nokia 5110 84x48 LCD dot-matrix display module, and a tiny 0.96 inch 128x64 OLED display module. Both the Nokia and the OLED displays use the SPI interface. I have used these displays individually in any number or projects I have built, but I often wondered if they could all be connected and controlled at once.

One of the greatest things to me about the Arduino is its ability to accept input and provide output to an amazing variety of devices. The Uno, equipped with 14 digital I/O pins and six analog pins, make connecting with almost anything you can imagine extremely simple, and often with little or no support hardware. In addition, the SPI.h and wire.h libraries make connecting and communicating with SPI and I2C devices even easier.

I am fascinated with all the gadgets that can be interfaced with the Arduino, and when I purchased a tiny I2C Temperature and Pressure sensor, I thought it would be a perfect opportunity to see if all my displays could be connected simultaneously and be used to display atmospheric data measured by the module.
Since the larger of my two LCD character based displays is controlled via I2C, connecting it with the temp/pressure module was a snap. No additional pins beyond the four I already had connected to the sensor were needed, since I2C devices communicate on a serial bus, each device with its own address.

The two SPI displays, the Nokia and OLED used an additional five pins, three pins common between the two displays, and one pin each to control each individual display.

The parallel interface equipped 16x2 display required an additional six pins along with a separate solderless breadboard to accommodate the pins that needed to be held high or low, provide a connection for the 10k pot used to control contrast, and power the display's backlight.

All told, fifteen of the Arduino's pins. Two for ground and +5V, two of the analog I/O pins for the I2C interface, and eleven of the digital I/O pins: five for the two SPI displays, and six for the parallel display. Not too terrible when you consider that there are five discrete devices being driven!

I had a lot of fun putting the project together, along with learning to use the U8glib graphic library to display the graphical pressure data on the two individual dot addressable displays. I'm not going to post the source code here, but if anyone is interested, leave a comment and I will be happy to provide it to you.


 Until next time, happy project building, and be sure to check out some of my other projects on my YouTube channel: My YouTube Channel

24 comments:

  1. Hello,
    i am trying to drive 4 oled displays over spi, but i am having some trouble, could you give me your code so i can compare it with mine? your wiring diagramm would be nice too.
    Regards

    ReplyDelete
    Replies
    1. I sincerely apologize for not seeing your comment before today!

      I further apologize that I don't have a ready made wiring diagram, but the snippet below and the link to a complete working program below should help.

      To connect two SPI displays, I instantiated two u8glib objects, one for each display, like in the code snippet below:

      U8GLIB_PCD8544 u8g(13, 11, 10, 9, 8); // SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, Reset = 8
      U8GLIB_SSD1306_128X64 u8g2(13, 11, 7 , 9); // SPI Com: SCK = 13, MOSI = 11, CS = 7, A0 = 9

      EACH SPI device requires its own unique Cable Select (CS) pin. The rest of the pins can be shared between the devices.

      Then in the body of the code, I called each u8glib object's "picture loop" separately:

      u8g.firstPage();
      do {
      draw();
      } while ( u8g.nextPage() );

      u8g2.firstPage();
      do {
      draw2();
      } while ( u8g2.nextPage() );


      Link to a working example:
      https://drive.google.com/file/d/0B8rKcOSD8CvQeHRZX0doQTNQMEk
      (Note that the example also utilizes a few additional libraries to read from a BMP180 temp sensor, so if you want to do something a little different with the code, you will probably have to edit out the parts that don't apply.

      Hope this helps, let me know if I can help, or if you need any additional help.

      Delete
    2. Hey,
      thanks but i still cant drive my 4 displays on the arduino,
      at the moment i am trying with 2, and that works fine but i have
      U8GLIB_SSD1306_128X64 FR(13, 11, 6, 7, 8);
      U8GLIB_SSD1306_128X64 FL(13, 11, 9, 10, 12);
      as constructors, so i have to use different pins not only for cs, but for dc and res!
      My dispays have 7 pins (vcc,gnd,d0,d1,res,dc,cs) d0 = clk and d1=sda on the back ist has some resitors and 4spi and 3spi on it, what is the difference between 4spi and 3spi? if i hook up 4 displays with 3 different pins each + clk and sda that makes 14 pins, and i will run our of pins.
      is there a way to just use clk,sda and cs pins?
      regards

      Delete
    3. what is the difference between 4spi and 3spi?
      If your display only has resistors on R3 and R4, your display is hardwired for 4 pin SPI.
      3 wire SPI is a method of data communication that uses a single wire for transmitting AND receiving data, and since the display doesn't transmit and only receives data, I'm not sure why a 3 wire SPI interface would even be useful anyway.

      is there a way to just use clk,sda and cs pins?
      No. The DC pin is most definitely needed to tell the display when it is receiving commands versus when it is receiving data.
      In my case, I was able to share the DC pin between both displays, only requiring one pin on the Arduino for both displays. If that is true in your case, you would be able to have a single DC pin connected to all four displays.

      Are you sure that the reset (RES) pin needs to be connected to make the display function? If it definitely needs to be connected for the display to function, and you don't need to be able to reset each display individually, you should be able to connect all four displays' RES pins together and use a single pin on the Arduino to control them all.

      What it comes down to is since I don't have four displays identical to yours, I can't say for sure what will and won't work. It may just take some experimentation to see what works and how few pins you can get away with.

      Here are some links to diagrams showing some of the potential connection methods. I'm not saying any of these will work for you, but maybe you can find one that does.
      Least desirable (14 pins)
      Shared RES (11 pins)
      No RES (10 pins)
      Shared RES, shared DC(8 pins)
      No RES, shared DC(7 pins)



      Delete
    4. Hey thanks for the answer,
      Managed to use clk, sda, dc shared pins. Cs and reset are on separate pins each. Tried to set the res pin to high, to save pins on the arduino, but it's not working. Maybe a rc network will do the trick.
      Thanks

      Delete
    5. This comment has been removed by the author.

      Delete
    6. Hi Jan did you end up getting this working? I'm starting a project where I'd love to run 4/5 colour spi displays. Do you have Write up for what you're doing and how you ended up wiring it???
      Thanks so much

      Delete
  2. Nice to see somebody getting it up and working. :)
    Have been at it for a couple of days now, but can't get it to work right. So it would be awesome if you could send the code.

    Regards

    ReplyDelete
    Replies
    1. To connect two SPI displays, I instantiated two u8glib objects, one for each display, like in the code snippet below:

      U8GLIB_PCD8544 u8g(13, 11, 10, 9, 8); // SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, Reset = 8
      U8GLIB_SSD1306_128X64 u8g2(13, 11, 7 , 9); // SPI Com: SCK = 13, MOSI = 11, CS = 7, A0 = 9

      EACH SPI device requires its own unique Cable Select (CS) pin. The rest of the pins can be shared between the devices.

      Then in the body of the code, I called each u8glib object's "picture loop" separately:

      u8g.firstPage();
      do {
      draw();
      } while ( u8g.nextPage() );

      u8g2.firstPage();
      do {
      draw2();
      } while ( u8g2.nextPage() );


      Link to a working example:
      https://drive.google.com/file/d/0B8rKcOSD8CvQeHRZX0doQTNQMEk
      (Note that the example also utilizes a few additional libraries to read from a BMP180 temp sensor, so if you want to do something a little different with the code, you will probably have to edit out the parts that don't apply.

      Hope this helps, let me know if I can help, or if you need any clarification.

      Delete
    2. Thanks alot for you answer :)
      I came to the same conclusion as you did, so must be the display controller in the Nokia 5110, that just ain't happy. I have come up with another solution, hacking the adafruit library, and using hardware SPI. Will try and document it when i am done.

      Regards Kuro

      Delete
  3. Hi Kuro any chance you managed to get your solution sorted? I'm looking to try and run 4 displays at once

    ReplyDelete
    Replies
    1. Yeah, but i am not happy with it at the moment. The project is on hold, because of life, but i hopefully should be able to finished it in a couple of months.
      I ended up using this adafruit library: https://github.com/adafruit/Adafruit-PCD8544-Nokia-5110-LCD-library
      Have tested it with 3 displays running on the hardware SPI bus, and it works great. Buttt.... At the moment it takes up 3 dedicated pins pr display, and that's not working for my project, since i need those pins for other stuff. It should be possible to get down to 1 dedicated pin pr display, i just haven't had time to go through the library, and not good enough at understanding the underlying code at the moment.
      Hope this makes some kind of sense, and it helps you in some way.

      Regards Kuro

      Delete
  4. Thanks for the reply! yes I thought maybe you could share all the common pins for spi and just have the one addressing pin.. did you basically just create new instances per display?

    Thanks Kuro,
    Tom

    ReplyDelete
    Replies
    1. You can do that, that's how SPI is defined. But no libraries i have found is made so that it is possible to do that. As you mentioned, i have created one instance pr display, where each display needs to have its own:

      - Data/Command select (D/C)
      - LCD chip select (CS)
      - LCD reset (RST)

      It is by the SPI standard possible to just have a dedicated LCD chip select pr Display.
      The beginning of my code looks like this:

      #include
      #include
      #include

      // Software SPI (slower updates, more flexible pin options):
      // pin 7 - Serial clock out (SCLK)
      // pin 6 - Serial data out (DIN)
      // pin 5 - Data/Command select (D/C)
      // pin 4 - LCD chip select (CS)
      // pin 3 - LCD reset (RST)
      //Adafruit_PCD8544 display = Adafruit_PCD8544(13,11, 12, 8, 7);

      // Hardware SPI (faster, but must use certain hardware pins):
      // SCK is LCD serial clock (SCLK) - this is pin 13 on Arduino Uno
      // MOSI is LCD DIN - this is pin 11 on an Arduino Uno
      // pin 5 - Data/Command select (D/C)
      // pin 4 - LCD chip select (CS)
      // pin 3 - LCD reset (RST)
      Adafruit_PCD8544 display = Adafruit_PCD8544(5, 4, 3);
      Adafruit_PCD8544 display2 = Adafruit_PCD8544(8, 6, 7);

      The hardware SPI is necessary in my opinion when driving multiple displays, since the software one is waaaaay to slow. It differs from arduino to arduino where the hardware SPI pins are.

      Delete
    2. Don't know why the included libraries disappeared in the last post. But they are as following:

      SPI.h
      Adafruit_GFX.h
      Adafruit_PCD8544.h

      Delete
  5. This comment has been removed by the author.

    ReplyDelete
  6. Thanks so much for your reply.
    So wiring wise what is your dedicated SPI pin doing? just driving the addressing of one of the monitors then you're using other digial pins for the other ones?

    Would you happen to have a fritzing or wiring shot?

    Which lcds did you end up using?
    Thanks again :)

    ReplyDelete
    Replies
    1. Sorry for the late reply, my project is on standby at the moment, to busy with other stuff, and not good enough at coding to modify the library, so that i only need one dedicated pin pr display.
      At the moment each display got a dedicated Command select, Chip select and reset. I should be able to get that down to just a dedicated Chip select pr display. I have no wiring diagram, tried to plan in fritzing, but the program is just way to buggy for my taste. I will make a short article about how to get this to work when i am done, since it seems there is not much info about it out there. But dont expect anything within the next two months :3

      Delete
  7. i want to add two 16*2 lcd display with arduino..can you please provide me the source code for my scenario,and the two displays will show two different measurements..Tnx :)

    ReplyDelete
    Replies
    1. That is much easier than this. There is instructions and code here: https://www.hackmeister.dk/2010/08/4-lcd-displays-on-1-arduino/

      Delete
  8. This comment has been removed by the author.

    ReplyDelete
  9. Sorry for my english but i need help. I need to paralel connect 2 displays on arduino . I need just display info. Can i get schemme like i can connect it please?

    ReplyDelete
  10. great interesting blog I am learning and enjoying it so thanks in advance to everyone.

    question: could you get 30 - 40 displays working all at once? what would be needed? daisy chaining using spi seems or "appears" could be an endless chain . no?
    thank you

    ReplyDelete
  11. The Orleans Casino & Hotel - Mapyro
    Property 보령 출장샵 Location With a stay at The Orleans Casino & Hotel 구리 출장마사지 in New Orleans (Toms River), you'll be 경상남도 출장안마 centrally located in New Orleans, 광주 출장샵 steps from 과천 출장마사지 Fashion

    ReplyDelete