I2C Information

Hitchhikers Guide to i2c

  1. What is i2c

Basic: i2c means Inter-Integrated Circuit and it´s a bus-system for attaching low-speed peripherals. According to Wikipedia.

  1. Pin Map of the Core

D0 = SDA; D1=SCl -> here is the mapping of the complete :spark: core pins

  1. Do I have to use pullup-resistors

Mhm, not exactly sure, but let me say I have to. I have a 16x2 LiquidCrystal Display with an i2c backpack from sainsmart (2004) - when I try to find the correct i2c adress without 4,7K Ω resistors the scanner did not find any adress.

  1. What, you say scanner?

Yes, the i2c adress can be from 0x01 to 0x7E and higher. Sometimes when you buy a i2c device the reseller gives you the information that the adress is 0x… and you try it and the device did not do anything. So chances are high that you send your commands to the wrong adress. Therefore is better to quick fire up a scanner and off you go!
I used the scanner from Arduino Playground. Just copy the raw content to :spark: Cloud IDE and change the line:

#include <Wire.h>


#include "application.h"

We are finally there - now open up the serial monitor of your choice and connect to the core. You should no find a line like this:

I2C device found at address 0x3F  !

you´ve received a free towel and can fetch it every time you want on Alpha Centauri

Read the Docs. On Mac there is CoolTerm, but site from the-meiers is currently down (4days or more by now). I use SerialTools on Mac instead. It´s completely up to you which one you choose.

So hopefully I did all things right, next up bring the 1602lcd i2c lib to life!


Now, this could easily be posted to a wiki by anyone; if there was one :frowning:

1 Like

Some other hints…

How Does I2C Work?

All I2C communications are buffered. Write transmissions are not made until EndTransmission() is called, and reads are made all at once when requestFrom() is called. This means that delays between subsequent calls to read() and write() are not critical timing wise.

That sounds good. What are the implications?

Well, since all I2C communications are buffered, the communications need to be stored somewhere. This is within a fixed length buffer. This buffer is currently limited to 32 bytes.

What happens if I want to read more than 32 bytes?

You could re-compile with a different buffer size, but the easiest way is to break up your communications. Just create a separate sequence from BeginTransmission and you should be fine. [Having said that, in practice the number might be 31 - this needs to be checked in practice]


I’m trying to scan the I2C devices, but my Core keeps rebooting after around a second of cyan light. It goes white -> green blinking -> cyan blinking -> cyan steady and then reboots.

If I attach to the serial port in the quick amount of time available while it is cyan, I just read “I2C Scanner Scannin” and then it drops. Any idea?

@alessandroorru, are there pull-up resistors on the I2C lines? Which system firmware version are you running?

Yes, I placed the two 4.7k resistors on the i2c lines to the 3.3v of the Core. The I2C driver is powered by an external 5v supply. The firmware version should be 0.5.2.

@alessandroorru, when you say “I2C driver” what are you referring to? Which I2C device have you connected?

Sorry, I have one this:

it is attached to an LCD 20x4 display.

The problem seems to be in the “Wire.begin()” call. If I remove it, the loop will work as expected, the Core will not reboot, but of course it doesn’t find any device.

@alessandroorru can you post your code?

I copied and pasted the one linked in the original code, just replacing the import line (as stated in the original post).

You could try to add Particle.process() inside your scanning loop and most likely you’ll also need to add it in setup() here

void setup()
  while (!Serial) Paricle.process();    // <-- to keep cloud connection alive
  Serial.println("\nI2C Scanner");

Unfortunately it didn’t help. I tried to put it in different places, but nothing changes. I also tried using MANUAL mode, avoiding the connection to the cloud, but it still reboots (even if just turning on and off the white light).

The reboot cycle lasts really a few seconds, it seems like that the call to Wire.begin() makes it crash…

@alessandroorru, I suggest the following:

  1. Connect the pull-up resistors to the same 5V supply powering the I2C board.
  2. MAKE SURE the grounds for the photon (GND) and the I2C board are connected together (ie common ground)

Once this is done, try again. If you are powering the Photon via USB, you could power the I2C board and the display via the Photon’s Vin pin which is just below Vusb or 5v.

Ok I checked the connections a few times and I have been able to run the scan at the end. Thank you!

This is very handy!! THANKS!!!

1 Like

Your wish is my command - better later than never:

One more note on I2C addresses: when sent over the wire, the address is sent in bits 7 thru 1 of the byte, with the read/write flag in bit 0. Some data sheets have the device address in bits 0 thru 6 (and it’s sent as addr << 1 | readWriteFlag ), and some data sheets have the device address in bits 1 thru 7 (and it’s sent as addr | readWriteFlag ). Case in point: the data sheet for the DS3231MZ+ real time clock shows the address as 0xD0. Note that bit 7 is set… this address is already shifted left by one. But the “Wire” library for the Photon expects the address be 00 to 7F – NOT shifted left! The interface for the DS3231MZ+ didn’t work until I shifted the address right by one bit – to 0x68. When you give this address to the Photon beginTransmission( ) function, it shifts it left (to 0xD0) and applies the appropriate read or write bit in bit 0.

Net result: if the address in the data sheet doesn’t work (especially if it’s in the range 0x80 to 0xFE!), try shifting it right by one bit!

Hope this helps ---- Dale


Might help somebody else with an Electron…

The Electron has 3 Serial ports so you need to change Serial to Serial1 in your code if your using the first Serial port, USART1_TX, USART1_RX and GND.


One point to remember when using I2C devices is that the signal level of the I2C line is usually proportiontal to the voltage of the device. So for example the core, photon and electron are at heart 3.3V devices. Which means they are expecting to see 3.3 volt signals on the I2C bus.

You mentioned you were powering the LCD screen via a seperate 5 volt source. Which means it is real likely that the LCD screen is talking back to the particle device at 5 volt I2C signals. That not a good thing to do.

You might want to consider putting a level shifter between the LCD screen and the particle device, which will do the jon of uping and downing the I2C bus data between the two.

Something like:-

Will do the trick nicely.


1 Like