The Start


Hi, What and Why

Plug it in

Rule number 1

Water Sensor

Sound Sensor

Joystick

Tri Colour LED

RTC (Real Time Clock) DS1302

RTC (Real Time Clock) DS3231

Matrix LED step 1

LCD

Stepper Motor

LCD revisited with PCF8574T

Humidity Sensor

Shift Register

RFID tags (RC-522)

7 Segment display

Ultrasonic distance sensor

5V regulator

analogRead and analogWrite

Wiring an Array of Switches

The next step


Other things I have bought

Infra red and Processing

Programming a separate arduino chip

Creating your own PCB

L293D for a DC motor

4 digit 7 segment display

Starting with motors

RF433 Wireless Comms

Sort a character array

More stuff


I2C devices (SDA,SCL)

I2C scanner

SPI devices (MOSI,MISO)

HMC5883L Compass

MMA7361 Accelerometer

Added projects


Message Display System

4WD robot car
4WD robot car II

4WD robot car COMPLETE

MP3 Player

I2C devices


If something has connectors labelled SDA and SCL, then it is an i2c device that can be accessed using the Wire.h library. You can daisy chain several of these devices together, providing each device has a unique address.

Arduino Uno :
SDA goes to pin A4,
SCL goes to pin A5.

Get the address of an i2c device by plugging it in, and runnning the i2c scanner.

If you have several of the same devices with the same address, eg 15 barometric sensors of the same type, then you have a clear choice: either reset the addresses to make each one unique (this is possible with some but not necessarily all devices), or you plug each one into a different arduino.

Daisy chained i2c devices:
This is my RTC (Real Time Clock) DS3231 connected to my LCD (which is being managed by that highly recommended interface board, the PCF8574T )
i2c devices

The RTC DS3231 has a Very handy set of SCL, SDA, GND and VCC connectors, for the purpose of daisy chaining i2c devices. Above, I have quickly found randomly coloured cables and connected SDA-SDA, SCL-SCL, etc.
This is the code that I used. Note that I am _not_ using a library for the DS3231; I love the code to access it directly.

#include <Wire.h>					// For the i2c devices
#include <LiquidCrystal_I2C.h>	// For the LCD

LiquidCrystal_I2C lcd(0x27,16,2);  // set the LCD address to 0x27 for a 16 chars and 2 line display

#define DS3231_I2C_ADDRESS 104		// RTC is connected, address is Hex68 (Decimal 104)

// SCL - pin A5
// SDA - pin A4
// To set the clock, run the sketch and use the serial monitor.
// Enter T1124154091014; the code will read this and set the clock. See the code for full details.
//
byte seconds, minutes, hours, day, date, month, year;
char weekDay[4];

byte tMSB, tLSB;

float my_temp;

char my_array[100];            // Character array for printing something.

void setup()
{
  Wire.begin();
  Serial.begin(9600);
  lcd.init();                      // initialize the lcd 

  
}

void loop()
{
 
  watchConsole();
 
 
  get3231Date();
 
  Serial.print(weekDay); Serial.print(", "); Serial.print(date, DEC); Serial.print("/"); Serial.print(month, DEC);
   Serial.print("/"); Serial.print(year, DEC); Serial.print(" - ");
  Serial.print(hours, DEC); Serial.print(":"); Serial.print(minutes, DEC); Serial.print(":"); Serial.print(seconds, DEC);

  my_temp = (float)get3231Temp();
 
  Serial.print(" - Temp: "); 
  Serial.println(my_temp);
  
  // NOTE: Arduino does NOT implement printing floats to a string.
  // If you use the std C function : sprintf(my_array, "Temp: %4.2f", my_temp), It will NOT CONVERT.
  // So I abandoned this, since I don't need to print the float to the LCD anyway.
  
sprintf(my_array, "Time: %d-%d-%d", hours, minutes, seconds);

// Print a message to the LCD.
  lcd.backlight();
  lcd.setCursor(0,0);
  lcd.print("Test Display I2C");
  lcd.setCursor(0,1);
  lcd.print(my_array);
  delay(1000);
}

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

