I2C 4x20 LCD screen flashing nearly all pixels on during SPI SD card write

Hello,

I have a data logger system which is running well and logging to my SD card and displaying the live data on the screen. Odd thing, since adding the SD card the screen more or less flashes during and in sync with an SD card write.

Ive put a video on YouTube to try to show rather than explain. I2s arduino screen flash with spi sd write - YouTube

The flashing isnt always regular but it more or less is and follows the once per sec SD card write. If i remove the SD card or disconnect it or disable in the programme, this flashing stops.

In the video, its connected up to an Uno and is very spread about - ive since stripped down and wired into a Nano and pushed everything together with shorter wires and generally made it very much neater.

Thinking this was perhaps an EMI issue, i twisted together wires going to the SD card into their own bundle - no effect.
Have fitted capacitors near the power feeds to the SD card, the level shifter, the LCD - again, no effect.
I also beefed up the power supply adding an external supply. The 5v rails supplied by USB was sagging to about 4.8V, now back to just over 5.0V and again no effect.

Im wondering if there is a programming thing going on somewhere, or if the SPI & I2C conflict with eachother somewhere?

The relevant parts of the programming are as follows:

 /*
 * SD card attached to SPI bus as follows:
 ** MOSI - pin 11
 ** MISO - pin 12
 ** CLK - pin 13
 ** CS - pin 4

*/

#include <Wire.h>
#include "RTClib.h"
#include <FreqMeasure.h>
#include <LiquidCrystal_I2C.h>
#include <SD.h>

#define lenght 20.0

