8 channel 20 amp i2c current sensor board with Arduino Leonardo

Hey folks, first post here to please go easy on me. I’ve been working on a current monitoring project using the analog inputs of the Arduino Leonardo. I use an Ethernet Shield 2 to allow me to remotely monitor the current levels of each input. Each current value is nicely displayed on an array of dynamic virtual gauges written in AJAX hosted on a small webpage stored on the microSD card of the Ethernet shield. So far, I’ve successfully displayed the value of each analog input using a 10k potentiometer in place of an actual current sensor.
For simplicity, rather than purchasing current transformers for each analog input and building the necessary circuits to interface them with the Arduino, I’ve instead purchased an “8-Channel 20-Amp AC Current Monitor with I2C Interface” board from NCD. I hope to capture each of the 8 current sensor values via the i2c Arduino interface and display them on these virtual gauges.
I have absolutely no experience with i2c however, I believe I’ve done enough research to correctly connect the 8-Channel Current Monitor board to my Arduino’s Ground, SDA, and ACL pins. The board is powered by its own 12 volt power adapter so I don’t believe I need the +5 volt connection (please tell me if I’m mistaken).
I’m hoping someone might be able to point me to a simple Arduino sketch which will allow me to monitor the numeric value of at least a single channel on the current monitor board. If there is a topic on this forum explaining the use of a i2c current sensor with an Arduino Leonardo, I must have missed it. Any direction you might be able to point me in would be greatly appreciated.
Thank you in advance!

Hi Aaron,
Here you go

i2C is super easy :slight_smile:
let me know if you need anything else.

Thanks

@Bhaskar, thanks for your help! I loaded the sketch found on your GitHub page (PECMAC/Arduino/PECMAC125A.ino) but was not able to see any output on the serial monitor window. I assume even if there was no current being detected, the output would still show the “Channel :” and “Current :” texts but with null values.
I suspect the sketch might not be directly compatible with the Leonardo Arduino board without some minor code changes (only guessing here).
The Leonardo i2c pins are Digital 2 (SDA) and Digital 3 (SCL). Perhaps this needs to be set somewhere in the sketch?
On a positive note, I did confirm that I have the current monitor board correctly connected via the Leonardo’s i2c interface using a i2c scanner sketch I found via a Google search…
https://www.hackster.io/abdularbi17/how-to-scan-i2c-address-in-arduino-eaadda
My Leonardo recognized the device at the expected address of 0x2A!

20:33:06.370 -> Scanning...
20:33:06.370 -> I2C device found at address 0x2A !
20:33:06.370 -> done

If you have any ideas or suggestions for next steps, I’m all ears.
Thank you,
Aaron

the serial terminal baudrate is 9600.

define the i2c as wire.begin(2,3)

Given that the i2c scanner sketch I tried earlier correctly probed the 8 channel current monitor board with an i2c Device Address of 0x2A, I assume that I do not need to define the SCL and SDA pins in the sketch. This must be defined (or assumed) in the sketch already.
The i2c communication seems to be successfully established between my Leonardo Arduino and the 8 channel current monitor board so I suspect that the issue is likely with how I’m trying to call the Internal Register Address or Data values for each current probe on this board.
The serial baud rate is already set to 9600 and the Serial Monitor tool functions correctly in other sketches I’ve used with this same value so I think we’re good here.
Looking at the serial monitor output, I do not see any printed data when I load the PECMAC125A.ino sketch.
To better illustrate what I’ve tried as well as some of the more specific questions I have about this sketch, I’ve added comments within the sketch (see below) for your reference:

// Distributed with a free-will license.
// Use it any way you want, profit or free, provided it fits in the licenses of its associated works.
// PECMAC125A
// This code is designed to work with the PECMAC125A_DLCT03C20 I2C Mini Module available from ControlEverything.com.
// https://www.controleverything.com/content/Current?sku=PECMAC125A_DLCT03C20#tabs-0-product_tabset-2

#include<Wire.h>

// PECMAC125A I2C address is 2A(42)
#define Addr 0x2A


