ATMEGA328P I2C Issue

Hey,

I have a custom designed CCA that uses an ATMEGA328P micro controller, a MCP4725 DAC (I2C interface) and another sensor (SPI interface). In my initial design all of these devices ran off of 5VCC and the atmega utilized a 16MHz resonator to provide the clock. Everything worked great, I had my I2C clock at 400khz and my SPI clock at 5Mhz. In an effort to reduce the power consumption, I was playing with the clock scaler to get the ATMEGA to run at a lower speed and use less power with success… To reduce power even further I made the following changes:

  1. I replaced the 16MHz resonator with a 2MHz resonator

  2. I put a 5V to 3.3V regulator on my board to run the ATMEGA at 3.3V

  3. I used a PCA9306 voltage level translator to work between the ATMEGA and MCP4725 (I2C lines)

  4. I updated the boards.txt file to change f.cpu to 2Mhz (this was already done when i was using the clock scalers)

The design functions but for some reason my I2C clock is running at 1.9-3.8khz depending on how I play with my code.

  1. When I have the following enabled in my code i get the 1.9khz, when i disable it (i.e. “\”) i get 3.8khz

CLKPR = 0x80;
CLKPR = 0x01;

  1. I played around with the TWBR, which i had always run the following:

TWBR = ((2000000 /400000l) - 16) / 2; // Change the i2c clock to 400KHz

but it didn’t seem to make a difference.

When I have both #1 and #2 above enabled this is what I get:

The ATMEGA328P clock was probed at the external resonator

The SPI clock was probed at the ATMEGA328P pin

