I2C and SPI conflict

Hello,

I am using the I2C backpack from Adafruit in SPI mode to drive an LCD panel. It works perfectly and I am quite familiar with this product having bought 50+ so far. This uses the LiquidCrystal library. I also use a DS1307 RTC module which is an I2C device, default address 0x68, connected to SDA/SCL on a Leonardo. The RTC works perfectly using RTClib.

The problem is when the code is combined. The RTC still reports the time correctly with Serial.print();, but the LCD remains blank.

LCD/Backpack connections are: (SPI jumper bridged)

  • 5V to Arduino 5V pin
  • GND to Arduino GND pin
  • CLK to Digital 2
  • DAT to Digital 3
  • LAT to Digital 4

The RTC

  • 5V to Arduino 5V pin
  • GND to Arduino GND pin
  • SCL to Leonardo SCL
  • SDA to Leonardo SDA

Code attached

Any help appreciated!!!!!

// *****************************************************************************
// ** SGH_RTC_Alarm
// ** Timers, alarms and real time clock (RTC) example
// **
// ** Uses a DS1307 RTC module connected to I2C pins SDA/SCL. 
// ** Default I2C addressing assumed
// ** --------------------------------------------------------------------------
// ** Coding by:   Don Gibson  info@SmartGreenHouse.org
// ** Based on original code from "Arduino Cookbook" Michael Margolis / O'Reilly Press
// ** Created:     May 17 2013
// ** Version:     1.2
// ** Last update: added weekday alarm  2013/05/19
// ** Modified by: DG
// ** This code is public domain, but please always include the original header
// ** in any subsequent copies
// *****************************************************************************
// ** By default in timeAlarms.h there are 6 alarms declared
// ** to add more alarms, edit timeAlarms.h as follows:
// ** dtNBR_ALARMS 12  which increases the number of alarms to 12 (255 max)
// *****************************************************************************
 /* The circuit:
 * 5V to Arduino 5V pin
 * GND to Arduino GND pin
 * CLK to Digital 2
 * DAT to Digital 3
 * LAT to Digital 4
*/


#include <Wire.h>
#include <RTClib.h>         //assumes SDA/SCL connections to RTC module
#include <Time.h>
#include <TimeAlarms.h>
#include "LiquidCrystal.h"

#define DS1307_I2C_ADDRESS 0x68  // the default I2C address of DS1307 RTC

int currentSeconds = 0;

RTC_DS1307 RTC;             // create the RTC object instance

// Connect LCD via SPI. Data pin is #3, Clock is #2 and Latch is #4
// Relates to CATkit & Kitten pins:  K2; K3; K1 for remote connection
LiquidCrystal lcd(3, 2, 4);

int iYear;
int iMonth;
int iDay;
int iHour;
int iMinute;
int iSecond;

int alarmOneInterval = 600; // seconds for the timer interval in alarmOne
int alarmTwoInterval = 60;  // seconds for the timer interval in alarmTwo

boolean ON = 1;
boolean OFF = 0;
boolean waterState = OFF;   // use waterState to ensure the valves are either ON or OFF and the 
                            // status of the valve is always known

int solenoidPin = 7;        // attach D7 to a 5v relay control signal to control the water valve

