RNMotor-Board - Frage zur I2C-Ansteuerung
Moin,
@Frank, ich wollte mich ja nochmal bei dir melden, wenn ich das Motor-Board ausprobiert habe. Leider hat eine andere Bestellung etwas auf sich warten lassen, aber jetzt habe ich die nötigen Kabel und ein Application Board für mein Mega8 und konnte heute mit dem Testen beginnen.
Ich programmiere das Mega8-Modul mit dem AVRco (Pascal), der hier wohl nicht so verbreitet ist. Ich habe noch nicht so viel Ahnung von dem Ding, aber das wird schon noch kommen :-) Ich habe mir die Anleitung zum Motor-Board angeschaut, bei der ja zu jedem Befehl auch ein Bascom-Beispielcode vorhanden ist. Die Sprache kenne ich leider überhaupt nicht, aber mich hat gewundert, dass die Daten in ein Array gesetzt werden und dann nur das erste Element versendet wird:
Dim I2cdaten(6) As Byte
'Motorstrom auf 200mA begrenzen
I2cdaten(1) = 10 'Kennung muss bei RN-Motor immer 10 sein
I2cdaten(2) = 10 'Befehlscode
I2cdaten(3) = 0 '1 Parameter
I2csend &H56, I2cdaten(1),5 'Befehl wird gesendet
Oder verstehe ich das nur falsch? Vielleich könnte mir jemand noch etwas genauer beschreiben, was man genau an die Platine senden soll.
Was muss man eigentlich alles senden, damit sich der Motor zunächst einmal dreht (zum Testen, ob es überhaupt geht)? Reicht da "Motor einschalten", also Befehlscode 10?
Und noch eine Frage zum Verändern der Slave ID: Wird die für immer gespeichert? Das wäre gut...
Gruß
Johannes
Code für Ansteuerung mit AVRco (Pascal)
Moin,
ich habe den Code soweit fertig. Noch ein Hinweis: Da ich zwei Boards ansteuere, habe ich das ganze so programmiert, dass ich als Nummer für die Motoren eine Zahl von 1 bis 4 übergebe. Die Funktionen pStepperAdress() und pStepperMotor() ermitteln daraus die Adresse und die Motornummer, die gesendet werden soll. Das soll nicht irritieren. Bei Bedarf poste ich den Code nochmal einfacher für nur ein Board.
Code:
program ApplicationBoardTest;
{ $BOOTRST $00C00} {Reset Jump to $00C00}
{$NOSHADOW}
{ $W+ Warnings} {Warnings off}
Device = mega8, VCC = 5;
Import SysTick, SerPort, PWMport1, PWMport2, ADCPort, I2Cexpand, TWImaster, LCDmultiPort;
From System Import;
Define
ProcClock = 16000000; {Hertz}
SysTick = 10; {msec}
StackSize = $003C, iData;
FrameSize = $003C, iData;
SerPort = 19200, Stop1; {Baud, StopBits|Parity}
RxBuffer = 8, iData;
TxBuffer = 8, iData;
ADCchans = 2, iData;
ADCpresc = 128;
PWMres = 9; {bits}
PWMpresc = 64;
TWIpresc = TWI_BR400;
LCDmultiPort = I2C_TWI;
LCDrows_M = 2; {rows}
LCDcolumns_M = 16; {columns per line}
LCDtype_M = 44780;
I2Cexpand = I2C_TWI, $38; {Port0 = PCA9554 an Adresse $38}
I2CexpPorts = Port0; // I2Cexpand ports
{Port0 ist die IO Port Erweiterung (I2Cexpand) über den PCA9554 Baustein.
Durch Anschluß weiterer PCA9554 kann man bis Port7 erweitern}
Implementation
{$IDATA}
{--------------------------------------------------------------}
{ Type Declarations }
type
{--------------------------------------------------------------}
{ Const Declarations }
const
STEPPER_ADRESS1:byte = 43;
STEPPER_ADRESS2:byte = 44;
STEPPER_MOTOR1:byte = 0;
STEPPER_MOTOR2:byte = 1;
STEPPER_MOTOR3:byte = 2;
STEPPER_MOTOR4:byte = 3;
STEPPER_DIRECTION_RIGHT:byte = 0;
STEPPER_DIRECTION_LEFT:byte = 1;
STEPPER_MODUS_VS:byte = 0;
STEPPER_MODUS_HS:byte = 1;
{--------------------------------------------------------------}
{ Var Declarations }
{$IDATA}
var
{Portdefinition für Taster und LED's. Kein Unterschied zwischen normalen IO-Ports und I2Cexpand Ports}
LED1[@Port0, 4] : bit;
LED2[@Port0, 5] : bit;
LED3[@Port0, 6] : bit;
LED4[@Port0, 7] : bit;
Taster1[@Pin0, 3] : bit;
Taster2[@Pin0, 2] : bit;
Taster3[@Pin0, 1] : bit;
Taster4[@Pin0, 0] : bit;
M1F[@PortD, 6] : bit;
M1R[@PortD, 7] : bit;
M2F[@PortD, 5] : bit;
M2R[@PortD, 4] : bit;
temp:word;
{--------------------------------------------------------------}
{ functions }
procedure InitPorts;
begin
PortD:= %00001100;
DDRD:= %11110000;
PWMPort1:= 0;
PWMPort2:= 0;
end InitPorts;
procedure Init_I2C;
begin
LCDsetup_M(LCD_m1); //Initialisiere I2C LCD an Adresse $20
LCDcursor_M(LCD_m1, false, false); //Setze Cursor Blink off und Cursor visible off
DDR0:= $F0; //Port0.4 bis 7 als Ausgänge (LED's)
Port0:= $F0; //Port0.4 bis 7 auf 1 (LED's aus)
INP_POL0:= $00; //Polarität für Taster positiv
end Init_I2C;
function pStepperAdress( Motor:byte ) : byte;
begin
if (Motor = 0) or (Motor = 1) then return(STEPPER_ADRESS1); endif;
if (Motor = 2) or (Motor = 3) then return(STEPPER_ADRESS2); endif;
end pStepperAdress;
function pStepperMotor( Motor:byte ) : byte;
begin
if (Motor = 2) then return(0);
elsif (Motor = 3) then return(1);
else return(Motor); endif;
end pStepperMotor;
procedure StepperCurrency( Motor : byte; Currency : integer );
var data : array[1..4] of byte;
begin
data[1] := 1;
data[2] := pStepperMotor( Motor );
data[3] := byte( Currency DIV 10 );
data[4] := 0;
mDelay( 100 );
TWIout( pStepperAdress( Motor ), 10, data );
mDelay( 100 );
end;
procedure StepperModus( Motor, Modus : byte );
var data : array[1..4] of byte;
begin
data[1] := 14;
data[2] := Modus;
data[3] := 0;
data[4] := 0;
mDelay( 100 );
TWIout( pStepperAdress( Motor ), 10, data );
mDelay( 100 );
end;
procedure StepperOn( Motor : byte );
var data : array[1..4] of byte;
begin
data[1] := 10;
data[2] := pStepperMotor( Motor );
data[3] := 0;
data[4] := 0;
mDelay( 200 );
TWIout( pStepperAdress( Motor ), 10, data );
mDelay( 200 );
end;
procedure StepperStop( Motor : byte );
var data : array[1..4] of byte;
begin
data[1] := 3;
data[2] := pStepperMotor( Motor );
data[3] := 0;
data[4] := 0;
mDelay( 200 );
TWIout( pStepperAdress( Motor ), 10, data );
mDelay( 200 );
end;
procedure StepperOff( Motor : byte );
var data : array[1..4] of byte;
begin
data[1] := 9;
data[2] := pStepperMotor( Motor );
data[3] := 0;
data[4] := 0;
mDelay( 10 );
TWIout( pStepperAdress( Motor ), 10, data );
mDelay( 10 );
end;
procedure StepperRotate( Motor, Speed, Direction : byte );
var data : array[1..4] of byte;
begin
data[1] := 4;
data[2] := pStepperMotor( Motor );
data[3] := Direction;
data[4] := 0;
TWIout( pStepperAdress( Motor ), 10, data );
mDelay( 100 );
data[1] := 8;
data[2] := pStepperMotor( Motor );
data[3] := Speed;
data[4] := 0;
TWIout( pStepperAdress( Motor ), 10, data );
mDelay( 100 );
data[1] := 6;
data[2] := pStepperMotor( Motor );
data[3] := 0;
data[4] := 0;
TWIout( pStepperAdress( Motor ), 10, data );
mDelay( 100 );
end;
procedure StepperStep( Motor, Direction : byte );
var data : array[1..4] of byte;
begin
data[1] := 4;
data[2] := pStepperMotor( Motor );
data[3] := Direction;
data[4] := 0;
TWIout( pStepperAdress( Motor ), 10, data );
mDelay( 30 );
data[1] := 7;
data[2] := pStepperMotor( Motor );
data[3] := 0;
data[4] := 0;
TWIout( pStepperAdress( Motor ), 10, data );
end;
procedure StepperSteps( Motor, Speed, Direction : byte; Steps : integer );
var data : array[1..4] of byte;
begin
data[1] := 4;
data[2] := pStepperMotor( Motor );
data[3] := Direction;
data[4] := 0;
TWIout( pStepperAdress( Motor ), 10, data );
mDelay( 30 );
data[1] := 8;
data[2] := pStepperMotor( Motor );
data[3] := Speed;
data[4] := 0;
TWIout( pStepperAdress( Motor ), 10, data );
mDelay( 100 );
data[1] := 5;
data[2] := pStepperMotor( Motor );
data[3] := LO( Steps );
data[4] := HI( Steps );
TWIout( pStepperAdress( Motor ), 10, data );
end;
{--------------------------------------------------------------}
{ Main Program }
{$IDATA}
begin
InitPorts;
Init_I2C;
EnableInts;
LCDclr_m(LCD_m1);
M1F:= true;
M1R:= false;
M2F:= true;
M2R:= false;
PWMport1:= 400;
PWMport2:= 400;
temp:=GetADC(1);
write(LCDout_m, ' mindrobots ');
LCDxy_m(LCD_m1, 0, 1);
//Einstellen des Motorstroms
StepperCurrency( STEPPER_MOTOR1, 200 );
//Vollschritt oder Halbschritt
StepperModus( STEPPER_MOTOR1, STEPPER_MODUS_VS );
//Einschalten
StepperOn( STEPPER_MOTOR1 );
//15 Schritte mit langsamer Geschwindigkeit, links herum
StepperSteps( STEPPER_MOTOR1, 200, STEPPER_DIRECTION_LEFT, 15 );
mDelay( 5000 );
//15 Schritte mit höherer Geschwindigkeit, links herum
StepperSteps( STEPPER_MOTOR1, 50, STEPPER_DIRECTION_LEFT, 15 );
mDelay( 1000 );
end ApplicationBoardTest.
Bei der StepperSteps()-Funktion muss man daran denken, dass die Funktion nicht so lange wartet, bis die Schritte ausgeführt wurden. Das muss man selbst mit einem Wait machen. Theoretisch könnte man noch aus der Geschwindigkeit errechnen, wie lange das Drehen dauert und dem entsprechend ein Wait setzen.
Gruß
Johannes