[RESOLVED] First attempt at I2C
Wildatheart
Posts: 195
This is my first attempt at using I2C with the propeller. The program below hangs after joining the master bus, but I am guessing more than that will need to be corrected even though I get a successful build. Thanks in advance for your help.
/* Using PPDB: Test I2C OSEPP IR proximity sensor module http://osepp.com/products/sensors-arduino-compatible/osepp-ir-proximity-sensor-module/ SW1 and SW2 are shorted for address 0x20 Assume master controller has pull-ups, therefore SB1 and SB2 are left open. See PDF schematic at bottom of OSEPP web page. */ #include "simpletools.h" // Include simpletools header i2c *i2cBus; // I2C bus ID const int IRsensor_SCL = 28; // Propeller pin 28 const int IRsensor_SDA = 29; // Propeller pin 29 int sensorADDR = 0b0100000; // Device address 0x20 int memADDR = 0; // Presume only 1 device register ? int main() { i2cBus = i2c_newbus(IRsensor_SCL, IRsensor_SDA, 0); // Join the I2C bus master (Mode 0 indicates pull-up print ("Joined master bus \n"); // resistors present on the SDA & SCL lines) while(1) { while((i2c_busy(i2cBus,sensorADDR))) // Wait here if sensor is busy { int val = 0; // Prepare val for new reading i2c_in(i2cBus, sensorADDR, memADDR, 1, (char*)&val, 1); print("value = %d \n", val); // Print the sensor reading pause (500); } } }
Comments
I use the same I2C function in my projects and use 0b1010000 for the EEPROM (address 0xA0) and 0b1100000 for a compass (address 0xC0) and using the 7 bit binary for the device address it all works. The 7 bit address has bit 0, the R/W bit, removed.
EDIT: I just modified my EEPROM code and defined a variable "int eeadr = 0b1010000; and the program continues to access the EEPROM. So if you change the variable sensorADDR assignment to 0b0010000 it should work.
I am suspecting the need for pull-ups on the SCL and SDA lines?
The last parameter being 0 means that the I2C bus will have pullup resistors instead of the propeller I/O driving the bus high and low. The propeller does not provide the pullups in mode 0, you have to provide them. Actually, per the I2C Specification, pullups are required. I use 4.7K resistors and never have any problems. Just be sure to use 3.3 Volts as the pullup source, not 5 - keeps the prop happy.
edit (again!) Just noticed you are using the PPDB, and the schematics indicate that it is using one 10K resistor as a pullup on the SDA (P29) line. Add a 10K to SCL line.
Just looked up the device you are using and there seems to be some confusion re device address. The OSEPP site for the IR module clearly states the device address is 0x20, but the I2C interface chip on the module is a PCA9534, which, according to all data sheets shows a device address of 0b0100000.
For the i2c_in statement, I would define a char variable at the beginning of main and use that variable name for the data field. Change "(char*)&val" to whatever name you use for the data variable.
On the module the schematic shows two switches, A1 and A2, both need to be closed to keep the low nibble of the device address at 0.
Added 10K between 3.3V and SCL (pin 28) as recommended. Also renamed (char*)&val with a char variable as recommended. Still no go.
But I have noticed that if I set val = 5 the loop will cycle and print the value received as 5. So among other possible problems the i2c_in is not functioning as intended.
Im guessing that memADDR or the parameters in i2c_in are not set properly.
int val = (data >> 2) & 1; needs to be changed to int val = (data >> 1) & 1;
Example code works with or without i2c_busy and/or i2c_stop
Andy, after your review of the changes one of us should pass this on to OSEPP to promote this sensor's use with the Propeller. Thanks Hal and Andy for your interest and help.