void setup()
{
  Serial.begin(57600);
  Wire.begin();  //set address here  default is 0x68
  RTC.begin();
  
  if (! RTC.isrunning()) {
    Serial.println("RTC is not running - you may need to replace the battery or check connections");
    // following line sets the RTC to the date & time this sketch was compiled
    RTC.adjust(DateTime(__DATE__, __TIME__));
  }
  //RTC.adjust(DateTime(__DATE__, __TIME__)); //uncomment to set time for the 1st time using the RTC
  
  
  DateTime now = RTC.now();   // get the current time from the RTC and load the following variables
  iYear = int(now.year());
  iMonth = int(now.month());
  iDay = int(now.day());
  iHour = int(now.hour());
  iMinute = int(now.minute());
  iSecond = int(now.second());  

  pinMode(solenoidPin, OUTPUT);                     // set the pin direction
  
  setTime(iHour,iMinute,iSecond,iDay,iMonth,iYear); // this initialises the timer with .now()
     
  Alarm.timerRepeat(alarmOneInterval, alarmOne);    // timer triggers every alarmOneInterval
  Alarm.timerRepeat(alarmTwoInterval, alarmTwo);    // timer triggers every alarmTwoInterval
  Alarm.alarmRepeat(10,0,0, dayAlarmOne);           // alarm at 10:00:00 each day
  Alarm.alarmRepeat(10,30,0, dayAlarmTwo);          // alarm at 10:30:00 each day
  Alarm.alarmRepeat(dowTuesday,20,30,0, weekAlarm); // alarm at 20:30:00 each Tuesday
  
  
  // set up the LCD's number of rows and columns: 
  lcd.begin(20, 4);
  lcd.setBacklight(HIGH);
  // Print a message to the LCD.
  lcd.print("  SmartGreenHouse!");
  lcd.setCursor(0,1);
  lcd.print("Using SPI protocol");
  lcd.setCursor(0,3);  
  lcd.print("CAT5 cable upto 100m");
}

void alarmOne()
{
  Serial.print("Alarm One triggered at : ");
    
    Serial.print("    ");
    DateTime now = RTC.now(); 
    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.println();
    // do something

}

void alarmTwo()
{
    DateTime now = RTC.now(); 
    Serial.print(now.year(), DEC);
    Serial.print('/');
    Serial.print(now.month(), DEC);
    Serial.print('/');
    Serial.print(now.day(), DEC);
    Serial.print(" ..... at : ");
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.println();  
    // do something else
}

void dayAlarmOne()
{
    Serial.print("Day alarm ONE triggered at : ");
    DateTime now = RTC.now(); 
    Serial.print(dayStr(weekday())); // print the name of the day
    Serial.print("    ");
    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.println();  
    waterState= ON;
    waterTimer(waterState); // turn on the water
}

void dayAlarmTwo()
{
    Serial.print("Day alarm TWO triggered at : ");
    DateTime now = RTC.now(); 
    Serial.print(dayStr(weekday())); // print the name of the day
    Serial.print("    ");
    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.println();
    waterState = OFF;  
    waterTimer(waterState); // turn off the water

}

void weekAlarm()
{
    Serial.print("Week alarm triggered at : ");
    DateTime now = RTC.now(); 
    Serial.print(dayStr(weekday())); // print the name of the day
    Serial.print("  ==============>   ");
    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.println();  
    // do something nice, once per week. Take your friend out for lunch perhaps?
}

void waterTimer(boolean action)
{
    if (action) 
    {
      digitalWrite(solenoidPin, HIGH); // turn on or off the water solenoid/relay
      Serial.print("Water turned on at  : ");
    } else {
      digitalWrite(solenoidPin, LOW); // turn on or off the water solenoid/relay 
      Serial.print("Water turned off at : "); 
    }
    DateTime now = RTC.now(); 
    Serial.print(dayStr(weekday())); // print the name of the day
    Serial.print("  ===============>   ");
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.println();  
}
void loop()
{ 
  // do processing here
  if(second() != currentSeconds) // just a loop to trigger the timer/alarm scheduler
  {
    currentSeconds = second();
    Alarm.delay(1);   
  }
  // now do something useful, like read sensors, send a Tweet, put on the coffee
  // add action code to the alarm functions to take an action at a specific time or time interval
  // you can also embed a timed event within another alarm function,
  // e.g. turn on the lawn sprinkler for 10 minutes every Tuesday at 10:00 pm
  // but remember to turn it off again!
  // http://smartgreenhouse.org 
}

OK - after a bit more testing... ported to a MEGA everything works correctly. Leonardo - still not working.

the same problem I have too with Leonardo , LCD and RTC

any call to RTC.xxx or to wire.xxx makes the LCD not working! (prints garbage). Any trick I tried was useless.