unsigned int data[36];
// Unsure what to set the typeOfSensor value to so I've left it at 0
int typeOfSensor = 0;
// My max current is 20 amps. I've tried maxCurrent values of both 20 and 0 but no success
int maxCurrent = 0;
// The board is 8 channels. I've tried noOfChannel values of both 8 and 0 but no success
int noOfChannel = 0;
void setup() 
{
  // Initialise I2C communication as MASTER
  Wire.begin();
  // Initialise Serial Communication, set baud rate = 9600
  Serial.begin(9600);

  // Read configuration command
  // Header byte-1, Header byte-2, command-2, byte 3, 4, 5 and 6 are reserved, checksum
  byte readConfigCommand[8] = {0x92, 0x6A, 0x02, 0x00, 0x00, 0x00, 0x00, 0xFE};
  
  // Start I2C Transmission
  Wire.beginTransmission(Addr);
  // Send read configuration command   
  Wire.write(readConfigCommand, 8);
  // Stop I2C Transmission
  Wire.endTransmission();

  for(int i = 0; i < 3; i++)
    {
      // Start I2C Transmission
      Wire.beginTransmission(Addr);
      // Stop I2C Transmission
      Wire.endTransmission();

      // Request 1 byte of data
      Wire.requestFrom(Addr, 1);

      // Read 3 bytes of data
      // typeOfSensor, maxCurrent, noOfChannel
      if(Wire.available() == 1)
      {
        data[i] = Wire.read();
      }
    }

    typeOfSensor = data[0];
    maxCurrent = data[1];
    noOfChannel = data[2];

  // Output data to serial monitor
  Serial.print(" Type Of Sensor : ");
  Serial.println(typeOfSensor);
  Serial.print(" Max Current : ");
  Serial.println(maxCurrent);
  Serial.print(" No Of Channel : ");
  Serial.println(noOfChannel);
  delay(300);
}

void loop()
{
  // Read current command
  // Header byte-1, Header byte-2, command-1, start channel-1, stop channel-12,
// There are only 8 channels on this current monitor board. Do I need to change one of the HEX values below since the stop channel should be 8 rather than 12?
  // byte 5 and 6 reserved, checksum
  byte readCurrentCommand[8] = {0x92, 0x6A, 0x01, 0x01, noOfChannel, 0x00, 0x00, 0x0A};

  // Start I2C Transmission
  Wire.beginTransmission(Addr);
  // Send configuration command   
  Wire.write(readCurrentCommand, 8);
  // Stop I2C Transmission
  Wire.endTransmission();
  
  for(int i = 0; i < noOfChannel * 3; i++)
    {
      // Start I2C Transmission
      Wire.beginTransmission(Addr);
      // Stop I2C Transmission
      Wire.endTransmission();

      // Request 1 byte of data
      Wire.requestFrom(Addr, 1);

      // Read 3 bytes of data
      // typeOfSensor, maxCurrent, noOfChannel
      if(Wire.available() == 1)
      {
        data[i] = Wire.read();
      }
    }
  
  for(int i = 0; i < noOfChannel; i++)
  {
    // Read current data
    // msb1, msb, lsb
    int msb1 = data[i * 3] & 0xff;
    int msb = data[1 + i * 3] & 0xff ;
    int lsb = data[2 + i * 3] & 0xff;
    Serial.print(msb1);
    Serial.print(msb);
    Serial.print(lsb);
    float current = (msb1 * 65536) + (msb * 256) + lsb;
    
    // Convert the data to ampere
    current = current / 1000;

    // Output to the serial monitor
    Serial.print("Channel : ");
    Serial.println(i + 1);
    Serial.print("Current : ");
    Serial.println(current);
  }
  delay(500);
}

There must be something simple I’m missing. I’m sure once we identify it, all the i2c theory will make sense to me.
Thanks again for all your help!
Best,
Aaron

add some debug print message and where its getting stuck.

That is an excellent idea!
I’ve added print commands at nearly all the steps in the loop portion of the sketch.
Here is the modified sketch with the print results below:

// Distributed with a free-will license.
// Use it any way you want, profit or free, provided it fits in the licenses of its associated works.
// PECMAC125A
// This code is designed to work with the PECMAC125A_DLCT03C20 I2C Mini Module available from ControlEverything.com.
// https://www.controleverything.com/content/Current?sku=PECMAC125A_DLCT03C20#tabs-0-product_tabset-2

#include<Wire.h>

// PECMAC125A I2C address is 2A(42)
#define Addr 0x2A


unsigned int data[36];
// Unsure what to set the typeOfSensor value to so I've left it at 0
int typeOfSensor = 0;
// My max current is 20 amps. I've tried maxCurrent values of both 20 and 0 but no success
int maxCurrent = 0;
// The board is 8 channels. I've tried noOfChannel values of both 8 and 0 but no success
int noOfChannel = 0;
void setup() 
{
  // Initialise I2C communication as MASTER
  Wire.begin();
  // Initialise Serial Communication, set baud rate = 9600
  Serial.begin(9600);

  // Read configuration command
  // Header byte-1, Header byte-2, command-2, byte 3, 4, 5 and 6 are reserved, checksum
  byte readConfigCommand[8] = {0x92, 0x6A, 0x02, 0x00, 0x00, 0x00, 0x00, 0xFE};
  
  // Start I2C Transmission
  Wire.beginTransmission(Addr);
  // Send read configuration command   
  Wire.write(readConfigCommand, 8);
  // Stop I2C Transmission
  Wire.endTransmission();

  for(int i = 0; i < 3; i++)
    {
      // Start I2C Transmission
      Wire.beginTransmission(Addr);
      // Stop I2C Transmission
      Wire.endTransmission();

      // Request 1 byte of data
      Wire.requestFrom(Addr, 1);

      // Read 3 bytes of data
      // typeOfSensor, maxCurrent, noOfChannel
      if(Wire.available() == 1)
      {
        data[i] = Wire.read();
      }
    }

    typeOfSensor = data[0];
    maxCurrent = data[1];
    noOfChannel = data[2];

  // Output data to serial monitor
  Serial.print(" Type Of Sensor : ");
  Serial.println(typeOfSensor);
  Serial.print(" Max Current : ");
  Serial.println(maxCurrent);
  Serial.print(" No Of Channel : ");
  Serial.println(noOfChannel);
  delay(300);
}

