Lichtgitter

Aus Kicker
Zur Navigation springenZur Suche springen

So sieht unser Leihlichtgitter der Fa. Baumer aus:

LED Sendeseite:

Lichtgitter1.png

Empfangsseite:

Lichtgitter2.png

folgendes ist zu beachten:

Informationen

1. FCDM082 (FCDM012 haben eine sehr grobe Auflösung)

2. Schnittstelle wählen: SSI + RS-422 oder RS-422 oder Parallel 10 Bit + RS-422

3. richtiger Ausgabewert: - erster und letzter geblockter Strahl und nicht: Standardeinstellung Anzahl der geblockten Strahlen

4. Ausgabeformat: normal (Standardeinstellung / k.A was das heisst) oder largest blocked area oder over all

5. Kodierung: Binär (Standardeinstellung) oder Gray oder BCD

6. Doppelabtastung: nein (Standardeinstellung) oder ja (erhöht die Auflösung - darüber müssen wir noch sprechen)

7. Smoothing-Wert: 1 Strahl (Standardeinstellung) bzw. ... Strahlen

8. EXTRAS Programmier-Kit - incl. Verbindungskabel und Software zum Einstellen


Wir bekommen: RS-422 + SSI Schnittstelle

Sourcecode

Ausgegeben werden für jeden Messwert:

  • Zeitstempel
  • Koordinate (erster oder letzter geblockter Strahl?)
  • Dicke (Anzahl der geblockten Strahlen)

Fremdcode benötigt um Schnittstelle zu Verwenden!

//*****************************************************************************
//*
//*		
//*		ComTools.h
//*
//*
//*****************************************************************************
#ifndef 	__COM_TOOLS_H__
#define 	__COM_TOOLS_H__



									//  Konstanten für Parity
#define 	P_NONE		0			//	0 = kein Parity Bit
#define 	P_EVEN		1			//	1 = gerade
#define 	P_ODD		2			//	2 = ungerade
#define 	P_SPACE		3			//	3 = immer 0
#define 	P_MARK		4			//	4 = immer 1

#define 	D_7BIT		0			// 	7-Databits
#define 	D_8BIT		1			// 	8-Databits

#define 	S_1BIT		0			// 	1   Stopbit
#define 	S_1_5BIT	1			// 	1.5 Stopbits
#define 	S_2BIT		2			// 	2   Stopbits


	void	ComDetectPorts(int iCount,int *pMode,int iMaxPorts);
	int		ComInit();
	int		ComExit();
	int		ComOpen (unsigned Nr,int Baud,int Parity,int Stopbits,int Databits);
	int		ComClose(unsigned Nr);
	int		ComReadData (unsigned Nr,void *Buffer,int Max);
	int		ComRead (unsigned Nr);
	int		ComWriteData(unsigned Nr,void *Buffer,int Count);
	int		ComWrite(unsigned Nr,int Zeichen);
	int		ComGetReadCount (unsigned Nr);
	int		ComGetWriteCount(unsigned Nr);

#endif


//*****************************************************************************
//*
//*
//*		ComTools.cpp
//*
//*
//*****************************************************************************
//
//	(C) Copyright Anton Zechner 2007
//
#include	<windows.h>
#include	<memory.h>
#include	"ComTools.h"

#define 	MAX_COM_PORTS	8

static HANDLE	hComFile[MAX_COM_PORTS];
static BOOL		bIsOpen	[MAX_COM_PORTS];

//*****************************************************************************
//*
//*		ComInit
//*
//*****************************************************************************
int ComInit()
{
return 1;
}

//*****************************************************************************
//*
//*		ComExit
//*
//*****************************************************************************
int ComExit()
{
int	i;

	for(i=0;i<MAX_COM_PORTS;i++)
		{
		if(!bIsOpen[i])continue;
		ComClose(i);
		}

return 1;
}