not only this, also I can't setup the RTClock with any command of RTC. or wire. even if I don't use the LCD.
(I haven't try to remoove it phisicaly yet) (problem resolved, wrong wiring)

any ideas? I see in Mega there is no problem but I have only leonardo :cold_sweat:

It is possible to use the internal <time.h> functions and vars instead of RTC. The 1Hz clock that uses, has the same accuracy with the RTC? (I suppose not). Also are there smaller models than MEGA without this problem? --

thanks!

Makis

OK - the SDA and SCL pins are actually D2, D3 on a Leonardo. Those were the pins I was also using for the SPI connections for the LCD display, CLK,DAT,LAT. Hence the conflict. On the Mega there was no problem, so I looked at the Leonardo documentation more carefully.

:slight_smile:

Those were the pins I was also using for the SPI connections for the LCD display, CLK,DAT,LAT.

The SPI pins are only on the ICSP header on the Leonardo. The above means that you didn't use SPI but some kind of software emulation of it.
Also the current version of the LiquidCrystal library (as of version 1.0.5 of the IDE) does not support I2C or SPI driven displays. I assume you used another library so please be so kind to post the link to it.

The pinout reference for the Leonardo is here:

Arduino Leonardo Pinout Reference | www.johngineer.com/blog/… | Flickr which clearly shows SDA/SCL on D2/D3

The library I am using for the LCD is from Adafruit, which specifically supports their I2C/SPI backpack -

After some fiddling, it works now with the Leonardo.

Arduino Leonardo Pinout Reference | www.johngineer.com/blog/… | Flickr which clearly shows SDA/SCL on D2/D3

Correct, but that are the I2C pins and not the SPI pins.

This uses the LiquidCrystal library.

This was a quote from your first post. If you tell us some lies it's quite hard to help you. The library you used is clearly stated as a modified version of the LiquidCrystal library (shame on Adafruit for not changing the library's name) and they also mislead people by talking about SPI for their bus. An SPI bus has the signals SCLK, MISO, MOSI and SS (sometimes referred to as CS). It's not offending if you don't use the MISO line (the talk back channel) but omitting the SS signal does violate the SPI definition, so what they sell is not an SPI device but some proprietary serial shift out interface.

As you can see, providing all relevant information helps us to help you, without it we're tapping in the dark.

You are quite right, of course. The Adafruit "SPI" connections DAT, CLK do the data transfer and LAT is the device select pin, allowing many devices to share DAT and CLK, with each device "latched" as needed to enable communications. It works and it is quite simple to implement.

The reason I use this is to simplify the wiring using CAT5 (CATkit/Kitten) cabling.

arbutus:
The pinout reference for the Leonardo is here:

Arduino Leonardo Pinout Reference | www.johngineer.com/blog/… | Flickr which clearly shows SDA/SCL on D2/D3

The library I am using for the LCD is from Adafruit, which specifically supports their I2C/SPI backpack -

Overview | I2C/SPI LCD Backpack | Adafruit Learning System

After some fiddling, it works now with the Leonardo.

I downloaded the LiquidCrystal.h and Adafruit_MCP23008... , I make new compile, it runs ok, but still LCD does not show any good chars.
So??? What have you change more?

I changed the "SPI" pins needed for the Adafruit backpack for the Leonardo so that they did not conflict with the I2C pins ...

// ***************************************************************************** /* The circuit: * 5V to Arduino 5V pin * GND to Arduino GND pin * CLK to Digital 2 (8 on Leonardo) * DAT to Digital 3 (9 on Leonardo) * LAT to Digital 4 (10 on Leonardo) */

#include <Wire.h>
#include <RTClib.h> //assumes SDA/SCL connections to RTC module
#include <Time.h>
#include <TimeAlarms.h>
#include "LiquidCrystal.h"

#define DS1307_I2C_ADDRESS 0x68 // the default I2C address of DS1307 RTC

int currentSeconds = 0;

RTC_DS1307 RTC; // create the RTC object instance

// Connect LCD via SPI. Data pin is #3, Clock is #2 and Latch is #4 on Mega
// Connect LCD via SPI. Data pin is #9, Clock is #8 and Latch is #10 on Leonardo
// Relates to CATkit & Kitten pins: K2; K3; K1 for remote connection
LiquidCrystal lcd(9, 8, 10);

int iYear;

how run this? ? ? the ??? (error)

clk - dat - lat?? my RT clock has SDA SCL SQW

