I am trying to modify the output voltage of a buck converter that is as a slave device via Arduino MEGA2560 as a Master device and using PMBus protocol.
I have written a code to write and read the output voltage, but I received garbage value (C0).
I would be grateful if someone can help me to solve the problem.
Here is the entire code.
#include <Wire.h>
void setup() {
Wire.begin(); // join i2c bus (address optional for master)
Serial.begin(9600); // start serial communication at 9600bps
}
byte msb = 0;
byte lsb = 0;
byte V_out = 0;
void loop() {
// step 1: Unlock PMBUS write protection
Wire.beginTransmission(0x38); // transmit to device(0x38)
Wire.write(0x10); // sets register pointer to the command register (0x10)
Wire.write((byte)0x00); // sends Data:0x00
Wire.write(0x17); // PEC
Wire.endTransmission(); // stop transmitting
delay(70);
// step 2: VOUT setpoint
Wire.beginTransmission(0x38); // transmit to device(0x38)
Wire.write(0x21); // sets register pointer to the command register(0x21)
Wire.write((byte)0x00); //sends Byte#0:0x66 to the command register (0x21)
Wire.write((byte)0xC6); //sends Byte#1:0xC6 to the command register (0x21)
Wire.write(0x17); // PEC
Wire.endTransmission(); // stop transmitting
delay(70); // datasheet suggests at least 65 milliseconds
// step 3: Set VOUT_OV_WARN
Wire.beginTransmission(0x38); // transmit to device(0x38)
Wire.write(0x42); // sets register pointer to to the command register(0x42)
Wire.write((byte)0x33); //sends Byte#0:0x33 to the command register (0x42)
Wire.write((byte)0xD3); //sends Byte#1:0xD3 to the command register (0x42)
Wire.write(0x17); // PEC
Wire.endTransmission(); // stop transmitting
delay(70);
// step 4: Command 0xEC should be send to unlock the MCU which save the data.
Wire.beginTransmission(0x38); // transmit to device(0x38)
Wire.write(0xEC); //sets register pointer to to the command register(0xEC)
Wire.write(0x04); //sends Byt count:N:4(0x04) to the command register (0xEC)
Wire.write((byte)0x7E); //sends Byte#0:0x7E to the command register (0xEC)
Wire.write((byte)0x15); //sends Byte#1:0x15 to the command register (0xEC)
Wire.write((byte)0xDC); //sends Byte#2:0xDC to the command register (0xEC)
Wire.write((byte)0x42); //sends Byte#3:0x42 to the command register (0xEC)
Wire.write(0x45); // PEC
Wire.endTransmission(); // stop transmitting
delay(70);
//step 5: Command 0x11 should be send to save the Vout setpoint in the MCU
Wire.beginTransmission(0x38); // transmit to device(0x38)
Wire.write(0x11); //sets register pointer to to the command register(0x11)
Wire.endTransmission(); // stop transmitting
delay(70);
// step 6: request reading Vout setpoint from the Buck Converter
Wire.beginTransmission(0x38); // transmit to device(0x38)
Wire.write(0x21); //sets register pointer to to the command register(0x21)
Wire.endTransmission(false); // stop transmitting
Wire.requestFrom((uint8_t) 0x38, (uint8_t) 2, (uint8_t) true); // Wire.requestFrom(38, 2); // request 2 bytes from peripheral device #0x38
// step 7: receive reading from the Buck Converter
if (2 <= Wire.available()) { // if two bytes were received
msb = Wire.read(); // receive high byte (overwrites previous reading)
msb = msb << 8; // shift high byte to be high 8 bits
lsb= Wire.read(); // receive low byte as lower 8 bits
V_out = msb | lsb;
Serial.print(" V_out = ");
Serial.print(V_out, HEX); // print the reading
Serial.println(" V");
}
delay(250); // wait a bit since people have to read the output :)
}
This will always result in the MSB being ignored. A byte can only hold 8 bits. If you move these 8 bits by 8 bits you have no value left in the variable.
Not yet. My major is not digital electronic, so it is difficult for me to understand the concept of these kinds of codes. I need to change the code, but should study more, and it is time-consuming for me.
You should also test return codes (where available) from the Wire library functions you are using to help with troubleshooting, especially Wire.endTransmission(). See Wire - Arduino Reference
As well as msb, which you have already been told about, V_out must also be defined as uint16_t.
If you are getting "garbage values" that is already quite good since it shows that I2C is delivering "something" so, for example, the I2C address must be correct.
#include <Wire.h>
void setup() {
Wire.begin(); // join i2c bus (address optional for master)
Serial.begin(9600); // start serial communication at 9600bps
}
uint16_t msb = 0;
uint8_t lsb = 0;
byte V_out = 0;
void loop() {
// step 1: Unlock PMBUS write protection
Wire.beginTransmission(0x38); // transmit to device(0x38)
Wire.write(0x10); // sets register pointer to the command register (0x10)
Wire.write((byte)0x00); // sends Data:0x00
// Wire.write(0x17); // PEC
Wire.endTransmission(); // stop transmitting
delay(50);
// step 2: VOUT setpoint
Wire.beginTransmission(0x38); // transmit to device(0x38)
Wire.write(0x21); // sets register pointer to the command register(0x21)
Wire.write((byte)0x00); //sends Byte#0:0x66 to the command register (0x21)
Wire.write((byte)0xC6); //sends Byte#1:0xC6 to the command register (0x21)
// Wire.write(0x17); // PEC
Wire.endTransmission(); // stop transmitting
delay(50); // datasheet suggests at least 65 milliseconds
// step 3: Set VOUT_OV_WARN
Wire.beginTransmission(0x38); // transmit to device(0x38)
Wire.write(0x42); // sets register pointer to to the command register(0x42)
Wire.write((byte)0x33); //sends Byte#0:0x33 to the command register (0x42)
Wire.write((byte)0xD3); //sends Byte#1:0xD3 to the command register (0x42)
// Wire.write(0x17); // PEC
Wire.endTransmission(); // stop transmitting
delay(50);
// step 4: Command 0xEC should be send to unlock the MCU which save the data.
Wire.beginTransmission(0x38); // transmit to device(0x38)
Wire.write(0xEC); //sets register pointer to to the command register(0xEC)
Wire.write(0x04); //sends Byt count:N:4(0x04) to the command register (0xEC)
Wire.write((byte)0x7E); //sends Byte#0:0x7E to the command register (0xEC)
Wire.write((byte)0x15); //sends Byte#1:0x15 to the command register (0xEC)
Wire.write((byte)0xDC); //sends Byte#2:0xDC to the command register (0xEC)
Wire.write((byte)0x42); //sends Byte#3:0x42 to the command register (0xEC)
// Wire.write(0x45); // PEC
Wire.endTransmission(); // stop transmitting
delay(50);
//step 5: Command 0x11 should be send to save the Vout setpoint in the MCU
Wire.beginTransmission(0x38); // transmit to device(0x38)
Wire.write(0x11); //sets register pointer to to the command register(0x11)
Wire.endTransmission(); // stop transmitting
delay(50);
// step 6: request reading Vout setpoint from the Buck Converter
Wire.beginTransmission(0x38); // transmit to device(0x38)
Wire.write(0x21); //sets register pointer to to the command register(0x21)
Wire.endTransmission(false); // stop transmitting
// Wire.requestFrom((uint8_t) 0x38, (uint8_t) 2, (uint8_t) true); // Wire.requestFrom(38, 2); // request 2 bytes from peripheral device #0x38
// step 7: receive reading from the Buck Converter
if (Wire.requestFrom(0x38, 2) >= 2) { // if two bytes were received
uint16_t msb = Wire.read(); // receive high byte (overwrites previous reading)
msb = msb << 8; // shift high byte to be high 8 bits
uint8_t lsb = Wire.read(); // receive low byte as lower 8 bits
V_out = msb | lsb;
Serial.print(" msb = ");
Serial.println(msb, HEX); // print the reading
Serial.println(" lsb = ");
Serial.print(lsb, HEX); // print the reading
Serial.print(" V_out = ");
Serial.print(V_out, HEX); // print the reading
Serial.println(" V");
}
delay(250); // wait a bit since people have to read the output :)
}
Note: Data return from MCU is in Vout Mode format : (Byte #1<<8) + (Byte #0)
#include <Wire.h>
void setup() {
Wire.begin(); // join i2c bus (address optional for master)
Serial.begin(9600); // start serial communication at 9600bps
}
uint16_t msb = 0;
uint8_t lsb = 0;
uint16_t V_out = 0;
void loop() {
// step 1: Unlock PMBUS write protection
Wire.beginTransmission(0x38); // transmit to device(0x38)
Wire.write(0x10); // sets register pointer to the command register (0x10)
Wire.write((byte)0x00); // sends Data:0x00
// Wire.write(0x17); // PEC
Wire.endTransmission(); // stop transmitting
delay(50);
// step 2: VOUT setpoint
Wire.beginTransmission(0x38); // transmit to device(0x38)
Wire.write(0x21); // sets register pointer to the command register(0x21)
Wire.write((byte)0x66); //sends Byte#0:0x66 to the command register (0x21)
Wire.write((byte)0xC6); //sends Byte#1:0xC6 to the command register (0x21)
// Wire.write(0x17); // PEC
Wire.endTransmission(); // stop transmitting
delay(50); // datasheet suggests at least 65 milliseconds
// step 3: Set VOUT_OV_WARN
Wire.beginTransmission(0x38); // transmit to device(0x38)
Wire.write(0x42); // sets register pointer to to the command register(0x42)
Wire.write((byte)0x33); //sends Byte#0:0x33 to the command register (0x42)
Wire.write((byte)0xD3); //sends Byte#1:0xD3 to the command register (0x42)
// Wire.write(0x17); // PEC
Wire.endTransmission(); // stop transmitting
delay(50);
// step 4: Command 0xEC should be send to unlock the MCU which save the data.
Wire.beginTransmission(0x38); // transmit to device(0x38)
Wire.write(0xEC); //sets register pointer to to the command register(0xEC)
Wire.write(0x04); //sends Byt count:N:4(0x04) to the command register (0xEC)
Wire.write((byte)0x7E); //sends Byte#0:0x7E to the command register (0xEC)
Wire.write((byte)0x15); //sends Byte#1:0x15 to the command register (0xEC)
Wire.write((byte)0xDC); //sends Byte#2:0xDC to the command register (0xEC)
Wire.write((byte)0x42); //sends Byte#3:0x42 to the command register (0xEC)
// Wire.write(0x45); // PEC
Wire.endTransmission(); // stop transmitting
delay(50);
//step 5: Command 0x11 should be send to save the Vout setpoint in the MCU
Wire.beginTransmission(0x38); // transmit to device(0x38)
Wire.write(0x11); //sets register pointer to to the command register(0x11)
Wire.endTransmission(); // stop transmitting
delay(50);
// step 6: request reading Vout setpoint from the Buck Converter
Wire.beginTransmission(0x38); // transmit to device(0x38)
Wire.write(0x21); //sets register pointer to to the command register(0x21)
Wire.endTransmission(false); // stop transmitting
// Wire.requestFrom((uint8_t) 0x38, (uint8_t) 2, (uint8_t) true); // Wire.requestFrom(38, 2); // request 2 bytes from peripheral device #0x38
// step 7: receive reading from the Buck Converter
if (Wire.requestFrom(0x38, 2) >= 2) { // if two bytes were received
uint16_t msb = Wire.read(); // receive high byte (overwrites previous reading)
msb = msb << 8; // shift high byte to be high 8 bits
uint8_t lsb = Wire.read(); // receive low byte as lower 8 bits
uint16_t V_out = msb | lsb;
Serial.print(" msb = ");
Serial.println(msb, HEX); // print the reading
Serial.println(" lsb = ");
Serial.print(lsb, HEX); // print the reading
Serial.print(" V_out = ");
Serial.print(V_out, HEX); // print the reading
Serial.println(" V");
}
delay(250); // wait a bit since people have to read the output :)
}