double percent=100.0;
unsigned char b;
unsigned int peace;
RTC_DS1307 RTC;
const int chipSelect = 10;
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
void setup() {
  delay(100);

  Serial.begin(57600);
  Wire.begin();
  RTC.begin();

  lcd.begin(20, 4);
  FreqMeasure.begin(); 

  lcd.createChar(0, p1);
  lcd.createChar(1, p2);
  lcd.createChar(2, p3);
  lcd.createChar(3, p4);
  lcd.createChar(4, p5);

  pinMode(ledred, OUTPUT);  
  pinMode(ledgrn, OUTPUT); 
  pinMode(ScrnBtn, INPUT);
  pinMode(FOutPIN, OUTPUT);
  digitalWrite(ledred, LOW);
  digitalWrite(ledgrn, HIGH);


  Serial.print("Initializing SD card...");
  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
  
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Initializing SD card...");
          
  pinMode(10, OUTPUT);
  
  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("SD card failed,");
    lcd.setCursor(0, 1);
    lcd.print("or not present");
    return;
  }
  Serial.println("card initialized.");
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("SD card initialized.");
  
  if (! RTC.isrunning()) {
    Serial.println("RTC is NOT running!");
    // following line sets the RTC to the date & time this sketch was compiled
    //RTC.adjust(DateTime(__DATE__, __TIME__));  
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("RTC is NOT running!");
  } 
  delay(1000);
}
DateTime now = RTC.now();

        if (millis() >= (lastSec + 1000))
        {
//          Serial.println("Date & Time,Frequency,Sign,DeltaFreq,TempADC,TempUsed,TAdjust,THyst,Delta-,Delta+");
          Serial.print(now.year(), DEC);
          Serial.print('/');
          Serial.print(now.month(), DEC);
          Serial.print('/');
          Serial.print(now.day(), DEC);
          Serial.print(' ');
          Serial.print(now.hour(), DEC);
          Serial.print(':');
          Serial.print(now.minute(), DEC);
          Serial.print(':');
          Serial.print(now.second(), DEC);
          Serial.print(",");
          Serial.print(frequency,3);
          Serial.print(",");
          Serial.print(sign);
          Serial.print(",");
          Serial.print(DeltaFreq);
          Serial.print(",");
          Serial.print(TempMeasure);
          Serial.print(",");
          Serial.print(temperature);  
          Serial.print(",");
          Serial.print(TAdjust);
          Serial.print(",");
          Serial.print(THyst);
          Serial.print(",");
          Serial.print(TempSetUse - THyst);
          Serial.print(",");
          Serial.println(TempSetUse + THyst);        
          
          
          lastSec = millis();
        }
        
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        //SD data log 

      File dataFile = SD.open("datalog.txt", FILE_WRITE);

      // if the file is available, write to it:
      if (dataFile) {
//          dataFile.println("Date & Time,Frequency,Sign,DeltaFreq,TempADC,TempUsed,TAdjust,THyst,Delta-,Delta+");
          dataFile.print(now.year(), DEC);
          dataFile.print('/');
          dataFile.print(now.month(), DEC);
          dataFile.print('/');
          dataFile.print(now.day(), DEC);
          dataFile.print(' ');
          dataFile.print(now.hour(), DEC);
          dataFile.print(':');
          dataFile.print(now.minute(), DEC);
          dataFile.print(':');
          dataFile.print(now.second(), DEC);
          dataFile.print(",");
          dataFile.print(frequency,3);
          dataFile.print(",");
          dataFile.print(sign);
          dataFile.print(",");
          dataFile.print(DeltaFreq);
          dataFile.print(",");
          dataFile.print(TempMeasure);
          dataFile.print(",");
          dataFile.print(temperature);  
          dataFile.print(",");
          dataFile.print(TAdjust);
          dataFile.print(",");
          dataFile.print(THyst);
          dataFile.print(",");
          dataFile.print(TempSetUse - THyst);
          dataFile.print(",");
          dataFile.println(TempSetUse + THyst);  

      dataFile.close();


    }  
    // if the file isn't open, pop up an error:
    else {
      Serial.println("error opening datalog.txt");
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("error opening datalog.txt");
    } 



        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        //LCD data output 

        ScrnBtnState = digitalRead(ScrnBtn);

        if (ScrnBtnState != ScrnBtnLastState) 
        {
          if (ScrnBtnState == HIGH) 
          {
            ScrnBtnCount++;
          }
          ScrnBtnLastState = ScrnBtnState;
        }

        if (ScrnBtnCount > ScrnBtnMax) 
        {
          ScrnBtnCount = 0;
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // if (ScrnBtnCount == 0)

        if (buttonPinValue >= 0 && buttonPinValue <= 100)
        {
          lcd.clear();
          lcd.setCursor(0, 0);
          lcd.print("Freq:     Temp:");
          lcd.setCursor(0, 1);
          lcd.print(frequency, 3);  //Display to 4DP
          lcd.print("Hz  ");
          lcd.print(temperature, 1);  //Display to 1DP
          lcd.print((char)223);
          lcd.print("C  "); 

          lcd.setCursor(0,2);
          lcd.print((frequency - FreqSet),4);

          double percent = DeltaFreq/0.3*100.0;

          lcd.setCursor(0,3);
          //lcd.rightToLeft();

          double a=lenght/100*percent;

          // drawing black rectangles on LCD
          if (a>=1) {
            for (int i=1;i<a;i++) {
              lcd.write(4);
              b=i;
            }
            a=a-b;
          }
          peace=a*5;

          // drawing charater's colums
          switch (peace) {
          case 0:
            break;
          case 1:
            lcd.print((char)0);
            break;
          case 2:
            lcd.write(1);
            break;
          case 3:
            lcd.write(2);
            break;
          case 4:
            lcd.write(3);
            break;
          }
        }

If there are any clues, i would appreciate pointers in the right direction.

It could be pin clash of some sort but I have never seen the display called like that. I just use.

LiquidCrystal_I2C lcd(0x27,20,4);

Maybe this is down to the library, in which case you might change it.\

It could be power. If your external power on the barrel jack, it should be a minimum of 7v. "Just over 5v" sounds rather like you are recycling a phone charger. If so,stop being a cheapskate and come forth with the $5 for a proper wall wart.

Hi,

Thanks - will check the LCD, think this was in an example and ive left it as i thought the I2C LCD library needed to be told a pin order but perhaps not. I could also perhaps try a different I2C LCD library - if there are ones, not yet looked.

No being cheap, i would say a $5 (which would be probably £25 here!!) wall adapter is in my mind cheaper than my supply...

My circuit has a 240:9-0-9 transformer which i use to get an AC cycle reference from. Using that same transformer (with rectifier & smoothing) im feeding a Recom 20W DCDC giving me 5V +/- 1% Handy thing about these DCDC is they take 9-36vDCin and heat dissipation is almost non-existent!

The other reason for taking power from the transformer is it keeps it cool - small transformers under no to small load get quite hot (almost as if permanently shorted!) due to core saturation and they need a bit of load to stop the saturation and cool down.

Will look into the LCD library and see whats happening there and get back.

Cheers,
Stuart

Nick_Pyner:
LiquidCrystal_I2C lcd(0x27,20,4);

Found that i got my lcd string (?) from http://arduino-info.wikispaces.com/LCD-Blue-I2C. Will try trimming down as you suggest, perhaps it works with this library too.

OK, I had a look at that link and I think the whole thing is junk and Malpartida hasn't the faintest idea what he is doing. What is really notable is that the I2C interface board "YwRobot Arduino LCM1602 IIC V1" mentioned therein is exactly the same as the one I have. If you have that interface too, I suggest you get the library from YWRobot. All their documents are clearly marked //YWRobot in line one, and Malpartida's name is nowhere to be seen. Their example programmes are clear, succinct, and take up a hell of lot less real estate. That in itself will be worth the effort. Note that, while the board is marked 1602, it will work 4x20. There are separate libraries for each format.

Having said that I'm not sure it will fix your problem and the power supply is still suss. After all the description, the only thing that is important is what I asked, and what you haven't mentioned - where the power is applied. If you are using the barrel jack, the 5v is not enough, indeed a 1A phone charger is probably a better bet at 5.3v. However, if you are sure the 5v is really true, smooth and kosher, you can apply it to the VIN pin.

However, if you are sure the 5v is really true, smooth and kosher, you can apply it to the VIN pin.

No, the 5V pin, the VIN pin is for voltages in the range 7V-16V and is almost the same as the power connector.

Hello,

Noted about the link on the display, will give a crack at the LCD and revise that and get back with the results.

Power from my supply is connected directly into the 5V rails/Vcc pin. Ive placed 100uF and 0.1uF caps close to the power supply to each device.

The 3.3v for the SD level shifter comes from the SD card's onboard regulator as i dont think the 3.3v supply on the Aruino is upto the job of driving the SD card.

At this point i dont think power is the issue as supplies are stable.

Thanks again,
Stuart

Seeing the effect in the youtube video I get the impression that not the driver chip is generating that flickering but it's the display's contrast setting that increases for a moment. Afterwards the exact same stuff is on the display as before. Can you provide a link to the I2C LCD module (the driver) and the actual LCD you have? I just want to check how the contrast is set there.

OK. I reckon Pylon is right and I am wrong about the VIN pin anyway, and I'm sure you know what you are doing about power since you are staying away from the barrel jack! This includes the SD. My only experience of them is when they are on an Ethernet card or other shield which has on-board 3.3v regulation

I can't recall getting the library direct from YWRobot myself, I guess I must have got it from a link in the eBay listing. It can't be hard to find, but PM me if you have a problem.

Can you provide a link to the I2C LCD module (the driver) and the actual LCD you have? I just want to check how the contrast is set there.

(Oops)

I have told you all I can about the display, and I'm afraid I can't remember where it came from. I'm sure the contrast is set with the little blue pot on the control board but I have never touched it. The jumper at the end disables the backlight.

On reflection, and while I still think that Wiki you alluded to is junk, this might not be down to Malpartida, who is just the author of a library. Irrespective, I submit you will be better off with the YWRobot library.

Ok, finally got a chance to look at this:

stuartsjg:

Nick_Pyner:
LiquidCrystal_I2C lcd(0x27,20,4);

Found that i got my lcd string (?) from http://arduino-info.wikispaces.com/LCD-Blue-I2C. Will try trimming down as you suggest, perhaps it works with this library too.

If i just replace my LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); with your LiquidCrystal_I2C lcd(0x27,20,4);, i get the error "invalid conversion from 'int' to 't_backlightPol'"