RTC_DS1307 RTC ?? (error)

I try to compile it in arduino environment

Ah, no the RTC is on SDA/SCL

The LCD panel is on LAT/DAT/CLK

The problem was that in my original code/wiring the SDA/SCL lines are D2/D3 on a Leonardo and I was using D2/D3/D4 for the LCD display. So changing the LCD to D8/D9/D10 fixed that

I may be confused, but I thought that 2 or more I2C devices should use the same wire bus, rather than using another pair of pins. Can someone clarify my confusion ?

Thanks, Jack

arbutus:
Ah, no the RTC is on SDA/SCL

The LCD panel is on LAT/DAT/CLK

in GDM1602K.pdf I see (the LCD) : VSS (GROUND), VDD (5V), V0 (CONTRAST) ,RS (H/L Register select signal) ,
R/W (H/L Read/Write signal), E (H/L Enable signal), DB0-7 (H/L Data bus line), A and K (Backlight +/-, but in mine, witch is RGB, the reverse - and I had to find it by myself) . All with pins from 1 to 16
which ones?

I may be confused, but I thought that 2 or more I2C devices should use the same wire bus, rather than using another pair of pins. Can someone clarify my confusion ?

Correct, up to 127 devices can use the same bus wires (theoretically, practically it's usually limited by the bus capacity) but these guys want to connect an I2C devices and a device with some proprietary SPI-like serial interface that is very different from I2C. If you just use I2C devices they can share the bus.

but in mine, witch is RGB, the reverse - and I had to find it by myself) . All with pins from 1 to 16
which ones?

If your's is RGB it should have more than the 16 pins. You didn't provide a link to your hardware so it's almost impossible for us to help you further.

pylon:

If your's is RGB it should have more than the 16 pins. You didn't provide a link to your hardware so it's almost impossible for us to help you further.

I couln't find any help, discussion or schematic for the 18 pins. Only a photo with 3 colors together side by side that was writing 'normal or reverse polarity' I think.

another strange thing, as you are from arduino stuff
the Serial.available should wait until one char is pressed. But not in me, it sends ch=-1 continuously, thousands. So I had to make a function to control it.
-->
char Readchar()
{ char ch;
ch=' ';
while (ch!=-1)
{
ch= Serial.read();
// Serial.print(" sec -> "); Serial.println(ch);
return ch;
if (ch=-1) break; // I put this because while works funny, destroy the last char, should be repeat
}
}
also I got one error (stk500_getsync(): not in sync:) from Ubuntu, during upload, serial monitor works ok.
I found also others have the same problem but no solution.
Also, there is not ''leonardo'' choice in Ubuntu arduino compiler. Must have a newer version


Also I made matrix for Greek chars. There are 10 (??????????) but leonardo only 8 can accept , so the last 2 go to 1st and 2nd position.
Can't change this? Or is possible in other model of arduino?

Thanks and excuse me for the little off-topic

Don't you have a link to the page where you bought that stuff? If not, please make a sharp picture of it, maybe one of the forum members recognize the model and can provide a link to the datasheet.

Oh, I thought I understood him to say both devices were I2C devices. If they were both run as I2C, on the same bus, then it may eliminate some problems. May not be able to configure them that way I guess.

Thanks for the info.

Jack

My system is working - the problem was because pins 2,3,4 were being used for the Adafruit LCD backpack. See previous post from me.

The backpack is Overview | I2C/SPI LCD Backpack | Adafruit Learning System I AM NOT USING I2C for the LCD! It uses the Adafruit SPI protocol. This backpack could use I2C, and the address is selectable so it could work comfortably with the RTC.

The I2C device is a DS1307 RTC module using SDA/SCL (also D2,D3 on the Leonardo) address 0x68

Multiple I2C devices can be used on an I2C bus provided each device has an unique address.

Similarly the Adafruit 'SPI' system also allows multiple devices to share DAT and CLK, with device selected by LAT.

arbutus:

My system is working - the problem was because pins 2,3,4 were being used for the Adafruit LCD backpack. See previous post from me.

look, I have this LCD with the pins I wrote,
can you please write to me where to put this pins on leonardo board and then we will see about the software.

thanks!