The I2C clock was probed at the ATMEGA328P pin (although I probed it on the MCP4725 side and got the same #'s)

ATMEGA328P Clock …2Mhz as expected


Google Photos

SPI Clock (was expecting 500khz but plenty fast for what i need)


Google Photos

I2C Clock… 1.9Khz… Much slower than what i expect which is 400khz

Google Photos

If i disable the clock scaler (#1 above), the ATMEGA328P clock stays the same.

SPI clock… 500khz as expected

Google Photos

I2C clock… 3.8khz, so it doubles but it is way low still.

Google Photos

No idea why my I2C clock is so slow now, any ideas?

Basic code below:

#include <Wire.h>
#include <Adafruit_MCP4725.h>
#include <SPI.h>
#define kNOERROR 0
#define kPRIMARYREADERROR 1
#define kEXTENDEDREADTIMEOUTERROR 2
#define kPRIMARYWRITEERROR 3
#define kEXTENDEDWRITETIMEOUTERROR 4
#define kCRCERROR 5
#define kUNABLETOCHANGEPROCESSORSTATE 6
#include <avr/sleep.h>
#include <avr/power.h>

//190907const uint16_t LEDPin = 13;
const uint32_t WRITE = 0x40;
const uint32_t READ = 0x00;

const uint32_t COMMAND_MASK = 0xC0;
const uint32_t ADDRESS_MASK = 0x3F;
unsigned long nextTime;
bool ledOn = false;
bool includeCRC = true;

Adafruit_MCP4725 dac;

void setup(void) {

  //disable ADC
ADCSRA = 0;

power_adc_disable(); // ADC converter
power_timer0_disable();// Timer 0
power_timer1_disable();// Timer 1
power_timer2_disable();// Timer 2

CLKPR = 0x80;
CLKPR = 0x01;

  uint16_t unused;
  uint32_t flags;
  uint32_t flagsAndZeroOffset;
  // Initialize SPI
  SPI.begin();
  pinMode(SS, OUTPUT);
  //Sets Unused Pins to Internal Pullup
  pinMode(2,INPUT_PULLUP);
  pinMode(3,INPUT_PULLUP);
  pinMode(4,INPUT_PULLUP);
  pinMode(5,INPUT_PULLUP);
  pinMode(6,INPUT_PULLUP);
  pinMode(7,INPUT_PULLUP);
  pinMode(8,INPUT_PULLUP);
  pinMode(9,INPUT_PULLUP);
  pinMode(15,INPUT_PULLUP);
  pinMode(16,INPUT_PULLUP);
  pinMode(17,INPUT_PULLUP);

 //190907 pinMode(LEDPin, OUTPUT);

  nextTime = millis();
  //190907digitalWrite(LEDPin, LOW);
  digitalWrite(SS, HIGH);
  // Make sure all of the SPI pins are
  // ready by doing a read
  PrimaryRead(SS, 0x0, unused);
  // Unlock the device
  ExtendedWrite(SS, 0xFFFE, 0x27811F77);
  // Make sure the device is unlocked
  ExtendedRead(SS, 0x22, flags);
  if (!((flags & 0x0022) == 0x0020))
  {
  Serial.println("Device is not Unlocked");
  }

  

  // For Adafruit MCP4725A1 the address is 0x62 (default) or 0x63 (ADDR pin tied to VCC)
 dac.begin(0x62);
TWBR = ((2000000 /400000l) - 16) / 2; // Change the i2c clock to 400KHz

  
}

void loop(void) {

  temp = PrimaryRead(SS, 0x20, angle);
  SPIvariable = (float)(angle & 0x0FFF) * (360.0 / 4096.0);

//    Serial.println(SPIvariable);
  

   dac.setVoltage(3*SPIvariable,false);

}
TWBR = ((2000000 /400000l) - 16) / 2; // Change the i2c clock to 400KHz

Did you calculate that result?

With 2MHz you cannot reach 400kHz I2C speed, the maximum is 125kHz. Then you have to set TWBR to 0 and TWPS in TWSR also to 0. And of course the clock scaler must be disabled.

How do i set the TWPS in TWSR to 0?

TWPS &= ~3;

Look at your first post. That's why we insist in uploading picture to this forum and not pointing to temporary storage space.

Coding is not my forte, it is saying TWPS isn’t declared in scope. Not sure why it is giving me the error nor how to fix it. I don’t declare TWBR prior to just stating "TWBR = 0;

Understood on the picture attachment, to be honest it isn’t very intuitive on how to do that on this message board compared to others. I see it in this box i’m typing in currently, but didn’t on the original (likely just overlooked).

As practice i attached the difference between the standard boards.txt file and the mods that I had to make just to be able to upload.

Well i’m sorta making progress… I went back to the boards.txt file and changed the frequency back to 16mhz and started playing around with the low byte fuse value using this website: http://www.martyncurrey.com/arduino-atmega-328p-fuse-settings/

Using 0xCA I got the I2C up to ~50khz but now my SPI bus is down to ~60khz… WTH… Guess i’ll keep looking at it.

This is with TWBR = 0 and the prescalers commented out

I wonder if there are larger gaps in the I2C communication due to the software overhead of the Wire library.

There is an ancient discussion about running fast and going quickly into sleep mode or running slow and using a lot of time before going into sleep mode. In most cases it is better to enter the sleep mode as quick as possible and do short bursts of activity.

Do you have to keep the DAC running ? So maybe you can not enter the sleep mode ?

Running at 16MHz with 5V or 8MHz with 3.3V are the two most used options. Did you measure how much better your circuit is ?

I assume that you have read this: https://www.gammon.com.au/power.
When you can not use the sleep mode, then there might be parts of the chip that can be turned off.
On that page I read that lowering the 16MHz by 8 times, reduces the power by 2 times. A long math calculation will therefor cost 4 times as much power at 2 MHz. In that situation the lower clock speed will not save power, it will cost more power then running at 16MHz.

There is a forum trick: attach the pictures, upload your post to the forum, copy the links of the attached pictures, modify the post and use inline pictures with the links of the attached pictures. Keep the pictures attached as they are.

Update, did some testing and think i got it where i need it. Not sure why the SPI and I2C clocks seem to scale differently but nonetheless i made it work.