given it was complaining about the backlight polarity, i took a guess at LiquidCrystal_I2C lcd(0x27,20,4,POSITIVE); which compiled and ran fine with the same issue as before.

pylon:
Seeing the effect in the youtube video I get the impression that not the driver chip is generating that flickering but it's the display's contrast setting that increases for a moment. Afterwards the exact same stuff is on the display as before. Can you provide a link to the I2C LCD module (the driver) and the actual LCD you have? I just want to check how the contrast is set there.

The LCD contrast as far as im aware is set only by the pot on the back of the LCD PCB. Adjusting this changes the contrast of the displayed text i want and the all squares lit condition i dont want.

I agree it looks like it going to full contrast, however often there is a line or block of pixels which stay dark.

The LCD was bought from ebay http://www.ebay.co.uk/itm/I2C-Arduino-LCD-2004-20x4-Character-LCD-Module-Blue-Backlight-for-Arduino-Pi-Pic-/161107072069?ssPageName=ADME:L:OC:GB:3160 althogh the one shown just now is not the unit i have.

Markings are as follows:
LCD PCB (Green with 5 on-board IC's), marked "J204A". "2013 08 QC Pass Made in China" sticker
Black module, marked "IIC module", has "PCF8574T // K22881 // 01 // ToM00303 marked on the IC" ("//" denotes new line on the IC)

Will keep at it!

According to this, the SD card is using D4 as the slave select.

/*
 * SD card attached to SPI bus as follows:
 ** MOSI - pin 11
 ** MISO - pin 12
 ** CLK - pin 13
 ** CS - pin 4

*/

You can't use D4 for the LCD. You are using it in both examples below.

If i just replace my LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); with your LiquidCrystal_I2C lcd(0x27,20,4);, i get the error "invalid conversion from 'int' to 't_backlightPol'"

