RGB LED Matrix (SPI) + RealTimeClock (I2C) Wire.h

Hi all,

I'm trying to scroll the time provided by an RTC Clock on an 8x8 LED Matrix. 8) :smiley:

DEVICES:
-Arduino Duemilanove

-RGB LED Matrix 8x8 (Serial Interface SPI)

  • has a Serial Interface which uses SPI
  • I've reprogrammed the Atmega328P on the Backpack of the matrix through ArduinoISP. That allows me to use the Sparkfun LED Matrix Library without having erroneous LEDs on the Matrix.
  • I'm using the Sparkfun LED Library to control the LED Matrix which is not a Standard Library and does not include the Standard SPI Library. (I think it uses some kind of its own SPI configuration.)
    Link for the tutorial and library: Controlling RGB Matrices with Arduino - SparkFun Electronics

-RealTimeClock (uses I2C)

  • I'm using the standard Wire.h library included in the arduino software.

PROBLEM:
Problem with combining SPI (custom library) + I2C (Wire.h)
I've managed to control both devices in a separate sketch. They work fine, as long as I use them in a separate sketch. As soon as I try to bring the LED MATRIX Sketch and the RTC Sketch together in one sketch nothing works anymore.

As an example: I'm trying to copy the RTC Sketch step by step into the RGB LED Matrix Sketch. As soon as I import the Wire.h Library into the RGB LED MATRIX Sketch nothing works anymore. The program stops without even printing out Serial Outputs.
(I think it could have to do with the (maybe Clock)Configuration of both Libraries.) (both libraries could change global variables which are used by both to different values and so violate the communication.)

SKETCHES

-RGB LED MATRIX Sketch
Pin 13,12,11,10,VCC,GND
RGB LED Matrix Sketch:

//Add libraries for using the LED Matrices
#include <RGB.h>
#include <RGBMatrix.h>

int NUM_BOARDS = 1;
char colors[8] = {BLACK, RED, GREEN, BLUE, ORANGE, MAGENTA, TEAL, WHITE};

void setup()
{
    delay(5000);
    pinMode(10, OUTPUT);
    RGBMatrix.begin(NUM_BOARDS);
    Serial.begin(9600);
}

void loop()
{  
    // scroll example time
    RGBMatrix.scroll(" 17:32", ORANGE, 50);
    RGBMatrix.clear(); 
}

Library Files:
RGBMatrix.h

/* 
 * Copyright 2010 SparkFun Electronic
 * Written by Ryan Owens
*/

#ifndef RGBMatrix_h
#define RGBMatrix_h

#include <avr/pgmspace.h>
#include "WProgram.h"

//Define the SPI Pin Numbers
#define DATAOUT 11		//MOSI
#define DATAIN  12		//MISO 
#define SPICLOCK  13	//sck
#define SLAVESELECT 10	//ss

#define NUM_ROWS	8
#define NUM_COLUMNS	8
#define NUM_PIXELS	64
#define BUFFER	10	//Maximum frame is 8 boards. Buffer can hold an additional char
					//before and after first/last character.

class cRGBMatrix
{
	public:
		/*
			RGB Class constructor
			Sets the number of boards currently connected in the matrix system
			Inputs: int num_boards - The number of boards in the system
			Usage: RGBMatrix myMatrix(NUM_BOARDS);
		*/
		cRGBMatrix(int num_boards);
		cRGBMatrix(void);
		
		/*
			Configures SPI and I/O for communication with an RGB Matrix.
			Note: Pinout should reflect the pin assignments in the RGBMatrix.h file
		*/		
		void begin(int num_boards);
		
		/*
			Sets the color of a pixel on a given matrix
			Inputs: int screen - The specific matrix to have a pixel set
					int row - The row of the pixel to be set
					int column - The column of the pixel to be set
					char color - The color to be used for the pixel fill.
			Returns: 1 - Success
					 0 - Failure (invalid screen, row or column)
		*/
		char fillPixel(int screen, int row, int column, char color);
		
		/*
			Fills a coloumn on a single matrix of the screenBuffer.
			Note: display won't be updated until display() function is called.
			Inputs: int screen - The specific matrix to have a column filled
					int column - The column number to be filled
					char color - The color used for the fill
			Returns: 1 - Success
					 0 - Failure (causes are invalued screen or column number)
		*/		
		char fillColumn(int screen, int column, char color);
		
		/* 
			Fills a row on a single matrix of the screenBuffer.
			Note: display won't be updated until the display() function is called
			Inputs: int screen - The matrix to have a row filled
					int row - The row to be filled
					char color - The color to be used for the fill
			Returns: 1 - Success
					 0 - Failure (invalid screen or row)
		*/		
		char fillRow(int screen, int row, char color);
		
		/*
			Fills a screen in the screenBuffer
			Note: display won't be updated until the display() function is called.
			Inputs: int screen - The screen to be filled
					char color - The color to be used for the fill.
			Returns: 1 - Success
					 0 - Failure (invalid board)
		*/		
		char fillScreen(int screen, char color);
		
