[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?
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)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.
IR Proximity Sensor Module Setup Connect one end of the cable into either Molex connectors on the sensor Connect the other end of the cable to the Arduino board: RED: 5V WHITE: I2C SDA (pin A4 on Uno; pin 20 on Mega) BLACK: GND GREY: I2C SCL (pin A5 on Uno; pin 21 on Mega) Set the DIP switch on the sensor to set the sensor address (check back of sensor for possible addresses) Example Sketch // OSEPP IR Proximity Sensor Example Sketch // by OSEPP <http://www.osepp.com> // This sketch demonstrates interactions with the IR Proximity Sensor #include <Wire.h> // Possible sensor addresses (suffix correspond to DIP switch positions) #define SENSOR_ADDR_OFF_OFF (0x26) #define SENSOR_ADDR_OFF_ON (0x22) #define SENSOR_ADDR_ON_OFF (0x24) #define SENSOR_ADDR_ON_ON (0x20) // Set the sensor address here const uint8_t sensorAddr = SENSOR_ADDR_OFF_OFF; // One-time setup void setup() { // Start the serial port for output Serial.begin(9600); // Join the I2C bus as master Wire.begin(); // Turn on the sensor by configuring pin 1 of the GPIO expander to be an // output pin; the default output value is already HI so there's no need // to change it WriteByte(sensorAddr, 0x3, 0xFE); } // Main program loop void loop() { uint8_t val; // Get the value from the sensor if (ReadByte(sensorAddr, 0x0, &val) == 0) { // The second LSB indicates if something was not detected, i.e., // LO = object detected, HI = nothing detected if (val & 0x2) { Serial.println("Nothing detected"); } else { Serial.println("Object detected"); } } else { Serial.println("Failed to read from sensor"); } // Run again in 1 s (1000 ms) delay(1000); } // Read a byte on the i2c interface int ReadByte(uint8_t addr, uint8_t reg, uint8_t *data) { // Do an i2c write to set the register that we want to read from Wire.beginTransmission(addr); Wire.write(reg); Wire.endTransmission(); // Read a byte from the device Wire.requestFrom(addr, (uint8_t)1); if (Wire.available()) { *data = Wire.read(); } else { // Read nothing back return -1; } return 0; } // Write a byte on the i2c interface void WriteByte(uint8_t addr, uint8_t reg, byte data) { // Begin the write sequence Wire.beginTransmission(addr); // First byte is to set the register pointer Wire.write(reg); // Write the data byte Wire.write(data); // End the write sequence; bytes are actually transmitted now Wire.endTransmission(); } - See more at: http://osepp.com/learning-centre/start-here/ir-proximity-sensor-module/#sthash.s7X5gwaf.dpuf/* 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 i2c_SCL = 28; // Propeller pin 28 const int i2c_SDA = 29; // Propeller pin 29 const int irProx0 = 0x20; // Address 0x20 named irProx0 int main() { i2cBus = i2c_newbus(i2c_SCL, i2c_SDA, 0); // Declare I2C bus with pullups int reg = 0x3; // Declare/init reg & data char data = 0xFE; int b = i2c_out(i2cBus, irProx0, reg, 1, // Turn on sensor &data, 1); print("Bytes sent = %d\n", b); // Addr + reg + data = 3 while(1) // Main loop { while(i2c_busy(i2cBus, irProx0)); // Wait here if sensor is busy i2c_stop(i2cBus); // Might be needed reg = 0; // Set reg to 0 data = 0; // Prepare data for new reading b = i2c_in(i2cBus, irProx0, reg, 1, // Check irProx0 sensor &data, 1); print("Bytes total = %d\n"); // Addr + reg out + data in = 3 int val = (data >> 2) & 1; // Isolate detection bit if(b == 3) print("val = %d \n", val); // Print detection status pause (500); // 1/2 sec before repeat } }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.