I tried editing Wires.h, along with a few other tricks, before making my forum post. The change you suggested was one of the first thing I tried. I'm honored other hackers have the same thinking. However, it's still not reading the sensor. The Arduino Uno reads it just fine but the Zero seems to have i2c issues.
Or, if you prefer not to hack the Wire.h library, you can just add the following code after Wire.begin().
Wire.begin(); // Start Wire (I2C)
sercom3.disableWIRE(); // Disable the I2C bus
SERCOM3->I2CM.BAUD.bit.BAUD = SystemCoreClock / ( 2 * 400000) - 1 ; // // Set the I2C SCL frequency to 400kHz
sercom3.enableWIRE(); // Restart the I2C bus
The SAMD21 seems to be more particular than the AVRs when it comes to changing the SCL clock frequency. The AVRs only require the line: TWBR=12; to be added after Wire.begin(). The SAMD21 however requires the I2C bus to be disabled. It's therefore necessary to kick-start it again after the frequency has been changed.
It's a mystery why Arduino has never provided a 400kHz I2C option, as this is such a common requirement.
Thank you for the replies. I edited /samd/1.6.1/libraries/Wire/Wire.h with 400000.
My problem was the A4/A5 pins of my shield were not bridged with the SDL/SDA pins 9,10 of J101. It's a shame that the Zero isn't pin-compatible with the legacy Arduino Uno platform. Little incompatibilities like these are what typically consume my transition time between platforms, and make backwards compatibility between platforms difficult to manage (i.e. ability to switch between Zero and Uno during the project development timeline).
smoore:
I tried editing Wires.h, along with a few other tricks, before making my forum post. The change you suggested was one of the first thing I tried. I'm honored other hackers have the same thinking. However, it's still not reading the sensor. The Arduino Uno reads it just fine but the Zero seems to have i2c issues.
Sounds like problem is not I2C clock speed. You'll need to provide more info: I2C device, schematic or pin-to-pin summary, pullups, your software, photo ....
The UNO has internal I2C pullup resistors, it is my experience that the ZERO does not have internal I2C pullups.
void TwoWire::setClock(uint32_t frequency) {
sercom->disableWIRE(); // Disable the I2C bus
sercom->setClock(frequency); // Set the I2C SCL frequency
sercom->enableWIRE(); // Restart the I2C bus
}
and in the SERCOM class...
void SERCOM::setClock(uint32_t frequency) {
sercom->I2CM.BAUD.bit.BAUD = SystemCoreClock / ( 2 * frequency) - 1 ; // Set the I2C SCL frequency
}
...be added to the Zero's Wire library to replace the dummy function that's currently there?
I also noticed that TwoWire::setClock() function has been implemented for the AVR Arduinos.
You dug up a topic that's almost 5 years old. Nowadays it's possible to set the I2C to 400kHz by using the Wire.setClock() function. Just call it after Wire.begin():
Wire.begin(); // Start I2C comms on SCL and SDA
Wire.setClock(400000); // Set the SCL clock speed to 400kHz
The Wire.setClock() function only needs to be called one time. Looking at your sample code, the function should be moved from the loop() function and instead be placed in setup(), located just after Wire.begin():
#include <Wire.h> // specify use of Wire.h library
#define MCP4725 0x62 // MCP4725 base address
unsigned int val;
byte buffer[3];
void setup() {
Wire.begin(); // begin I2C
Wire.setClock(400000); // Set the SCL clock speed to 400kHz
} // end setup
void loop() {
buffer[0] = 0b01000000; // control byte
val = analogRead(0) * 4; // read pot
buffer[1] = val >> 4; // MSB 11-4 shift right 4 places
buffer[2] = val << 4; // LSB 3-0 shift left 4 places
Wire.beginTransmission(MCP4725); // address device
Wire.write(buffer[0]); // pointer
Wire.write(buffer[1]); // 8 MSB
Wire.write(buffer[2]); // 4 LSB
Wire.endTransmission();
// just an indicator
digitalWrite(13, HIGH);
delay(100);
digitalWrite(13, LOW);
delay(100);
} // end loop
The Wire.setClock() function only needs to be called one time. Looking at your sample code, the function should be moved from the loop() function and instead be placed in setup(), located just after Wire.begin():
#include <Wire.h> // specify use of Wire.h library
#define MCP4725 0x62 // MCP4725 base address
unsigned int val;
byte buffer[3];
void setup() {
Wire.begin(); // begin I2C
Wire.setClock(400000); // Set the SCL clock speed to 400kHz
} // end setup
void loop() {
buffer[0] = 0b01000000; // control byte
????
????
[/quote]
once for the code
you said to be called
Wouldn't it be constantly working in the program?
will we delete the program after calling the program
you wrote last
can i just use the program
continuous
or enablewıre then do we disablewıre?
is it necessary
once for the code
you said to be called
Wouldn't it be constantly working in the program?
The Arduino libraries such as Wire are setting the microcontroller's registers behind the scenes. The registers are analagous to a giant switchboard that are detailed in the SAMD21 datasheet. They determine the microcontroller's behaviour. For example the Wire.setClock() function changes the value of the I2C's BAUD register, this action causes the SCL clock rate to change from 100kHz to 400kHz. Also, the action only has to be performed one time in order to take effect.
or enablewıre then do we disablewıre?
is it necessary
When the Arduino Zero was realeased back in 2015, the Arduino core code hadn't reached full maturity and functions like Wire.setClock() hadn't been implemented. This meant that to get 400kHz on SCL you had to manually disable the I2C communications, set the BAUD register then reenable I2C comms oncemore. Nowadays the Wire.setClock() function does that for you.