Hello, I am trying to have a communication I2C with an arduino UNO using the library SoftI2CMaster.h, the problem is that I can't see the correct address never.
With the oscilloscope I can see the communication and that's what I see sending the command 2 and 3:
Command 3: 00000001(R/W=R)-1(ACK) - 10100101(data=A5)-1(ACK) otra palabra 00000000(R/W=W)-0(ACK) - 11111111(data=FF)-0(ACK)
Command 2: 00000001(R/W=R)-1(ACK) - 11111110(data=FE)-1(ACK) otra palabra 00000000(R/W=W)-0(ACK) - 11111111(data=FF)-0(ACK)
So the address ID is always 0x00 even if I have defined it as 0x50.
Here you can see part of the code:
#define SCL_PIN 5
#define I2C_TIMEOUT 100
#define I2C_NOINTERRUPT 0
#define I2C_SLOWMODE 1
#define FAC 1
#define I2C_CPUFREQ (F_CPU/FAC)
/* Corresponds to A4/A5 - the hardware I2C pins on Arduinos
#define SDA_PORT PORTC
#define SDA_PIN 4
#define SCL_PORT PORTC
#define SCL_PIN 5
#define I2C_FASTMODE 1
*/
#include <SoftI2CMaster.h>
#include <avr/io.h>
//------------------------------------------------------------------------------
void CPUSlowDown(int fac) {
// slow down processor by a fac
CLKPR = _BV(CLKPCE);
CLKPR = _BV(CLKPS1) | _BV(CLKPS0);
}
int nByte = 0;
byte lectura[4];
unsigned long valor = 0;
int MD_AD = 10;
int NPROM = 1536*2;
float out1_V=0;
float FS = 10;
float range = pow(2,15);
bool divido = 0;
unsigned long t_start, t_stop;
long n_bytes_joined, n_read, n_bytes_joined_read = 0, package = 256;
float bitrate;
uint8_t I2CADDR = 0x50, n_bytes[3], data;
int state = 0;
void setup() {
#if FAC != 1
CPUSlowDown(FAC);
#endif
// initialize serial:
Serial.begin(9600);
//Serial.begin(115200);
// make the pins outputs:
i2c_init();
}
void loop() {
// if there's any serial available, read it:
while (Serial.available() > 0) {
// look for the next valid integer in the incoming serial stream:
int command = Serial.parseInt();
Serial.flush();
if(command == 1){ // TC: Start Z axis acquistion
n_bytes_joined_read = 0;
i2c_start(I2CADDR | I2C_WRITE);
i2c_write(0x01);
i2c_stop();
//Serial.println("Sensor 1 sent");
//delay(50);
i2c_start(I2CADDR | I2C_READ);
//state = i2c_read(false);
state = i2c_read(true);
i2c_stop();
//Serial.println(n_bytes_joined);
Serial.println(state);
//delay(10);
Serial.flush();
}
else if(command == 2){ // TC: Start X axis acquisition
n_bytes_joined_read = 0;
i2c_start(I2CADDR | I2C_WRITE);
i2c_write(0xFE);
i2c_stop();
//delay(50);
//Serial.println("Sensor 2 sent");
i2c_start(I2CADDR | I2C_READ);
//state = i2c_read(false);
state = i2c_read(true);
i2c_stop();
//Serial.println(n_bytes_joined);
Serial.println(state);
//delay(250);
Serial.flush();
}
else if(command == 3){ // TC: Start Y axis acquisition
n_bytes_joined_read = 0;
i2c_start(I2CADDR | I2C_WRITE);
i2c_write(0xA5);
i2c_stop();
//delay(50);
//Serial.println("Sensor 3 sent");
i2c_start(I2CADDR | I2C_READ);
state = i2c_read(true);
i2c_stop();
//Serial.println(n_bytes_joined);
Serial.println(state);
//delay(250);
Serial.flush();
}
Just as curiosity --
You are communicating between which two devices?
Why are you using SoftI2CMaster.h rather than Wire.h?
GolamMostafa:
Just as curiosity --
You are communicating between which two devices?
Why are you using SoftI2CMaster.h rather than Wire.h?
I am using SoftI2CMaster.h because I have the communication done from another guy, he said it is working all perfectly but it is not.
The communication is between the arduino, wich is a Master, and a PCB that use a microcontroller PIC to monitor some sensors, the PIC was programmed as Slave with 0x50 ID address.
But even if I disconnect the cables from the pic, arduino send me the wrong ID address.
Please, make a simple test of I2C communication between Arduino UNO and PIC using the following sketch.
#include<Wire.h>
void setup()
{
Serial.begin(9600);
Wire.begin();
//---checking if PIC is present---------------
Wire.beginTransmission(0x50);
byte busStatus = Wire.endTransmission();
if(busStatus != 0)
{
Serial.print("PIC is not found...!:);
while(1); //wait for ever
}
Serial.print("PIC is found.");
}
void loop()
{
}
GolamMostafa:
Please, make a simple test of I2C communication between Arduino UNO and PIC using the following sketch.
#include<Wire.h>
void setup()
{
Serial.begin(9600);
Wire.begin();
//---checking if PIC is present---------------
Wire.beginTransmission(0x50);
byte busStatus = Wire.endTransmission();
if(busStatus != 0)
{
Serial.print("PIC is not found...!:);
while(1); //wait for ever
}
Serial.print("PIC is found.");
}
void loop()
{
}
I did, and the PIC is not found. The ACK is always at 1, so it is a NACK. But I have continuity between the SDa and SCL and the micro pins that correspond, and I have power in the micro as well.
I am using a PIC16f877 and the code on the pic si defined like this:
#include <16F877.h>
//#include <coms.h>
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3,FAST=100000, address=0x50, FORCE_HW)
#USE SPI (MASTER, CLK=PIN_A2, DI=PIN_A0, DO=PIN_A1, BAUD=100000, MODE=0, BITS=8, STREAM=SPI_0, MSB_FIRST)
Now, you know the problem that the PIC is not being seen by the UNO on its I2C Bus. So, what is your plan now?
GolamMostafa:
Now, you know the problem that the PIC is not being seen by the UNO on its I2C Bus. So, what is your plan now?
I made a I2C scanner and I sow the PIC 's ID is 0x28, even if I have programmed it as 0x50. So now if I use the program to found the PIC with the 0x28 address, yes I have positive response "PIC is found".
So now I'm thinking on what can be, the conversion decimal to hex is not possible because 0x28 hex = 40 dec.
andrea080690:
I made a I2C scanner and I sow the PIC 's ID is 0x28, even if I have programmed it as 0x50. So now if I use the program to found the PIC with the 0x28 address, yes I have positive response "PIC is found".
So now I'm thinking on what can be, the conversion decimal to hex is not possible because 0x28 hex = 40 dec.
0x28 and 0x50 -- both figures are correct. How?
1. What is 0x28?
It is the the 7-bit I2C address of PIC as slave (010 1000). When you have run the scanner program, the PIC is detected at this address. This is the 7-bit addrss (010 1000 ==> 0100 1000 ==> 0x28) that we enter while executing the following codes at UNO side:
Wire.beginTransmission(0b0101000);
Wire.requestFrom(0b0101000, n);
or
Wire.beginTransmission(0x28);
Wire.requestFrom(0x28, n);
or
#define slaveAddress 0b0101000; //0x28
Wire.beginTransmission(slaveAddress);
Wire.requestFrom(slaveAddress, n);
2. What is 0x50 (0101 0000 ===> 0101 000 0 ==> 0101000 0 (0x28 0)?
(1) When we execute Wire.write() command, the Compiler knows that data will move from Master to Slave (data write mode); the compiler adds 0 (LOW bit) at the end of I2C address; as a result, the MCU asserts 0101000 0 (0x50) on the I2C Bus.
(2) When we execute Wire.requestFrom(arg1, arg2) command, the Compiler knows that data will move from Slave to Master (data read mode); the compiler adds 1 (HIGH bit) at the end of I2C address; as a result, the MCU asserts 0101000 1 (0x51) on the I2C Bus.
perfect, so the first code is correct because is:
i2c_start(I2CADDR | I2C_WRITE);
so is 0x50|0= 0x28.
the thing is now I wrote a simple code with the wire.h library :
#include <Wire.h>
void setup()
{
Wire.begin(); // join i2c bus (address optional for master)
Serial.begin(9600); // start Serial for output
}
int IDaddress = 0x28;
int x = 0xF1;
// reset micro 0xF2
//sens1 0x01
//sens2 0xFE
//sens2 0xA5
//Status byte 7 - 0xF1
void loop()
{
while (Serial.available() > 0) {
int command = Serial.parseInt();
Serial.flush();
if(command == 1){ // TC: Start Z axis acquistion
Wire.beginTransmission(IDaddress); // transmit to device #4
Wire.write(0x01); // sends one byte
Wire.endTransmission(); // stop transmitting
}
else if (command == 2){ // TC: Start X axis acquisition
Wire.beginTransmission(IDaddress); // transmit to device #4
Wire.write(0xFE); // sends one byte
Wire.endTransmission(); // stop transmitting
}
else if (command == 3){ /// TC: Start Y axis acquisition
Wire.beginTransmission(IDaddress); // transmit to device #4
Wire.write(0xA5); // sends one byte
Wire.endTransmission(); // stop transmitting
}
And now every command I send it has positive ACK but the SDA and SCL pass from 5V to 3V, and a MOSFET changes his state (which is correct) but has 3V as well even if it should have 5V.
So what's wrong in the original code with softI2CMaster.h library, if there is something wrong?
With softI2CMaster.h library I have not positive ACK.