• Skip to main content
  • Skip to header right navigation
  • Skip to site footer
CDP Studio logo

CDP Studio

The no-code and full-code software development tool for distributed control systems and HMI

  • Doc
  • Why CDP
    • Software developers
    • Automation engineers
    • Managers
  • Products
    • Automation Designer
    • HMI Designer
    • Maritime HMIs
  • Services
  • Use cases
  • Pricing
  • Try CDP

CDP Studio Documentation

  • Protocols - I2C I/O
  • I2C I/O Communicating with Arduino compatible microcontrollers
  • 5.0.0

I2C Setup Guide Protocols - I2C I/O

I2C I/O Communicating with Arduino compatible microcontrollers

Prerequisites

In order to continue with the instructions below you need to make sure that you have enabled SSH and I2C on the device you will be deploying to.

Setting up the project in Studio

Adding the I2CIOServer

First, we add an I2CIOServer component to our system.

Selecting the I2C adapter

Then we enter the component.

We need to scroll down to properties and enter the correct i2c adapter.

Note: You can run "i2cdetect -l" from the terminal to list the available i2c adapters. If you can not see any available adapters then make sure that you have enabled the I2C and reboot.

Adding our I2CDevice (The Arduino)

We select the I2CIOServer component.

Then we enter a name and select I2CDevice from the "Model" dropdown.

We then type in the device's I2C address.

Note: We will specify this same address in the Arduino code later.

Adding the I2CRegisterWrite

We type in a name for our channel group.

We don't need to change the hidden Input property

We type in an address for our channel.

Note: In the Arduino code, we will handle these addresses with a simple switch case. The raw I2C data that will be transmitted to the Arduino will be "channel address" one byte, followed by the data in the channel.

Setting up the data we will transmit

We type in a name for our data.

We select a datatype "Model".

Note: If the data is larger than 1 byte in size then it will be split into several writes, the bytes will be sent in the order "least significant first". In the Arduino code, we will have to read in the data one byte at a time. The "short" type in this case will use 16 bits i.e. 2 bytes.

The input box should be pre-ticked because we wish to input data into this SignalChannel in RegisterWrite operation.

Setting up our Arduino as an I2C Slave

Note: One important thing to remember is that if you wish the Arduino to be the I2C Master then you would need a level converter for the logic. This is because the Arduino operates using a 5-volt logic level, the Raspberry is only constructed for a 3.3-volt logic level. However, this is not a problem as long as the Raspberry is the Master, because the master sets the voltage and 3.3 is still read correctly by the Arduino.

Here you can see the code sample for the Arduino. You can upload it to your Arduino using the Arduino IDE. The channel address that we use to send from the Raspberry "10" is defined as "POSITION_I2C_ADDRESS". In the handleIncoming function, we use the i2c_channel variable to store the channel address. The "ls" and "ms" are the bytes sent from the Raspberry. We configured the Raspberry to send a 16-bit short, in the Arduino it gets read in one byte at a time (8 -it).

If you decide to use a larger type then you need to handle this. If you decide to expand upon this code then you could handle this in the channel's case inside the switch statement.

#include <Wire.h>

#define POSITION_I2C_ADDRESS 0x10
#define ARDUINO_I2C_ADDRESS 0x04

int position = 0;
int i2c_channel;

void setup() {
  // If an I2C address is not specified then we join as master.
  // We initialize i2c as a slave with 4 as our address.
  Wire.begin(ARDUINO_I2C_ADDRESS);

  // We start the serial communication with a 9600 baud rate.
  // In order to print out our values.
  Serial.begin(9600);

  // We provide callback functions to handle the I2C interrupts
  Wire.onReceive(handleIncoming);
  Wire.onRequest(handleOutgoing);
}

void loop() {
  delay(100);
}

// interrupt callback to handle incoming I2C communication
void handleIncoming(int byteCount){
  i2c_channel = Wire.read();
  int ls = Wire.read();
  int ms = Wire.read();

  switch(i2c_channel){
    case POSITION_I2C_ADDRESS:
      position = (ms << 8) | ls;
      Serial.print(position);
      break;
  }

  // Flush if remaining
  while(Wire.available())
    Wire.read();
}

// We are not going to be sending back any values over I2C
void handleOutgoing(){
}

Wiring the Raspberry to the Arduino

We wire the SDA, SCL and ground pins together.

Running the system

With the Arduino and the Raspberry Pi wired up we just need to run the respective programs. We will upload the Arduino sketch using the Arduino IDE. After the sketch has been successfully uploaded we have to open the Serial monitor at 9600 baud rate. Next, we need to deploy and run the CDP System on the Raspberry Pi. When everything is running we can connect to the system and set the position variable in configure mode. The variable should then get sent to the Arduino over I2C and the ArduinoIDE's Serial monitor should output the new value.

I2C Setup Guide Protocols - I2C I/O

The content of this document is confidential information not to be published without the consent of CDP Technologies AS.

CDP Technologies AS, www.cdpstudio.com

Get started with CDP Studio today

Let us help you take your great ideas and turn them into the products your customer will love.

Try CDP Studio for free
Why CDP Studio?

CDP Technologies AS
Hundsværgata 8,
P.O. Box 144
6001 Ålesund, Norway

Tel: +47 990 80 900
E-mail: info@cdptech.com

Company

About CDP

Contact us

Services

Partners

Blog

Developers

Get started

User manuals

Support

Document download

Release notes

My account

Follow CDP

  • LinkedIn
  • YouTube
  • GitHub

© Copyright 2025 CDP Technologies. Privacy and cookie policy.

Return to top