edit: Or you must use another digital pin for the SD slave select, like D8.

I mentioned pin clash in reply #1 and now Surfer has brought it up again. This a been sidetracked by all the stuff about libraries and power. If you have not checked out pin 4 already, that is the first place to start.

Nick_Pyner:
I mentioned pin clash in reply #1 and now Surfer has brought it up again. This a been sidetracked by all the stuff about libraries and power. If you have not checked out pin 4 already, that is the first place to start.

Ill check but im sure i had already changed to another pin for the SD card CS after the suggestion. Cant remember if that change didn't perhaps work so ive left it as it was.

If the SD card library was using pin 4 on the arduino, how would this affect pin 4 coming out the I2C module? Im assuming its because of the method the LCD I2C data is produced to be sent for display?

Will double check this anyway.

Also need a tip on how to explain to my wife how a thing like this is not trivial!

Hi,
I'm using exactly the same LCD and a sd card. I just checked my code:

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

No issues at all.
Is there any chance to get another LCD and test it? Maybe 1602 version?
Are you using NewLiquidCrystal library?
Another thing, there might me a clash when updating LCD simultaneously with writing to SD or if updates happen too often. I personally made a small IF statement in main loop and check timing there, calling screen update every second (or half a second).

stuartsjg:

Nick_Pyner:
If you have not checked out pin 4 already, that is the first place to start.

If the SD card library was using pin 4 on the arduino, how would this affect pin 4 coming out the I2C module? Im assuming its because of the method the LCD I2C data is produced to be sent for display?

I think you are right, and I keep getting confused by all those numbers in the LiquidCrystal command, especially the 4, which I realise isn't a pin number at all. If you have wired your SPI lines to SDA,SCL it should be fine. It clearly isn't, yet your SPI controller board is the same as mine and I think that should be sufficient. The wiring is unclear but I can see the intent and, if you get anything displayed, it must be kosher.

If you cannot fix this, you might try the YWRobot library as a replacement from here,
http://homepages.ihug.com.au/~npyner/Arduino/LiquidCrystal_I2C2004V1
but you do get a display, so I don't hold much hope of that fixing anything.

Having said all that, it still LOOKS like, and in your words it sounds like, a power problem - SD comes on, LCD fails. One last forlorn shot in that direction: While I don't have any complaint about those DS1307 modules, plenty of people do, and they have been blamed for all sorts of things, including power issues. You might try feeding the LCD in parallel to the clock, rather than through it, as I believe you are at the moment.

Also need a tip on how to explain to my wife how a thing like this is not trivial!

Just tell her it should be trivial, but some clown in Australia keeps shunting you up a sidetrack.........

Which LCD screen are you using? A link to the device and how it is connected to the Arduino might help if you are still having trouble.

If you are using an Uno and D4 for the SD slave select, then insure the LCD screen is not connected to D4, D10, D11, D12, or D13.