Hi
Ich habe die Schaltung mit dem RNST01 zur Ansteuerung von 2 Schrittmotoren nachgebaut.(Von robotikhardware.de) Die Platine ist auf meinem Roboter verbaut der zusätzlich mit einer Sensorplatine bestückt ist. An die Sensorplatine sind 3 Distanzsensoren angeschlossen. Die 3 Sensorwerte werden mit Hilfe eines AD-Wandlers PCF-8591 ausgelesen.
Angesteuert wird das ganze über nen RS232 Dongle nach I2C. Die Ansteuerung der Sensorwerte macht keine Probleme. Die läuft wirklich sehr gut. Nur bei der Ansteuerung der Schrittmotoren tut sich nichts. Es muss irgendwas noch in meinem Quellcode falsch sein , dass die Ansteuerung nicht funktioniert. Ein HardwareFehler kann ich ausschließen hab die Platine sehr genau überprüft. Ich habe auch ein Terminal mit nem max232 an die Schaltung angeschlossen. Sobald die Platine mit Spannung versorgt wird initialisiert sie etc... Nur wenn ich nun Signale an den RNST01 sende passiert nichts. Die Treiberbausteine(L29 bleiben immer kalt. Könntet ihr bitte einen Blick auf meinen Quellcode werfen.
Im Quellcode mit eingebunden ist die port.dll und die i2c.com zum öffnen des Com-Ports und die I2C Befehle.
Quellcode des Programms:
Code:
unit RNST01_Form;
interface
uses
I2CCOM,PORTINC,
SysUtils, Classes, Graphics, Controls, Forms,
ExtCtrls, StdCtrls, LMDCustomButton, LMDButton, LMDControl,
LMDBaseControl, LMDBaseGraphicControl, LMDGraphicControl, LMDBaseMeter,
LMDCustomProgressFill, LMDProgressFill, Buttons;
const
RNST01_Write:byte = $56;
RNST01_Read :byte = $57;
cActivityInd:array[0..3] of char = ('\','|','/','-');
type
TForm1 = class(TForm)
Timer1: TTimer;
Panel3: TPanel;
comboPort: TComboBox;
btnStartStop: TLMDButton;
Label7: TLabel;
comboSpeed: TComboBox;
Label8: TLabel;
IndTimer: TLMDProgressFill;
IndSDA: TLMDProgressFill;
IndSCL: TLMDProgressFill;
btnISet: TButton;
Edit1: TEdit;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
Label4: TLabel;
Label5: TLabel;
Label6: TLabel;
btnMotorLinksDrehtLinks: TSpeedButton;
btnMotorLinksDrehtRechts: TSpeedButton;
Label9: TLabel;
Label10: TLabel;
btnMotorRechtsDrehtRechts: TSpeedButton;
btnMotorRechtsDrehtLinks: TSpeedButton;
Label15: TLabel;
SpeedButton5: TSpeedButton;
btnVoll: TSpeedButton;
btnHalb: TSpeedButton;
Panel1: TPanel;
SpeedButton3: TSpeedButton;
SpeedButton4: TSpeedButton;
Label13: TLabel;
Label11: TLabel;
SpeedButton2: TSpeedButton;
SpeedButton1: TSpeedButton;
Label12: TLabel;
Label17: TLabel;
Label16: TLabel;
Label18: TLabel;
Edit2: TEdit;
Button1: TButton;
SpeedButton6: TSpeedButton;
Button2: TButton;
procedure Timer1Timer(Sender: TObject);
procedure btnStartStopClick(Sender: TObject);
procedure btnISetClick(Sender: TObject);
procedure btnVollClick(Sender: TObject);
procedure btnHalbClick(Sender: TObject);
procedure btnMotorLinksDrehtLinksClick(Sender: TObject);
procedure btnMotorLinksDrehtRechtsClick(Sender: TObject);
procedure btnMotorRechtsDrehtLinksClick(Sender: TObject);
procedure btnMotorRechtsDrehtRechtsClick(Sender: TObject);
procedure btnMotorenAnClick(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure SpeedButton1Click(Sender: TObject);
procedure SpeedButton4Click(Sender: TObject);
procedure SpeedButton2Click(Sender: TObject);
procedure SpeedButton3Click(Sender: TObject);
procedure SpeedButton6Click(Sender: TObject);
procedure SpeedButton5Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
end;
var
Form1: TForm1;
ActivityInd:integer;
implementation
uses
Dialogs;
{$R *.DFM}
procedure TForm1.Timer1Timer(Sender: TObject);
begin
IndTimer.Caption:=cActivityInd[ActivityInd];
inc(ActivityInd,1);
if ActivityInd>=4 then ActivityInd:=0;
Application.ProcessMessages;
// REALTIME(false);
// DELAYUS(100);
// REALTIME(false);
IndSDA.UserValue:=Integer(DSR);
IndSCL.UserValue:=Integer(CTS);
end;
procedure TForm1.btnStartStopClick(Sender: TObject);
begin
ActivityInd:=0;
if btnStartStop.Caption='Start' then begin
btnStartStop.Caption:='Stop';
I2C_Init(ComboPort.ItemIndex+1,StrToInt(ComboSpeed.Text));
IndTimer.Enabled:=true;
IndTimer.Caption:='';
IndSDA.Enabled:=true;
IndSCL.Enabled:=true;
Timer1.Enabled:=true;
end else begin
Timer1.Enabled:=false;
btnStartStop.Caption:='Start';
I2C_DeInit(-1);
IndTimer.Enabled:=false;
IndTimer.Caption:='Timer';
IndSDA.Enabled:=false;
IndSCL.Enabled:=false;
IndSDA.UserValue:=0;
IndSCL.UserValue:=0;
end;
end;
procedure TForm1.btnISetClick(Sender: TObject);
var
Strom:Integer;
begin
Strom:=StrToIntDef(Edit1.Text,-1) div 10;
if Strom=-1 then
MessageDlg(format('Strom: ungültiger Wert "%s" mA',[Edit1.Text]), mtWarning, [mbOK], 0)
else begin
REALTIME(true);
I2C_Start;
I2C_Write(RNST01_Write);
I2C_Acknowledge(noAck);
I2C_Write(10); //Kennung RNST01
I2C_Acknowledge(noAck);
I2C_Write(1); //Befehl: Motorstrom setzen
I2C_Acknowledge(noAck);
I2C_Write(2); //Kennung: beide Motoren
I2C_Acknowledge(noAck);
I2C_Write(Strom);
I2C_Acknowledge(noAck);
I2C_Stop;
REALTIME(false);
end;
end;
procedure TForm1.btnVollClick(Sender: TObject);
begin
REALTIME(true);
I2C_Start;
I2C_Write(RNST01_Write);
I2C_Acknowledge(noAck);
I2C_Write(10); //Kennung RNST01
I2C_Acknowledge(noAck);
I2C_Write(14); //Befehl: Voll-/Halbschritt Modus wählen
I2C_Acknowledge(noAck);
I2C_Write(0); //Beide Motoren Vollschritt Modus
I2C_Acknowledge(noAck);
I2C_Stop;
REALTIME(false);
end;
procedure TForm1.btnHalbClick(Sender: TObject);
begin
REALTIME(true);
I2C_Start;
I2C_Acknowledge(noAck);
I2C_Write(RNST01_Write);
I2C_Acknowledge(noAck);
I2C_Write(10); //Kennung RNST01
I2C_Acknowledge(noAck);
I2C_Write(14); //Befehl: Voll-/Halbschritt Modus wählen
I2C_Acknowledge(noAck);
I2C_Write(1); //Beide Motoren Halbschritt Modus
I2C_Acknowledge(noAck);
I2C_Stop;
REALTIME(false);
end;
procedure TForm1.btnMotorLinksDrehtLinksClick(Sender: TObject);
begin
REALTIME(true);
I2C_Start;
I2C_Acknowledge(noAck);
I2C_Write(RNST01_Write);
I2C_Acknowledge(noAck);
I2C_Write(10); //Kennung RNST01
I2C_Acknowledge(noAck);
I2C_Write(4); //Befehl: Motor Drehrichtung
I2C_Acknowledge(noAck);
I2C_Write(0); //Linker Motor
I2C_Acknowledge(noAck);
I2C_Write(0); //Drehe Links
I2C_Acknowledge(noAck);
I2C_Stop;
REALTIME(false);
end;
procedure TForm1.btnMotorLinksDrehtRechtsClick(Sender: TObject);
begin
REALTIME(true);
I2C_Start;
I2C_Write(RNST01_Write);
I2C_Acknowledge(noAck);
I2C_Write(10); //Kennung RNST01
I2C_Acknowledge(noAck);
I2C_Write(4); //Befehl: Motor Drehrichtung
I2C_Acknowledge(noAck);
I2C_Write(0); //Linker Motor
I2C_Acknowledge(noAck);
I2C_Write(1); //Drehe Rechts
I2C_Acknowledge(noAck);
I2C_Stop;
REALTIME(false);
end;
procedure TForm1.btnMotorRechtsDrehtLinksClick(Sender: TObject);
begin
REALTIME(true);
I2C_Start;
I2C_Write(RNST01_Write);
I2C_Acknowledge(noAck);
I2C_Write(10); //Kennung RNST01
I2C_Acknowledge(noAck);
I2C_Write(4); //Befehl: Motor Drehrichtung
I2C_Acknowledge(noAck);
I2C_Write(1); //Rechter Motor
I2C_Acknowledge(noAck);
I2C_Write(0); //Drehe Links
I2C_Acknowledge(noAck);
I2C_Stop;
REALTIME(false);
end;
procedure TForm1.btnMotorRechtsDrehtRechtsClick(Sender: TObject);
begin
REALTIME(true);
I2C_Start;
I2C_Write(RNST01_Write);
I2C_Acknowledge(noAck);
I2C_Write(10); //Kennung RNST01
I2C_Acknowledge(noAck);
I2C_Write(4); //Befehl: Motor Drehrichtung
I2C_Acknowledge(noAck);
I2C_Write(1); //Rechter Motor
I2C_Acknowledge(noAck);
I2C_Write(1); //Drehe Rechts
I2C_Acknowledge(noAck);
I2C_Stop;
REALTIME(false);
end;
procedure TForm1.btnMotorenAnClick(Sender: TObject);
begin
REALTIME(true);
I2C_Start;
I2C_Write(RNST01_Write);
I2C_Acknowledge(noAck);
I2C_Write(10); //Kennung RNST01
I2C_Acknowledge(noAck);
I2C_Write(10); //Befehl: Motor Kontrolle
I2C_Acknowledge(noAck);
I2C_Write(2); //Beide Motoren einschalten
I2C_Acknowledge(noAck);
I2C_Stop;
REALTIME(false);
end;
procedure TForm1.Button1Click(Sender: TObject);
var
Schrittwert:Integer;
begin
Schrittwert:=StrToIntDef(Edit2.Text,-1) ;
if (Schrittwert<0) or (Schrittwert>255) then
MessageDlg(format('Schritte: ungültiger Wert "%s"´. Wert muss zwischen 0 und 255 liegen' ,[Edit2.Text]), mtWarning, [mbOK], 0)
else begin
REALTIME(true);
I2C_Start;
I2C_Write(RNST01_Write);
I2C_Acknowledge(noAck);
I2C_Write(10); //Kennung RNST01
I2C_Acknowledge(noAck);
I2C_Write(8); //Befehl: Schritte pro Sekunde
I2C_Acknowledge(noAck);
I2C_Write(2); //Beide Motoren
I2C_Acknowledge(noAck);
I2C_Write(SchrittWert);
I2C_Acknowledge(noAck);
I2C_Stop;
REALTIME(false);
end;
end;
procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
REALTIME(true);
I2C_Start;
I2C_Write(RNST01_Write);
I2C_Acknowledge(noAck);
I2C_Write(10); //Kennung RNST01
I2C_Acknowledge(noAck);
I2C_Write(6); //Befehl: Motor einschalten
I2C_Acknowledge(noAck);
I2C_Write(0); //Linker Motor
I2C_Acknowledge(noAck);
I2C_Stop;
REALTIME(false);
end;
procedure TForm1.SpeedButton4Click(Sender: TObject);
begin
REALTIME(true);
I2C_Start;
I2C_Write(RNST01_Write);
I2C_Acknowledge(noAck);
I2C_Write(10); //Kennung RNST01
I2C_Acknowledge(noAck);
I2C_Write(6); //Befehl: Motor einschalten
I2C_Acknowledge(noAck);
I2C_Write(1); //Rechter Motor
I2C_Acknowledge(noAck);
I2C_Stop;
REALTIME(false);
end;
procedure TForm1.SpeedButton2Click(Sender: TObject);
begin
REALTIME(true);
I2C_Start;
I2C_Write(RNST01_Write);
I2C_Acknowledge(noAck);
I2C_Write(10); //Kennung RNST01
I2C_Acknowledge(noAck);
I2C_Write(3); //Befehl: Motor stoppen, Strom eingeschaltet lassen
I2C_Acknowledge(noAck);
I2C_Write(0); //Linker Motor
I2C_Acknowledge(noAck);
I2C_Stop;
REALTIME(false);
end;
procedure TForm1.SpeedButton3Click(Sender: TObject);
begin
REALTIME(true);
I2C_Start;
I2C_Write(RNST01_Write);
I2C_Acknowledge(noAck);
I2C_Write(10); //Kennung RNST01
I2C_Acknowledge(noAck);
I2C_Write(3); //Befehl: Motor stoppen, Strom eingeschaltet lassen
I2C_Acknowledge(noAck);
I2C_Write(1); //Linker Motor
I2C_Acknowledge(noAck);
I2C_Stop;
REALTIME(false);
end;
procedure TForm1.SpeedButton6Click(Sender: TObject);
begin
Panel1.Enabled:=false;
Panel1.Color:=clBackground;
REALTIME(true);
I2C_Start;
I2C_Write(RNST01_Write);
I2C_Acknowledge(noAck);
I2C_Write(10); //Kennung RNST01
I2C_Acknowledge(noAck);
I2C_Write(9); //Befehl: Motor Kontrolle - Strom aus
I2C_Acknowledge(noAck);
I2C_Write(2); //Beide Motoren ausschalten
I2C_Acknowledge(noAck);
I2C_Stop;
REALTIME(false);
end;
procedure TForm1.SpeedButton5Click(Sender: TObject);
begin
Panel1.Enabled:=true;
Panel1.Color:=clBtnFace;
REALTIME(true);
I2C_Start;
I2C_Write(RNST01_Write);
I2C_Acknowledge(noAck);
I2C_Acknowledge(noAck);
I2C_Write(10); //Kennung RNST01
I2C_Acknowledge(noAck);
I2C_Write(10); //Befehl: Motor Kontrolle - Strom ein
I2C_Acknowledge(noAck);
I2C_Write(2); //Beide Motoren einschalten
I2C_Acknowledge(noAck);
I2C_Stop;
REALTIME(false);
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
REALTIME(true);
I2C_Start;
I2C_Write(RNST01_Write);
I2C_Acknowledge(noAck);
I2C_Write(10); //Kennung RNST01
I2C_Acknowledge(noAck);
I2C_Write(11); //Befehl: Konfiguration anzeigen
I2C_Acknowledge(noAck);
I2C_Stop;
REALTIME(false);
end;
end.
I2c.com:
Code:
//Purpose : I2C BitBanging routines for the serial ports using the PORT.DLL
//Reason : I2C_DeInit added. This is for a defined close of the I2C
// communication after use (for example when terminating an
// application)
// Renamed all procedures and function to meet the english language.
// Also set the prefix "I2C_" in front of each procedure/function to
// avoid possible conflicts with other procedures/functions with a
// similar name.
unit I2CCOM;
{______________________________________________________________________________}
interface
uses
SysUtils, StrUtils, PORTINC;
const
ack :boolean=true;
noack:boolean=false;
delayMarker:Cardinal=1;
procedure I2C_Init(ComPort:Integer; Baud:Integer);
procedure I2C_DeInit(ComPort:Integer);
Procedure I2C_Start;
Procedure I2C_Stop;
Procedure I2C_Acknowledge(ack:boolean);
Function I2C_Write (Wert : Byte): Boolean;
Function I2C_Read : Byte; overload;
Function I2C_Read(dummy:string) : string; overload;
procedure SDA(Value:byte); overload;
function SDA:byte; overload;
procedure SCL(Value:byte); overload;
function SCL:byte; overload;
{______________________________________________________________________________}
implementation
uses
DateUtils;
type
eTimeOutError=class(Exception);
var
sTime,eTime:TDateTime;
TimeoutValue:integer;
DelayValue:cardinal;
function isTimeout(what:string):boolean;
begin
Result:=SecondsBetween(sTime,eTime)>=TimeoutValue;
if Result then
Raise eTimeOutError.CreateFmt('I2C Timeout (%s)',[what]);
end;
procedure SDA(Value:byte); overload;
begin
DTR(Value);
end;
function SDA:byte; overload;
begin
Result:=DSR;
end;
procedure SCL(Value:byte); overload;
begin
RTS(Value);
// if Value=0 then
// repeat
// Delayus(DelayValue);
// eTime:=now;
// until (SCL=0) or isTimeout('SCL=0');
repeat
Delayus(DelayValue);
eTime:=now;
until (SCL=Value) or isTimeout('SCL='+IntToStr(Value));
end;
function SCL:byte; overload;
begin
Result:=CTS;
end;
procedure I2C_Init(ComPort:Integer; Baud:Integer);
begin
OpenCom(Pchar(format('com%d:%d,N,8,1',[ComPort,Baud])));
I2C_Stop;
Delayus(DelayValue);
end;
procedure I2C_DeInit(ComPort:Integer);
begin
I2C_Stop;
CloseCom;
end;
procedure I2C_Start;
begin
SCL(1);
Delayus(DelayValue);
SDA(1);
sTime:=now;
repeat
Delayus(DelayValue);
eTime:=now;
until (SCL=1) and (SDA=1) or isTimeout('Start');
SDA(0);
Delayus(DelayValue);
SCL(0);
Delayus(DelayValue);
end;
procedure I2C_Stop;
begin
SDA(0);
Delayus(DelayValue);
SCL(1);
sTime:=now;
repeat
Delayus(DelayValue);
eTime:=now;
until (SCL=1) or isTimeout('Stop');
SDA(1);
Delayus(delayMarker*DelayValue);
end;
procedure I2C_Pulse;
begin
SCL(1);
sTime:=now;
repeat
Delayus(DelayValue);
eTime:=now;
until (SCL=1) or isTimeout('Pulse');
SCL(0);
Delayus(DelayValue);//new
end;
procedure I2C_Acknowledge(ack:boolean);
begin
if ack then begin
SDA(0);
Delayus(DelayValue);
I2C_Pulse;
end else begin
SDA(1);
Delayus(DelayValue);
I2C_Pulse;
end;
Delayus(delayMarker*DelayValue);
end;
Function I2C_Write(Wert : Byte): Boolean;
var
Bitwert, n: Byte;
begin
Result := true;
Bitwert := 128;
//SDA(0);
for n:= 1 to 8 do begin
if (Wert and Bitwert) = Bitwert then
SDA(1)
else
SDA(0);
Bitwert := Bitwert SHR 1;
Delayus(DelayValue);
I2C_Pulse;
end;
// Delayus(DelayValue);
// I2C_Pulse;
Delayus(delayMarker*DelayValue);
end;
function I2C_Read : Byte;
var Mask, n: Byte;
begin
SDA(1);
Mask := 128;
Result := 0;
for n:= 1 to 8 do begin
SCL(1);
sTime:=now;
repeat
Delayus(DelayValue);
eTime:=now;
until (SCL=1) or isTimeout('Read');
if SDA=1 then
Result := Result OR Mask ;
Mask := Mask SHR 1;
SCL(0);
Delayus(DelayValue);
end;
end;
Function I2C_Read(dummy:string) : string; overload;
var
Mask, n: Byte;
begin
SDA(1);
Mask := 128;
Result:='';
for n:= 1 to 8 do begin
SCL(1);
sTime:=now;
repeat
Delayus(DelayValue);
eTime:=now;
until (SCL=1) or isTimeout('Read');
Result:=Result+ifthen(SDA=1,'1','0');
Mask := Mask SHR 1;
SCL(0);
Delayus(DelayValue);
end;
end;
{______________________________________________________________________________}
initialization
TimeoutValue:=3; //seconds
DelayValue :=1; //microseconds
end.
Ich denke das es vielleicht auch an der i2c.com liegen könnte . Das die Routine einfach nicht richtig stimmt.
Wär spitze wenn ihr mir weiterhelfen könntet.
Gruß Nero
Lesezeichen