		/*
			Puts a character into a posotion in the screenBuffer
			Note: display won't be updated until the display() function is called.
			Inputs: int screen - The matrix that will get the character
					char letter - The letter to put onto the screen
					char color - The color of the letter
			Returns: 1 - Success
		*/		
		char fillChar(int screen, char letter, char color);
		
		/*
			Puts a character into a position in the screenBuffer
			Note: display won't be updated until the display() function is called.
			Inputs: int screen - The matrix that will get the character
					char letter - The letter to put onto the screen
			Returns: 1 - Success
		*/
		char fillCharRandomColor(int screen, char letter);
		/*
			Scrolls an entire message on and off of the frame.
			Inputs: char * message - The message to be scrolled
					char color - The color for the text
					int speed - The scroll speed for the message
		*/		
		char scroll(char * message, char color, int speed);
		
		/*
			Scroll an entire message on and off of the frame.
			Inputs: char * message - The message to be scrolled
			int speed - The scroll speed for the message
		*/
		char scrollRandomColor(char * message, int speed);

		/*
			Sends the data in screenBuffer to the matrices.
		*/		
		void display(void);
		/*
			Clears the entire frame by filling all the screens with Black
		*/		
		void clear(void);
		
	private:
		/*
			Sends/receives a single byte to the SPI port.
			Inputs: char value - The value to be sent to the SPI port
			Returns: Value received from the SPI port
		*/	
		char spiTransfer(char value);
		
		/*
			Sends the frame of data determined by the screen parameter
			Inputs: char * screen - The 64 byte buffer to send over SPI
		*/		
		void sendScreen(char * screen);

		/*
			Scrolls a single fame onto and off of the frame.
			Inputs: int speed - The scroll speed
		*/		
		void scrollBuffer(int speed);
		int _num_boards;
};

extern cRGBMatrix RGBMatrix;

#endif

