i2c newb questions

Posted on
  • Hi, I ported PCA9865 functions over. I am trying to access it on the STM32F4Discovery. I am getting timeouts on both B6,B7 and B8,B9 pins. On B6,B7 I get
    INTERNAL ERROR: Timeout on I2C Write BUSY
    INTERNAL ERROR: Timeout on I2C Write SB
    INTERNAL ERROR: Timeout on I2C Write Transmit Mode 2
    INTERNAL ERROR: Timeout on I2C Write Transmit
    INTERNAL ERROR: Timeout on I2C Write Transmit
    at line 5 col 48
    this.i2c.writeTo(this.a, [PCA9685_MODE1, 0x0]);

    on B8,B9
    INTERNAL ERROR: Timeout on I2C Write Transmit Mode 2
    INTERNAL ERROR: Timeout on I2C Write Transmit
    INTERNAL ERROR: Timeout on I2C Write Transmit
    at line 5 col 48
    this.i2c.writeTo(this.a, [PCA9685_MODE1, 0x0]);

    Any advice on debugging?

  • Did you remember to do the I2C setup()?

    Is it wired up correctly? If you aren't using a breakout board, you need to have the 10k pullups (these are included in I2C breakout boards).

    Check talking to it manually, with I2C.writeTo() - check the datasheet for the I2C address to use, and see if it reacts. Some devices may take on an alternate address. Check that too - the module may be trying the other address.

    Is the device known working?

  • Thanks. I can confirm the driver works with a generic breakout, so obviously something went wrong on the other test hardware.

  • So it's all sorted now?

    Were you using 1v62? I'd added some code that should have given a slightly more helpful error message in the case of I2C errors :)

  • Yeah, it works. I tested against 1v60 and 1v62. I am still trying to clean it up and fix the 401 USB.

    //Sources:
    //https://github.com/technicalmachine/se­rvo-pca9685
    //https://github.com/adafruit/Adafruit-P­WM-Servo-Driver-Library
    //TODO:
    //Add additional modes and functions, ie.
    //such as from https://github.com/arc12/PCA9685/
    
    var C = {
    	PCA9685_SUBADR1 : 0x02,
        PCA9685_SUBADR2 : 0x03,
        PCA9685_SUBADR3 : 0x04,
    
        MAX : 4096,
        PCA9685_MODE1 : 0x00,
        PCA9685_MODE2 : 0x01,
        PCA9685_PRESCALE : 0xFE,
    
        /* MODE1 bits */
        PCA9685_RESTART : 0x80, //!< Restart logic. Default disabled. Not used.
        PCA9685_EXTCLK : 0x40, //!< External clock. Default disabled. Not used.
        PCA9685_AI : 0x20, //!< Register auto-increment. Enabled by initialise()
        PCA9685_SLEEP : 0x10, //!< Sleep (osc off). Device is sleeping on POR, brought out of sleep by initialise()
        PCA9685_SUB1 : 0x08,//!< Sub-address 1 enable. Default disabled. Not used.
        PCA9685_SUB2 : 0x04, //!< Sub-address 2 enable. Default disabled. Not used.
        PCA9685_SUB3 : 0x02, //!< Sub-address 3 enable. Default disabled. Not used.
        PCA9685_ALLCALL : 0x01, //!< Respond to all-call. Default enabled. Not used.
    
        /* MODE2 bits. These are not actually used at present */
        PCA9685_INVRT : 0x10,
        PCA9685_OCH : 0x08,
        PCA9685_OUTDRV : 0x04,
        PCA9685_OUTNE1 : 0x02,
        PCA9685_OUTNE0 : 0x01,
    
        // I2C Address for "all call" (7 bit form)
        PCA9685_ALLCALLADR : 0x70, //!< 0xE0 default "all call" I2C write address (7bit => 0x70)
    
        LED0_ON_L : 0x06,
        LED0_ON_H : 0x07,
        LED0_OFF_L : 0x08,
        LED0_OFF_H : 0x09,
    
        ALLLED_ON_L : 0xFA,
        ALLLED_ON_H : 0xFB,
        ALLLED_OFF_L : 0xFC,
        ALLLED_OFF_H : 0xFD
    };
    
    exports.connect = function(_i2c,freq) {
        return new PCA9685(_i2c,freq);
    };
    
    function PCA9685(i2c, freq, address) {
      this.i2c = i2c;
      freq = typeof freq != 'undefined' ? freq : 50;
      this.setPWMFreq(freq);
      this.a = typeof address ! == 'undefined' ? address : 0x40;
    
      this.resetPCA9685();
    }
    
    PCA9685.prototype.resetPCA9685 = function() {
      this.i2c.writeTo(this.a, [C.PCA9685_MODE1, 0x0]);
    };
    
    PCA9685.prototype.setPWMFreq = function(freq) {
      var prescaleval = (25000000/C.MAX)/freq - 1;
      var prescale = Math.floor(prescaleval);
      
      var oldmode = this.i2c.readFrom(this.a, C.PCA9685_MODE1) | 0x10;
      var newmode = (oldmode & 0x7F) | 0x10; // sleep
      this.i2c.writeTo(this.a, [C.PCA9685_MODE1, newmode]); // go to sleep
      this.i2c.writeTo(this.a, [C.PCA9685_PRESCALE, prescale]); // set the prescaler
      this.i2c.writeTo(this.a, [C.PCA9685_MODE1, oldmode]);
      setTimeout(this.i2c.writeTo(this.a, [C.PCA9685_MODE1, oldmode | 0x80]),1);
    };
    
    PCA9685.prototype.setPWM = function(num, on, off) {
    
      if (num < 1 || num > 16) {
        throw "Servos are 1-indexed. Servos can be between 1-16.";
      }
    
      this.i2c.writeTo(this.a, [C.LED0_ON_L + (num-1)*4, on]);
      this.i2c.writeTo(this.a, [C.LED0_ON_H + (num-1)*4, on >> 8]);
      this.i2c.writeTo(this.a, [C.LED0_OFF_L + (num-1)*4, off]);
      this.i2c.writeTo(this.a, [C.LED0_OFF_H + (num-1)*4, off >> 8]);
    };
    
    // 0...180
    PCA9685.prototype.moveServo = function (num, val) {
      if (num < 1 || num > 16) {
        throw "Servos are 1-indexed. Servos can be between 1-16.";
      }
    
      this.setPWM(num, ((val/180) * (this.high - this.low)) + this.low, Math.floor(C.MAX/100*on));
    };
    
    //I2C1.setup({scl:B8, sda:B9});
    //var driver = connect(I2C1, 50);
    //driver.setPWM(1,400,20);
    
  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

i2c newb questions

Posted by Avatar for FyberChris @FyberChris

Actions