void loop()
{
    Serial.print("Message 1/15: Let's get this party started!");
    Serial.println();
  // Read current command
  // Header byte-1, Header byte-2, command-1, start channel-1, stop channel-12,
// There are only 8 channels on this current monitor board. Do I need to change one of the HEX values below since the stop channel should be 8 rather than 12?
  // byte 5 and 6 reserved, checksum
    Serial.print("Message 2/15: Reading the current command");
    Serial.println();
  byte readCurrentCommand[8] = {0x92, 0x6A, 0x01, 0x01, noOfChannel, 0x00, 0x00, 0x0A};

    Serial.print("Message 3/15: Starting I2C Transmission");
    Serial.println();
  // Start I2C Transmission
  Wire.beginTransmission(Addr);
    Serial.print("Message 4/15: Sending configuration command");
    Serial.println();
  // Send configuration command   
  Wire.write(readCurrentCommand, 8);
    Serial.print("Message 5/15: Stopping I2C Transmission");
    Serial.println();
  // Stop I2C Transmission
  Wire.endTransmission();
    Serial.print("Message 6/15: Doing some math here before we transmit again");
    Serial.println();
  for(int i = 0; i < noOfChannel * 3; i++)
    {
    Serial.print("Message 7/15: Starting I2C Transmission");
    Serial.println();
      // Start I2C Transmission
      Wire.beginTransmission(Addr);
    Serial.print("Message 8/15: Stoping I2C Transmission");
    Serial.println();
      // Stop I2C Transmission
      Wire.endTransmission();
    Serial.print("Message 9/15: Requesting 1 byte of data");
    Serial.println();
      // Request 1 byte of data
      Wire.requestFrom(Addr, 1);

    Serial.print("Message 10/15: Read 3 bytes of data: typeOfSensor, maxCurrent, noOfChannel");
    Serial.println();
      // Read 3 bytes of data
      // typeOfSensor, maxCurrent, noOfChannel
      if(Wire.available() == 1)
      {
        data[i] = Wire.read();
      }
    }

    Serial.print("Message 11/15: Doing some more math here to average out our data");
    Serial.println();
  for(int i = 0; i < noOfChannel; i++)
  {
    // Read current data
    // msb1, msb, lsb
    int msb1 = data[i * 3] & 0xff;
    int msb = data[1 + i * 3] & 0xff ;
    int lsb = data[2 + i * 3] & 0xff;
    Serial.print("Message 12/15: Printing our msbl, msb, and lsb data");
    Serial.println();
    Serial.print(msb1);
    Serial.print(msb);
    Serial.print(lsb);
    float current = (msb1 * 65536) + (msb * 256) + lsb;

    Serial.print("Message 13/15: Dividing the current value by 1,000");
    Serial.println();
    // Convert the data to ampere
    current = current / 1000;

    Serial.print("Message 14/15: Printing the Channel and Current values");
    Serial.println();
    // Output to the serial monitor
    Serial.print("Channel : ");
    Serial.println(i + 1);
    Serial.print("Current : ");
    Serial.println(current);
  }
    Serial.print("Message 15/15: Waiting 1/2 second before we start this thing all over again");
    Serial.println();
    Serial.println();
    Serial.println();
  delay(500);
}

There are 2 gaps in the process, each will multiple missing steps, as shown here:
Message 1/15: Let’s get this party started!
Message 2/15: Reading the current command
Message 3/15: Starting I2C Transmission
Message 4/15: Sending configuration command
Message 5/15: Stopping I2C Transmission
Message 6/15: Doing some math here before we transmit again
-
-
-
-
Message 11/15: Doing some more math here to average out our data
-
-
-
Message 15/15: Waiting 1/2 second before we start this thing all over again

I’ll look into this a bit deeper tomorrow but wanted to post my findings in the meantime.
Thanks,
Aaron