Go Down

Topic: I2C and SPI conflict (Read 10192 times) previous topic - next topic

arbutus

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!!!!!
Code: [Select]

             
// *****************************************************************************
// ** 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
}
Don't breath in the magic smoke!

arbutus

OK - after a bit more testing...  ported to a MEGA everything works correctly.  Leonardo - still not working.
Don't breath in the magic smoke!

apollonios

#2
Jul 24, 2013, 05:58 pm Last Edit: Jul 24, 2013, 09:23 pm by apollonios Reason: 1
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   :smiley-roll-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

arbutus

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.

:)
Don't breath in the magic smoke!

pylon

Quote
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.

arbutus

The pinout reference for the Leonardo is here:

http://www.flickr.com/photos/johngineer/7329403498/  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 -

http://learn.adafruit.com/i2c-spi-lcd-backpack

After some fiddling, it works now with the Leonardo.

Don't breath in the magic smoke!

pylon

Quote
http://www.flickr.com/photos/johngineer/7329403498/  which clearly shows SDA/SCL on D2/D3


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

Quote
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.

arbutus

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.
Don't breath in the magic smoke!

apollonios

#8
Jul 24, 2013, 10:04 pm Last Edit: Jul 24, 2013, 10:06 pm by apollonios Reason: 1

The pinout reference for the Leonardo is here:

http://www.flickr.com/photos/johngineer/7329403498/  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 -

http://learn.adafruit.com/i2c-spi-lcd-backpack

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?

arbutus

#9
Jul 25, 2013, 02:00 am Last Edit: Jul 25, 2013, 03:27 am by arbutus Reason: 1
I changed the "SPI" pins needed for the Adafruit backpack for the Leonardo so that they did not conflict with the I2C pins ...

<code>
// *****************************************************************************
/* 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;

</code>
Don't breath in the magic smoke!

apollonios

#10
Jul 25, 2013, 02:47 pm Last Edit: Jul 25, 2013, 02:57 pm by apollonios Reason: 1
how run this? ? ? the <code>??? (error)

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

RTC_DS1307 RTC ??  (error)

I try to compile it in arduino environment


arbutus

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
Don't breath in the magic smoke!

jack wp

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

apollonios

#13
Jul 25, 2013, 05:33 pm Last Edit: Jul 25, 2013, 05:35 pm by apollonios Reason: 1

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?

pylon

Quote
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.

Quote
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.

Go Up