Search code examples
c#raspberry-piioti2craspberry-pi4

Iot.Device.MotorHat and Raspberry Pi4


I have A problem using Iot.Device.MotorHat on Raspberry Pi 4 with Debian-bullseye 11. I am trying run a DcMotor from the raspberry through motor hat pca9685 . My code is:

public class DCMotorController : BaseClass
    {
        public void StartMotor()
        {
            using (var motorHat = new MotorHat(1000d, 0x40))
            {
                var dcMotorOne = motorHat.CreateDCMotor(1); // The error is thrown here

                dcMotorOne.Speed = 1;

                Wait(1500);

                dcMotorOne.Speed = 0;
            }
        }
}

But on the CreateDCMotor I get an error that I can't figure out

Unhandled exception. System.InvalidOperationException: Unexpected value of duty cycle (9766, 10280)
   at Iot.Device.Pwm.Pca9685.<OnOffToDutyCycle>g__OnOffToDutyCycleSampled|16_0(UInt16 onCycles, UInt16 offCycles)
   at Iot.Device.Pwm.Pca9685.OnOffToDutyCycle(UInt16 on, UInt16 off)
   at Iot.Device.Pwm.Pca9685.GetDutyCycle(Int32 channel)
   at Iot.Device.Pwm.Pca9685PwmChannel.get_ActualDutyCycle()
   at Iot.Device.Pwm.Pca9685PwmChannel..ctor(Pca9685 parent, Int32 channel)
   at Iot.Device.Pwm.Pca9685.CreatePwmChannel(Int32 channel)
   at Iot.Device.MotorHat.MotorHat.CreateDCMotor(Int32 motorNumber)
   at projectV2.DCMotorController.StartMotor() in /home/pi/test/DCMotorController.cs:line 13

Solution

  • It appears the library behaves incorrectly when the current MotorHat configuration is not within the values it would set itself at startup. And the MotorHat binding has no way of correcting this. The following workaround might help (until the behavior is fixed):

    
    public void StartMotor()
            {
                using (var pca = new Pca9685(new I2cDevice(1, 0xA0), -1, 0, false))
                {
                }
                using (var motorHat = new MotorHat(new I2cConnectionSettings(1, 0x5f), 1000d, MotorPinProvider.Waveshare))
                {
                    var dcMotorOne = motorHat.CreateDCMotor(1); // The error is thrown here
    
                    dcMotorOne.Speed = 1;
    
                    Wait(1500);
    
                    dcMotorOne.Speed = 0;
                }
            }
    

    The address appears to work, even though the constructor you use uses an offset of 0x60 on the I2C address, so the actual address when specifying 0x40 as argument is 0xA0, which is actually outside the valid ranges for I2C (only 7 bits allowed). I do not know what effect this has. Are there any other devices connected to the I2C bus? Otherwise, a wrong address would give a different error.

    I didn't test the above workaround, since I do not have the required hardware.

    Edit: Updated to reflect the exact constructor call required, after finding that the OP apparently has the "Waveshare" module. And there's quite a bit of confusion on the correct address to use.