libraries / Mitov / Mitov_Maxim_MotorDriverShield.hon commit Added link to project report (97a3ba0)
   1////////////////////////////////////////////////////////////////////////////////
   2//                                                                            //
   3//     This software is supplied under the terms of a license agreement or    //
   4//     nondisclosure agreement with Mitov Software and may not be copied      //
   5//     or disclosed except in accordance with the terms of that agreement.    //
   6//         Copyright(c) 2002-2016 Mitov Software. All Rights Reserved.        //
   7//                                                                            //
   8////////////////////////////////////////////////////////////////////////////////
   9
  10#ifndef _MITOV_MAXIM_MOTOR_DRIVER_SHIELD_h
  11#define _MITOV_MAXIM_MOTOR_DRIVER_SHIELD_h
  12
  13#include <Mitov.h>
  14
  15namespace Mitov
  16{
  17//---------------------------------------------------------------------------
  18        enum TArduinoMaximMotorCurrentRegulationMode { crmRipple25, crmFastDecay, crmSlowDecay };
  19//---------------------------------------------------------------------------
  20        class Maxim_MotorDriverBasicChannel;
  21//---------------------------------------------------------------------------
  22        class Maxim_MotorDriverBasicShield : public OpenWire::Component
  23        {
  24                typedef OpenWire::Component inherited;
  25
  26        public:
  27                Mitov::SimpleList<Maxim_MotorDriverBasicChannel *>      FChannels;
  28                byte FChanged = 0xFF;
  29                bool FModified = true;
  30
  31        protected:
  32                byte F_MAX7300;
  33                byte F_MAX5387_1;
  34                byte F_MAX5387_2;
  35
  36        protected:
  37                void DoPotentiometerTransmission( byte Address, byte ARegister, byte AData )
  38                {
  39                        byte AAddress = 0b0101000 | (( Address & 0b111 ) << 1 );
  40
  41//                      Serial.print( AAddress );
  42//                      Serial.print( " " );
  43//                      Serial.print( ARegister );
  44//                      Serial.print( " " );
  45//                      Serial.println( AData );
  46
  47                        Wire.beginTransmission( AAddress );
  48                        Wire.write( ARegister );
  49                        Wire.write( AData );
  50                        Wire.endTransmission();
  51                }
  52
  53                void DoGPIOTransmissionAt( byte ARegister, byte AData )
  54                {
  55                        byte AAddress = 0b01000000 | ( F_MAX7300 & 0b1111 );
  56
  57                        Wire.beginTransmission( AAddress );
  58                        Wire.write( ARegister );
  59                        Wire.write( AData );
  60                        Wire.endTransmission();
  61                }
  62
  63                byte DoGPIOReadAt( byte ARegister )
  64                {
  65                        byte AAddress = 0b01000000 | ( F_MAX7300 & 0b1111 );
  66
  67                        Wire.beginTransmission( AAddress );
  68                        Wire.write( ARegister );
  69                        Wire.endTransmission();
  70                        Wire.requestFrom( AAddress, (byte)1 );
  71                        return Wire.read();
  72                }
  73
  74        protected:
  75                void UpdateSettings();
  76
  77                virtual void SystemStart();
  78
  79                virtual void SystemLoopUpdateHardware() override
  80                {
  81                        if( FModified )
  82                                UpdateSettings();
  83
  84                        inherited::SystemLoopUpdateHardware();
  85                }
  86
  87                void UpdateFailures();
  88
  89        public:
  90                Maxim_MotorDriverBasicShield( byte A_MAX7300, byte A_MAX5387_1, byte A_MAX5387_2 ) :
  91                        F_MAX7300( A_MAX7300 ),
  92                        F_MAX5387_1( A_MAX5387_1 ),
  93                        F_MAX5387_2( A_MAX5387_2 )
  94                {
  95                }
  96
  97        };
  98//---------------------------------------------------------------------------
  99        class Maxim_MotorDriverShieldComponent : public Maxim_MotorDriverBasicShield
 100        {
 101                typedef Maxim_MotorDriverBasicShield inherited;
 102
 103        public:
 104                OpenWire::SinkPin       FaultInputPin;
 105
 106        protected:
 107                bool    FFaultReceived = false;
 108
 109        protected:
 110                void DoFaultReceive( void * _Data )
 111                {
 112                        if( *(bool *)_Data )
 113                                UpdateFailures();
 114                }
 115
 116        public:
 117                Maxim_MotorDriverShieldComponent( byte A_MAX7300, byte A_MAX5387_1, byte A_MAX5387_2 ) :
 118                        inherited( A_MAX7300, A_MAX5387_1, A_MAX5387_2 )
 119                {
 120                        FaultInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&Maxim_MotorDriverShieldComponent::DoFaultReceive );
 121                }
 122        };
 123//---------------------------------------------------------------------------
 124        class Maxim_MotorDriverShield : public Maxim_MotorDriverBasicShield
 125        {
 126                typedef Maxim_MotorDriverBasicShield inherited;
 127
 128        protected:
 129                int FFailureChangePin;
 130
 131        protected:
 132                virtual void SystemLoopBegin( unsigned long currentMicros )
 133                {
 134                        inherited::SystemLoopBegin( currentMicros );
 135                        if( digitalRead( FFailureChangePin ) == HIGH )
 136                                UpdateFailures();
 137                }
 138
 139        public:
 140                Maxim_MotorDriverShield( byte A_MAX7300, byte A_MAX5387_1, byte A_MAX5387_2, int AFailureChangePin ) :
 141                        inherited( A_MAX7300, A_MAX5387_1, A_MAX5387_2 ),
 142                        FFailureChangePin( AFailureChangePin )
 143                {
 144                }
 145        };
 146//---------------------------------------------------------------------------
 147        class Maxim_MotorDriverBasicChannel : public OpenWire::Object
 148        {
 149        public:
 150                OpenWire::SinkPin       SpeedInputPin;
 151                OpenWire::SourcePin     FaultOutputPin;
 152
 153        public:
 154                bool Enabled = true;
 155                float MaxCurrent = 0.0f;
 156                TArduinoMaximMotorCurrentRegulationMode CurrentRegulationMode = crmRipple25;
 157                bool FFailure = false;
 158
 159        public:
 160        void SetEnabled( bool AValue )
 161                {
 162            if( Enabled == AValue )
 163                return;
 164
 165            Enabled = AValue;
 166                        FOwner.FChanged |= 0b00010000 << FIndex; 
 167                        FOwner.FModified = true;
 168                }
 169
 170        void SetMaxCurrent( float AValue )
 171        {
 172                        AValue = constrain( AValue, 0, 2.6 );
 173            if( MaxCurrent == AValue )
 174                return;
 175
 176            MaxCurrent = AValue;
 177                        FOwner.FChanged |= 0b1 << FIndex; 
 178                        FOwner.FModified = true;
 179        }
 180
 181        void SetCurrentRegulationMode( TArduinoMaximMotorCurrentRegulationMode AValue )
 182        {
 183            if( CurrentRegulationMode == AValue )
 184                return;
 185
 186            CurrentRegulationMode = AValue;
 187                        FOwner.FChanged |= 0b00010000 << FIndex; 
 188                        FOwner.FModified = true;
 189        }
 190
 191        protected:
 192                Maxim_MotorDriverBasicShield &FOwner;
 193                int FIndex;
 194
 195                float FSpeed;
 196                float FSenseResistor;
 197
 198        protected:
 199                void DoSpeedReceive( void * _Data )
 200                {
 201                        float AValue = constrain( *(float *)_Data, 0, 1.0 );
 202//                      Serial.println( AValue );
 203                        if( FSpeed == AValue )
 204                                return;
 205
 206                        if(( AValue > 0.5 && FSpeed <= 0.5 ) || ( AValue <= 0.5 && FSpeed > 0.5 ))
 207                                FOwner.FChanged |= 0b00010000 << FIndex; 
 208
 209                        FSpeed = AValue;
 210
 211                        FOwner.FModified = true;
 212
 213//                      FOwner.SetChannelValue( FIndex, AValue );
 214                }
 215
 216        public:
 217                byte    GetRegisterPins()
 218                {
 219                        byte    Result;
 220                        if( Enabled )
 221                                Result = 0;
 222
 223                        else
 224                                Result = 1;
 225
 226                        if( FSpeed > 0.5 )
 227                                Result |= 0b10;
 228
 229                        switch( CurrentRegulationMode )
 230                        {
 231                                case crmRipple25:
 232                                        Result |= 0b1000;
 233
 234                                case crmFastDecay:
 235                                        Result |= 0b1100;
 236
 237                                case crmSlowDecay:
 238                                        Result |= 0b0100;
 239
 240                        }
 241
 242                        return Result;
 243                }
 244
 245                byte GetPotentiometer()
 246                {
 247//                      byte ATest1 = Reference * 255 + 0.5;
 248//                      Serial.println( ATest1 );
 249                        return ( MaxCurrent * FSenseResistor / 2.6 ) * 255 + 0.5;
 250//                      return Reference * 255 + 0.5;
 251//                      return abs( FSpeed - 0.5 ) * 2 * 255 + 0.5;
 252                }
 253
 254                virtual void UpdateSpeed() = 0;
 255
 256                void UpdateFailure( bool AValue )
 257                {
 258                        if( FFailure == AValue )
 259                                return;
 260
 261                        FFailure = AValue;
 262                        FaultOutputPin.Notify( &FFailure );
 263                }
 264
 265                void InitFailure()
 266                {
 267                        FaultOutputPin.Notify( &FFailure );
 268                }
 269
 270        public:
 271                Maxim_MotorDriverBasicChannel( Maxim_MotorDriverBasicShield &AOwner, int AIndex, float AInitialSpeed, float ASenseResistor ) :
 272                        FOwner( AOwner ),
 273                        FIndex( AIndex ),
 274                        FSpeed( AInitialSpeed ),
 275                        FSenseResistor( ASenseResistor * 10 )
 276                {
 277//                      Serial.println( "---" );
 278                        FOwner.FChannels.push_back( this );
 279
 280//                      Serial.println( "---" );
 281                        SpeedInputPin.SetCallback( this, (OpenWire::TOnPinReceive)&Maxim_MotorDriverBasicChannel::DoSpeedReceive );
 282                }
 283
 284        };
 285//---------------------------------------------------------------------------
 286        class Maxim_MotorDriverChannel : public Maxim_MotorDriverBasicChannel
 287        {
 288                typedef Maxim_MotorDriverBasicChannel inherited;
 289
 290        protected:
 291                int FPWMPin;
 292
 293        protected:
 294                virtual void UpdateSpeed()
 295                {
 296                        byte AValue = abs( FSpeed - 0.5 ) * 2 * 255 + 0.5;
 297//                      Serial.println( AValue );
 298//                      Serial.println( FPWMPin );
 299                        analogWrite( FPWMPin, AValue );
 300//                      Serial.println( "---" );
 301                }
 302
 303        public:
 304                Maxim_MotorDriverChannel( Maxim_MotorDriverBasicShield &AOwner, int AIndex, int APWMPin, float AInitialSpeed, float ASenseResistor ) :
 305                        inherited( AOwner, AIndex, AInitialSpeed, ASenseResistor ),
 306                        FPWMPin( APWMPin )
 307                {
 308                }
 309        };
 310//---------------------------------------------------------------------------
 311        class Maxim_MotorDriverComponentChannel : public Maxim_MotorDriverBasicChannel
 312        {
 313                typedef Maxim_MotorDriverBasicChannel inherited;
 314
 315        public:
 316                OpenWire::SourcePin     MotorControlOutputPin;
 317
 318        protected:
 319                virtual void UpdateSpeed()
 320                {
 321                        float AValue = abs( FSpeed - 0.5 ) * 2;
 322//                      Serial.println( FSpeed );
 323                        MotorControlOutputPin.Notify( &AValue );
 324                }
 325
 326        public:
 327                using inherited::inherited;
 328        };
 329//---------------------------------------------------------------------------
 330        void Maxim_MotorDriverBasicShield::SystemStart()
 331        {
 332                inherited::SystemStart();
 333                DoGPIOTransmissionAt( 0x4, 0b10000001 ); // Enable and enable the interrupts
 334                for( int i = 0x9; i < 0x9 + 4; ++i )
 335                        DoGPIOTransmissionAt( i, 0b01010101 ); // All Output
 336
 337                DoGPIOTransmissionAt( 0x0E, 0xFF ); // All inputs
 338                DoGPIOTransmissionAt( 0x0E, 0b01111111 ); // P31 Poutput, the rest inputs
 339
 340                UpdateSettings();
 341
 342                for( int i = 0; i < FChannels.size(); ++i )
 343                        FChannels[ i ]->InitFailure();
 344
 345        }
 346//---------------------------------------------------------------------------
 347        void Maxim_MotorDriverBasicShield::UpdateFailures()
 348        {
 349                DoGPIOReadAt( 6 ); // Clear the interrupt bit
 350
 351                byte AFailureFlags = DoGPIOReadAt( 0x5B ); // Read pins 27 and up
 352                for( int i = 0; i < FChannels.size(); ++ i )
 353                        FChannels[ i ]->UpdateFailure( AFailureFlags & ( 1 << i ) == 0 );
 354
 355        }
 356//---------------------------------------------------------------------------
 357        void Maxim_MotorDriverBasicShield::UpdateSettings()
 358        {
 359                if( FChanged & 0b00110000 )
 360                {
 361                        byte    MAX7300Reg = FChannels[ 0 ]->GetRegisterPins() | ( FChannels[ 1 ]->GetRegisterPins() << 4 );
 362//                      Serial.println( MAX7300Reg );
 363                        DoGPIOTransmissionAt( 0x44, MAX7300Reg );
 364                }
 365
 366                if( FChanged & 0b11000000 )
 367                {
 368                        byte    MAX7300Reg = FChannels[ 2 ]->GetRegisterPins() | ( FChannels[ 3 ]->GetRegisterPins() << 4 );
 369                        DoGPIOTransmissionAt( 0x4C, MAX7300Reg );
 370                }
 371
 372                if( FChanged & 0b00000011 )
 373                {
 374                        if( FChanged & 0b00000001 )
 375                                DoPotentiometerTransmission( F_MAX5387_1, 0b00010001, FChannels[ 0 ]->GetPotentiometer() );
 376
 377                        if( FChanged & 0b00000010 )
 378                                DoPotentiometerTransmission( F_MAX5387_1, 0b00010010, FChannels[ 1 ]->GetPotentiometer() );
 379
 380                }
 381
 382                if( FChanged & 0b00001100 )
 383                {
 384                        if( FChanged & 0b00000100 )
 385                                DoPotentiometerTransmission( F_MAX5387_2, 0b00010001, FChannels[ 2 ]->GetPotentiometer() );
 386
 387                        if( FChanged & 0b00001000 )
 388                                DoPotentiometerTransmission( F_MAX5387_2, 0b00010010, FChannels[ 3 ]->GetPotentiometer() );
 389                }
 390
 391                for( int i = 0; i < FChannels.size(); ++i )
 392                        FChannels[ i ]->UpdateSpeed();
 393
 394                FChanged = 0;
 395                FModified = false;
 396        }
 397//---------------------------------------------------------------------------
 398}
 399
 400#endif