void watchConsole()
{
  if (Serial.available()) {      // Look for char in serial queue and process if found
    if (Serial.read() == 84) {      //If command = "T" Set Date
      set3231Date();
      get3231Date();
      Serial.println(" ");
    }
  }
}
 
void set3231Date()
{
//T(sec)(min)(hour)(dayOfWeek)(dayOfMonth)(month)(year)
//T(00-59)(00-59)(00-23)(1-7)(01-31)(01-12)(00-99)
//Example: 02-Feb-09 @ 19:57:11 for the 3rd day of the week -> T1157193020209
// T1124154091014
  seconds = (byte) ((Serial.read() - 48) * 10 + (Serial.read() - 48)); // Use of (byte) type casting and ascii math to achieve result.  
  minutes = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
  hours   = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
  day     = (byte) (Serial.read() - 48);
  date    = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
  month   = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
  year    = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0x00);
  Wire.write(decToBcd(seconds));
  Wire.write(decToBcd(minutes));
  Wire.write(decToBcd(hours));
  Wire.write(decToBcd(day));
  Wire.write(decToBcd(date));
  Wire.write(decToBcd(month));
  Wire.write(decToBcd(year));
  Wire.endTransmission();
}


void get3231Date()
{
  // send request to receive data starting at register 0
  Wire.beginTransmission(DS3231_I2C_ADDRESS); // 104 is DS3231 device address
  Wire.write(0x00); // start at register 0
  Wire.endTransmission();
  Wire.requestFrom(DS3231_I2C_ADDRESS, 7); // request seven bytes

  if(Wire.available()) {
    seconds = Wire.read(); // get seconds
    minutes = Wire.read(); // get minutes
    hours   = Wire.read();   // get hours
    day     = Wire.read();
    date    = Wire.read();
    month   = Wire.read(); //temp month
    year    = Wire.read();
       
    seconds = (((seconds & B11110000)>>4)*10 + (seconds & B00001111)); // convert BCD to decimal
    minutes = (((minutes & B11110000)>>4)*10 + (minutes & B00001111)); // convert BCD to decimal
    hours   = (((hours & B00110000)>>4)*10 + (hours & B00001111)); // convert BCD to decimal (assume 24 hour mode)
    day     = (day & B00000111); // 1-7
    date    = (((date & B00110000)>>4)*10 + (date & B00001111)); // 1-31
    month   = (((month & B00010000)>>4)*10 + (month & B00001111)); //msb7 is century overflow
    year    = (((year & B11110000)>>4)*10 + (year & B00001111));
  }
  else {
    //oh noes, no data!
  }
 
  switch (day) {
    case 1:
      strcpy(weekDay, "Sun");
      break;
    case 2:
      strcpy(weekDay, "Mon");
      break;
    case 3:
      strcpy(weekDay, "Tue");
      break;
    case 4:
      strcpy(weekDay, "Wed");
      break;
    case 5:
      strcpy(weekDay, "Thu");
      break;
    case 6:
      strcpy(weekDay, "Fri");
      break;
    case 7:
      strcpy(weekDay, "Sat");
      break;
  }
}

float get3231Temp()
{
  float temp3231;
  
  //temp registers (11h-12h) get updated automatically every 64s
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0x11);
  Wire.endTransmission();
  Wire.requestFrom(DS3231_I2C_ADDRESS, 2);
 
  if(Wire.available()) {
    tMSB = Wire.read(); //2's complement int portion
    tLSB = Wire.read(); //fraction portion
   
    temp3231 = (tMSB & B01111111); //do 2's math on Tmsb
    temp3231 += ( (tLSB >> 6) * 0.25 ); //only care about bits 7 & 8
  }
  else {
    //oh noes, no data!
  }
   
  return temp3231;
}