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