//*****************************************************************************
//*
//*		ComOpen
//*
//*****************************************************************************
//	Öffnet eine serielle Verbindung
//	Nr			: Ist die Nummer des Com-Ports (0=COM1 1=COM2 ...)
//	Baud		: Ist die Bautrate
//	Parity		: 0 = kein Parity Bit
//				  1 = gerade
//				  2 = ungerade
//				  3	= immer 0
//				  4 = immer 1
//	Stopbits	: 0 = Ein Stopbit
//				  1 = Ein/einhalb Stopbits
//				  2 = Zwei Stopbits
//	Bits		: 0 = 7 Datenbits
//				  1 = 8 Datenbits
//				  7 = 7 Datenbits
//				  8 = 8 Datenbits
//	Ergibt 1 wenn eine Schnittstelle geöffnet wurde
int ComOpen(unsigned Nr,int Baud,int Parity,int Stopbits,int Databits)
{
static const int	iPMode[]={NOPARITY,EVENPARITY,ODDPARITY,SPACEPARITY,MARKPARITY};
static const int	iSMode[]={ONESTOPBIT,ONE5STOPBITS,TWOSTOPBITS,ONESTOPBIT};
char				cName[]="\\\\.\\COM1";
HANDLE				hFile;
COMMTIMEOUTS		sTo;
DCB					sDcb;



	if(Nr>=MAX_COM_PORTS)return 0;
	if(bIsOpen[Nr])return 0;


	cName[7]='1'+Nr;

	   hFile= CreateFile(cName,GENERIC_READ|GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
	if(hFile==INVALID_HANDLE_VALUE)
		{
		hFile=0;
		return 0;
		}

	if(Databits==7)Databits=0;


	memset(&sDcb,0,sizeof(sDcb));
	sDcb.DCBlength=sizeof(sDcb);
	sDcb.BaudRate     	= Baud;
	sDcb.fParity      	= (Parity!=0)? TRUE:FALSE;
	sDcb.fBinary      	= TRUE;
	sDcb.Parity       	= iPMode[Parity];
	sDcb.StopBits     	= iSMode[Stopbits&3];
	sDcb.fOutxCtsFlow 	= FALSE;
	sDcb.fOutxDsrFlow 	= FALSE;
	sDcb.fDtrControl	= DTR_CONTROL_ENABLE;
	sDcb.fRtsControl	= RTS_CONTROL_ENABLE;
	sDcb.fDsrSensitivity= FALSE;
	sDcb.fAbortOnError	= FALSE;
	sDcb.ByteSize     	= (Databits)? 8:7;

	if(!SetCommState(hFile,&sDcb))
		{
		CloseHandle(hFile);
		return 0;
		}


	sTo.ReadIntervalTimeout		   = MAXDWORD; 		// 0 ms Read-Tomeout
	sTo.ReadTotalTimeoutMultiplier = 0;
	sTo.ReadTotalTimeoutConstant   = 0;
	sTo.WriteTotalTimeoutMultiplier= 12000/Baud+1;	// ? ms Write timeout per byte
	sTo.WriteTotalTimeoutConstant  = sTo.WriteTotalTimeoutMultiplier+1;
	if(!SetCommTimeouts((HANDLE)hFile,&sTo))
		{
		CloseHandle(hFile);
		return 0;
		}


	hComFile[Nr]=hFile;
	bIsOpen [Nr]=TRUE;


return 1;
}



//*****************************************************************************
//*
//*		ComClose
//*
//*****************************************************************************
//	Schließt eine serielle Verbindung
//	Nr	: Ist die Nummer des Com-Ports (0=COM1 1=COM2 ...)
//	Ergibt 1 wenn eine Schnittstelle geschlossen wurde
int	ComClose(unsigned Nr)
{

	if(Nr>=MAX_COM_PORTS)return 0;
	if(!bIsOpen[Nr])return 0;

	CloseHandle(hComFile[Nr]);
	hComFile[Nr]=0;
	bIsOpen [Nr]=FALSE;


return 1;
}


//*****************************************************************************
//*
//*		ComDetectPorts
//*
//*****************************************************************************
//	Speichert in iCount die Anzahl der gefundenen COM Ports
//	In pMode werden die Portzustänte gespeichert
//		0 = Nicht vorhanden
//		1 = Vorhanden
//		2 = Vorhanden und von einem anderen Programm benutzt
//		pMode[0] für COM1
//		pMode[1] für COM2
//		...
//	iMaxPorts ist die Anzahl der Ports die gescannt werden.
void ComDetectPorts(int iCount,int *pMode,int iMaxPorts)
{
int		i;
char	cName[]="\\\\.\\COM1";
HANDLE	hCom;



	for(i=0;i<iMaxPorts;i++)
		{
		if(i<MAX_COM_PORTS && bIsOpen[i])
			{
			pMode[i]=1;
			iCount++;
			continue;
			}

		cName[7]='1'+i;
		hCom=CreateFile(cName,GENERIC_WRITE|GENERIC_READ,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
		if(hCom==INVALID_HANDLE_VALUE)
			{
			if(GetLastError()==ERROR_FILE_NOT_FOUND)
				{
				pMode[i]=0;
				continue;
				}
			else{
				pMode[i]=2;
				iCount++;
				continue;
				}
			}

		CloseHandle(hCom);
		pMode[i]=1;
		iCount++;
		}

}

//*****************************************************************************
//*
//*		ComRead
//*
//*****************************************************************************
//	Ein Zeichen lesen
//	Nr		: Ist die Nummer des Com-Ports (0=COM1 1=COM2 ...)
//	Ergibt -1 wenn nichts gelesen wurde sonst das Zeichen
int ComRead(unsigned Nr)
{
unsigned char 	c;
DWORD			dwCount;


	if(Nr>=MAX_COM_PORTS)return -1;
	if(!bIsOpen[Nr])return -1;

	if(!ReadFile(hComFile[Nr],&c,1,&dwCount,0))return -1;
	if(dwCount!=1)return -1;


return c;
}

//*****************************************************************************
//*
//*		ComRead
//*
//*****************************************************************************
//	Mehrere Zeichen lesen
//	Nr		: Ist die Nummer des Com-Ports (0=COM1 1=COM2 ...)
//	Buffer	: Buffer in dem die Zeichen gespeichert werden
//	Max		: Maximale Anzahl der zu lesenden Zeichen
//	Ergibt die Anzahl der gelesenen Zeichen
int ComReadData(unsigned Nr,void *Buffer,int Max)
{
DWORD	dwCount;


	if(Nr>=MAX_COM_PORTS)return 0;
	if(!bIsOpen[Nr])return 0;

	ReadFile(hComFile[Nr],Buffer,Max,&dwCount,0);

return dwCount;
}


//*****************************************************************************
//*
//*		ComWrite
//*
//*****************************************************************************
//	Ein Zeichen senden
//	Nr		: Ist die Nummer des Com-Ports (0=COM1 1=COM2 ...)
//	Zeichen	: Ist das Zeichen das gesendet werden soll.
//	Ergibt die Anzahl der gesendeten Zeichen
int ComWrite(unsigned Nr,int Zeichen)
{
DWORD			dwCount;


	if(Nr>=MAX_COM_PORTS)return 0;
	if(!bIsOpen[Nr])return 0;

	WriteFile(hComFile[Nr],&Zeichen,1,&dwCount,0);


return dwCount;
}

//*****************************************************************************
//*
//*		ComWrite
//*
//*****************************************************************************
//	Mehrere Zeichen schreiben
//	Nr		: Ist die Nummer des Com-Ports (0=COM1 1=COM2 ...)
//	Buffer	: Buffer in dem die Zeichen gespeichert werden
//	Count	: Anzahl der zu sendenden Zeichen
//	Ergibt die Anzahl der gesendeten Zeichen
int	ComWriteData(unsigned Nr,void *Buffer,int Count)
{
DWORD			dwCount;


	if(Nr>=MAX_COM_PORTS)return 0;
	if(!bIsOpen[Nr])return 0;

	WriteFile(hComFile[Nr],Buffer,Count,&dwCount,0);

return dwCount;
}



//*****************************************************************************
//*
//*		ComGetReadCount
//*
//*****************************************************************************
//	Ergibt die Anzahl der Bytes die im Lesepuffer der Schnittstelle sind
//	Nr		: Ist die Nummer des Com-Ports (0=COM1 1=COM2 ...)
//	Ergibt die Anzahl der Bytes im Buffer
int ComGetReadCount(unsigned Nr)
{
COMSTAT		sComStat;
DWORD		dwErrorFlags;


	if(Nr>=MAX_COM_PORTS)return 0;
	if(!bIsOpen[Nr])return 0;

	dwErrorFlags=0;

	if(!ClearCommError(hComFile[Nr], &dwErrorFlags, &sComStat))return 0;

return sComStat.cbInQue;
}

//*****************************************************************************
//*
//*		ComGetWriteCount
//*
//*****************************************************************************
//	Ergibt die Anzahl der Bytes die im Schreibpuffer der Schnittstelle sind
//	Nr		: Ist die Nummer des Com-Ports (0=COM1 1=COM2 ...)
//	Ergibt die Anzahl der Bytes im Buffer
int ComGetWriteCount(unsigned Nr)
{
COMSTAT		sComStat;
DWORD		dwErrorFlags;


	if(Nr>=MAX_COM_PORTS)return 0;
	if(!bIsOpen[Nr])return 0;

	dwErrorFlags=0;

	if(!ClearCommError(hComFile[Nr], &dwErrorFlags, &sComStat))return 0;

return sComStat.cbOutQue;
}


//*****************************************************************************
//*
//*		
//*		spider.c
//*
//*
//*****************************************************************************
#include <conio.h>
#include <stdio.h>
#include <windows.h>
#include <string.h>
#include "ComTools.h"

#define OVECCOUNT 30    /* should be a multiple of 3 */

int
spiderReadData(unsigned int port, unsigned char *data, unsigned int max)
{                 
 return ComReadData(port, data, max);                
}

/*
 * Open the serial port and set the options as needed
 */
int
spiderOpenPort(unsigned int port)
{
 if(!ComOpen(port,38400,1,0,8)) {
    printf("spiderOpenPort failed for port 0x%x\n", port);
    return -1;
 }                       
 return 1;                                              
}

/*
 * Send command to COM_PORT port and wait until the echo occurs
 */
int
spiderSendCommand(unsigned int port, unsigned int command)
{
 if (ComWrite(port, command) == -1) {
    printf("spiderSendCommand failed for write on port 0x%x command 0x%x\n", 
        port, command);
    return -1;
 }
 sleep(1);
 /* wait until data is available */
 while (!ComGetReadCount(port)) {
 }
 if (ComRead(port) != command) {
    printf("spiderSendCommand failed for read on port 0x%x command 0x%x\n",
        port, command);
    return -1;
 }
 return command;                    
}


//*****************************************************************************
//*
//*
//*		ComTools.cpp
//*
//*
//*****************************************************************************
//

#include <conio.h>
#include <stdio.h>
#include <windows.h>
#include <string.h>

#define COM_PORT 1
#define OVECCOUNT 30    /* should be a multiple of 3 */


int
outputData(unsigned char *data, unsigned int max)
{
 int i = 0;
 
 printf("0x%.2x%.2x\t", data[1] & 0xff, data[0] & 0xff);
 printf("0x%.2x%.2x\n", data[3] & 0xff, data[2]) & 0xff;
 return 0;                 
}

//*****************************************************************************
//*
//*		main
//*
//*****************************************************************************
int main(int argc, char* argv[])
{
 unsigned char data[4];
 unsigned int res = 0;
 unsigned int i = 0;
 SYSTEMTIME stime, atime;
    
    

//open serial terminal port
printf("spiderOpenPort(): 0x%x\n", spiderOpenPort(COM_PORT));

GetSystemTime(&stime);
for (i = 0; i < 150; i++) {
//send read_all command
//printf("spiderSendCommand(): 0x%x\n",0);
spiderSendCommand(COM_PORT, 0x81);
//read data
res = spiderReadData(COM_PORT, data, sizeof(data));
//printf("spiderReadData(): 0x%x\n", res);
GetSystemTime(&atime);
printf("%d\t%ul\t", i, (atime.wMilliseconds + atime.wSecond * 1000) -
    (stime.wMilliseconds + stime.wSecond * 1000));
outputData(data, res);
}

system("PAUSE");

return 0;
}

OS9 Testmessung

Die Testmessungen mit dem Lichtgitter wurde auf einem OS9-Rechner mit PowerPC 555 wiederholt.

Systembedingt wurde die serielle Schnittstelle /term verwendet, die nur! mit 9600 Baud bei 1 Stopbit und even Parity, betrieben werden kann :-((

Die Schnittstelle musste zunächst in den binär-Moddus versetzt werden, damit volle 8 Bit Wertevorrat gesendet und empfangen werden kann; das erledigt das Programm serio.c.

Es wurden so schnell als möglich 1000 Abfragen mittels Lichtgitterkommando "read_all" (Code 0x81) im Programm lg.c gemacht. Das Kommandobyte 0x81 wird vom Lichtgitter geechot und es folgen vier binäre Datenbytes mit der Bereichsangabe des die Lichtstrahlen unterbrechenden Objektes mit Start- und Endewert.

Es werden also 6 Bytes übertragen. Bei einer Baudrate von 9600 ergibt das für die Zeichen bereits eine reine Übertragungszeit von 6 ms. Für die Verarbeitung im Lichtgitter und im OS9 System braucht man demzufolge 0,919 ms pro Kommandosequenz. Die minimale erreichbar Zykluszeit des Lichtgitters ist mit ca. 5,5 ms angegeben bei 38400 Baud Übertragungsrate.

Es wurden 1000 Abfragen in 6919 ms geschafft.

serio.c:

#include <stdio.h>
#include <stddef.h>
#include <modes.h>
#include <types.h>
#include <stdlib.h>
#include <sysglob.h>
#include <stdio.h>
#include <stdlib.h>

int main (int argc, char* argv)

{
printf ("serioraw v1.0 PPC turn /term into raw mode 38kbaud even parity\n");
system("kill 5;kill 7;kill 2; kill 9");

system("xmode /term nopause noecho");
system ("xmode /term xon=0x0 xoff=0x0");
system("xmode /term abort=0x0 bell=0x0");
system("xmode /term nobsb");
system("xmode /term nodel");
system("xmode /term nobsb");
system("xmode /term eof=0x0");
system("xmode /term eor=0x0");
system("xmode /term bsp=0x0");
system("xmode /term tab=0x0");
system("xmode /term quit=0x0");
system("xmode /term noupc");

system("xmode /term 0x7f=PASSTHRU  0x01=PASSTHRU 0x02=PASSTHRU 0x03=PASSTHRU ");
system("xmode /term 0x04=PASSTHRU 0x05=PASSTHRU 0x06=PASSTHRU ");
system("xmode /term 0x08=PASSTHRU 0x09=PASSTHRU 0x0b=PASSTHRU ");
system("xmode /term 0x0c=PASSTHRU 0x0d=PASSTHRU 0x10=PASSTHRU 0x11=PASSTHRU 0x12=PASSTHRU ");
system("xmode /term 0x13=PASSTHRU 0x17=PASSTHRU 0x18=PASSTHRU 0x1a=PASSTHRU 0x1b=PASSTHRU");
system("xmode /term baud=9600 parity=even");

return 0;
}

lg.c:

#include <stdio.h>
#include <stddef.h>
#include <modes.h>
#include <types.h>
#include <stdlib.h>
#include <sysglob.h>
#include <sg_codes.h>

u_int32 myclock(void)
{
glob_buff myg;
_os_getsys (offsetof(sysglobs, d_ticks ),sizeof(u_int32),&myg);
return myg.lng;
}
u_int32 wr_cmd(path_id pd,u_int8 cmd)
{
u_int32 count;
error_code ierr;
count=1;
_os_write(pd,&cmd,&count);
count=0;
_os_gs_ready(pd,&count);
count=1;
_os_read(pd,&cmd,&count);
return cmd;
}
u_int32 wr_dat(path_id pd,u_int8 cmd)
{
u_int32 count;
error_code ierr;
count=1;
_os_write(pd,&cmd,&count);
return cmd;
}

int main (int argc, char** argv)
{
char buf;
path_id path;
u_int32 count,icount,tstart,tend;
error_code ierr;
unsigned char cmd;
unsigned char data[100];
printf("Lichtgittertestprog V1.0 R.Seck\n");
/* stoppen aller aAktivitäten auf /term und baud=38400*/
ierr=_os_open("/term",S_IWRITE|S_IREAD,&path);

_os_gs_ready(path,&count);
if (count!=0) _os_read(path,&data,&count);
wr_cmd(path,0x00);
wr_cmd(path,0x89);  /* read DATA und POS*/
wr_dat(path,0x8f);  /* read DATA und POS*/
tstart=myclock();
for (icount=1;icount<1000;icount++) {
	wr_cmd(path,0x81);  /* read DATA und POS*/
	_os_gs_ready(path,&count);
	count=4;
	_os_read(path,&data,&count);
}
tend=myclock();
printf("Lichtgitterzyclus: %d [ms] 1000 Messungen gelesen\n",tend-tstart);
_os_close (path);
return 0;
}