-Missing Library Files: RGBMatrix.cpp & RGB.h
Please download it here: Controlling RGB Matrices with Arduino - SparkFun Electronics
(They're too bit for a post.)

RTC Sketch in next post.

-RTC Sketch (uses Standard Wire.h Library)
Pin 3, 4, 5, VCC, GND

#include "Wire.h"
#define DS1307_ADDRESS 0x68

int potentioPIN = 3;

void setup(){
  Wire.begin();
  Serial.begin(9600);
  delay(300);
  Serial.println("-------CLOCK STARTED-------");
  printAllInformation();
  Serial.println("---------------------------");
  Serial.println();
  delay(300);
  pinMode(potentioPIN, INPUT);  
}

void loop(){
  for(int i=0; i<2000; i++){
    Serial.println(getTime());
    delay(1000);
    int pV = analogRead((potentioPIN));
    Serial.println(pV);
    if(pV<100)changeHour(-1);
    else if(100<=pV&&pV<200)changeMinute(-1);
    else if(800<pV&&pV<=900)changeMinute(1);
    else if(900<pV)changeHour(1);
  }
}

// CONVERTERS ##########################################################################################################
byte decToBcd(byte val){
// Convert normal decimal numbers to binary coded decimal
  return ( (val/10*16) + (val%10) );
}
byte bcdToDec(byte val)  {
// Convert binary coded decimal to normal decimal numbers
  return ( (val/16*10) + (val%16) );
}
// END: CONVERTERS #####################################################################################################



// TIME GETTERS ########################################################################################################

// PRINT SETUP ---------------------------------------------------------------------------------------------------------
void printAllInformation(){
  // Reset the register pointer
  Wire.beginTransmission(DS1307_ADDRESS);
  Wire.send(0);
  Wire.endTransmission();

  Wire.requestFrom(DS1307_ADDRESS, 7);

  int second = bcdToDec(Wire.receive());
  int minute = bcdToDec(Wire.receive());
  int hour = bcdToDec(Wire.receive() & 0b111111); //24 hour time
  int weekDay = bcdToDec(Wire.receive()); //0-6 -> sunday - Saturday
  int monthDay = bcdToDec(Wire.receive());
  int month = bcdToDec(Wire.receive());
  int year = bcdToDec(Wire.receive());

  //print the date EG hour:min:sec - WD, DD:MM:YYYY
  String h = hour;
  if(hour<10) h = "0"+h;
  String m = minute;
  if(minute<10) m = "0"+m;
  String s = second;
  if(second<10) s = "0"+s;
  Serial.print(h);
  Serial.print(":");
  Serial.print(m);
  Serial.print(":");
  Serial.print(s);
  Serial.print(" - ");
    switch(weekDay){
    case 1:
      Serial.print("MO"); // Weekdays in German
      break;
    case 2:
      Serial.print("DI");
      break;
    case 3:
      Serial.print("MI");
      break;
    case 4:
      Serial.print("DO");
      break;
    case 5:
      Serial.print("FR");
      break;
    case 6:
      Serial.print("SA");
      break;
    case 7:
      Serial.print("SO");
      break;
    default: break;
  }
  Serial.print(", ");
  Serial.print(monthDay);
  Serial.print(".");
  Serial.print(month);
  Serial.print(".20");
  Serial.println(year);
}
// END: PRINT SETUP ----------------------------------------------------------------------------------------------------

// GET TIME ------------------------------------------------------------------------------------------------------------
String getTime(){
  // Reset the register pointer
  Wire.beginTransmission(DS1307_ADDRESS);
  Wire.send(0);
  Wire.endTransmission();

  Wire.requestFrom(DS1307_ADDRESS, 7);

  int second = bcdToDec(Wire.receive());
  int minute = bcdToDec(Wire.receive());
  int hour = bcdToDec(Wire.receive() & 0b111111); //24 hour time
  int weekDay = bcdToDec(Wire.receive()); //0-6 -> sunday - Saturday
  int monthDay = bcdToDec(Wire.receive());
  int month = bcdToDec(Wire.receive());
  int year = bcdToDec(Wire.receive());
  
  String h = hour;
  if(hour<10) h = "0"+h;
  String m = minute;
  if(minute<10) m = "0"+m; 
  String all = h+":"+m;
  return all;
}
// END: GET TIME -------------------------------------------------------------------------------------------------------

// END: TIME GETTERS ###################################################################################################



// TIME SETTERS ########################################################################################################

// CHANGE HOUR (DESIGNED FOR +-1) --------------------------------------------------------------------------------------
void changeHour(int h){
  // Reset the register pointer
  Wire.beginTransmission(DS1307_ADDRESS);
  Wire.send(0);
  Wire.endTransmission();

  Wire.requestFrom(DS1307_ADDRESS, 7);

  int second = bcdToDec(Wire.receive());
  int minute = bcdToDec(Wire.receive());
  int hour = bcdToDec(Wire.receive() & 0b111111); //24 hour time
  int weekDay = bcdToDec(Wire.receive()); //0-6 -> sunday - Saturday
  int monthDay = bcdToDec(Wire.receive());
  int month = bcdToDec(Wire.receive());
  int year = bcdToDec(Wire.receive());
  
  if(hour==23) hour = 0;
  else hour = hour + h;
  
  delay(200);
  Serial.print("Changing hour: ");
  if(h>0) Serial.print("+");
  Serial.println(h);
  delay(200);
  
  setDateTime(second, minute, hour, weekDay, monthDay, month, year);  
}
// END: CHANGE HOUR ----------------------------------------------------------------------------------------------------

// CHANGE MINUTE (DESIGNED FOR +-1) ------------------------------------------------------------------------------------
void changeMinute(int m){
  // Reset the register pointer
  Wire.beginTransmission(DS1307_ADDRESS);
  Wire.send(0);
  Wire.endTransmission();

  Wire.requestFrom(DS1307_ADDRESS, 7);

  int second = bcdToDec(Wire.receive());
  int minute = bcdToDec(Wire.receive());
  int hour = bcdToDec(Wire.receive() & 0b111111); //24 hour time
  int weekDay = bcdToDec(Wire.receive()); //0-6 -> sunday - Saturday
  int monthDay = bcdToDec(Wire.receive());
  int month = bcdToDec(Wire.receive());
  int year = bcdToDec(Wire.receive());
  
  if(minute==59) minute = 0;
  else minute = minute + m;
  
  delay(200);
  Serial.print("Changing minutes: ");
  if(m>0) Serial.print("+");
  Serial.println(m);
  delay(200);
  
  setDateTime(second, minute, hour, weekDay, monthDay, month, year);  
}
// END: CHANGE MINUTE --------------------------------------------------------------------------------------------------

// SET TIME ------------------------------------------------------------------------------------------------------------
void setDateTime(int second, int minute, int hour, int weekDay, int day, int month, int year){
  
  byte s = (byte) second; //0-59
  byte m = (byte) minute; //0-59
  byte h = (byte) hour; //0-23
  byte w = (byte) weekDay; //1-7
  byte d = (byte) day; //1-31
  byte m2 = (byte) month; //1-12
  byte y  = (byte) year; //0-99

  Wire.beginTransmission(DS1307_ADDRESS);
  Wire.send(0); //stop Oscillator

  Wire.send(decToBcd(s));
  Wire.send(decToBcd(m));
  Wire.send(decToBcd(h));
  Wire.send(decToBcd(w));
  Wire.send(decToBcd(d));
  Wire.send(decToBcd(m2));
  Wire.send(decToBcd(y));

  Wire.send(0); //start 

  Wire.endTransmission();
  
  delay(300);
  Serial.println("Time changed!");
  delay(300);
}
// END: SET TIME -------------------------------------------------------------------------------------------------------

// END: TIME SETTERS ###################################################################################################

Could you please help me combining these two sketches?

I don't know why the sketches can't be combined together even if they use different Pins. :astonished:

Thanks for your help!

greets

what i've learned so far today is, that combining I2C and SPI on one microcontroller is like running a car with diesel and oil at the same time - it won't work. I'll try to find an RTC Clock which has an SPI Interface, because it will be harder to find an RGB Matrix with an I2C Interface.

I'm open for suggestions.

Thanks

Greets