Fwd: emc rtlinux & irq



Folk

This forwards a most amazing post.  It came to me today from Spezia Raffaele 
Antonio in Italy.  He has built a wood router to use in his guitar 
manufacturing business.  Not only has he designed the mechanical parts of the 
router but much of the electronics on an ISA card, motor amps using simple 
h-bridge servo drivers, and hacked the EMC to run it all.

This is a must see for the mechanical types among us.  As near as I can tell, 
it is a must know more for the electrical/electronic folk.  We need a few 
code literate to take a look at what is cooking with his code mods.  There is 
one picture of a modified gui tha he wrote using Tcl/Tk.  And last but not 
least is a huge "how'd he tune it ini to make those h-bridge drivers work?"  

He appended a 3.7 meg file (enk.tar.gz) which I have placed in the dropbox at 
linuxcnc.org rather than hammering every list member with it.  Included are a 
number of jpgs of the mechanical, electronic, and electrical devices as he 
worked to develop each of them.  Included in that tarball is a text file 
where he asks the following questions of EMC users.  

----quote----

P.S. Excuse me for my bad english...and for my mistakes but are several
 yaers thet i don't write in english, and i now (know) only 20 words!!!

I have 3 question:

When i use this system with a low rotation of encoder (500 - 600 rpm ) its
 all work very well , but why while the
enkcapture routine can read very fast rotation of encoder emc interface
 have problem to display the step?

Make I the rigth thing when i use shared_memory to exacnge the step
 encoder position?

It's possible make a prg in rtlinux to generate pulse for pwm to pilot
 directli the h-bridge motor driver?

My personal goal is to make a motion control with a low number of
 componets that is possible.   And i think that this can be useful!
-----end quote-----

The rest of the message text, including the code modifications is appended to 
this forward as file toemc.  I encorage you to look over this stuff, download 
the dropbox file, and give some thought to how we might help Spezia Raffaele 
Antonio.  This might be an interesting discussion topic during a portion of 
EMC Monday if it waits that long to.

Makes me wish I'd paid more attention in high school Italian class -- wait, 
we didn't have Italian language in my high school.  Can anyone here serve as 
a translator for us?

I'll get an initial message back to him.  

Ray



----------  Forwarded Message  ----------

Subject: emc rtlinux & irq
Date: Tue, 15 Apr 2003 21:39:34 +0000
From: axefactory-at-tiscali.it
To: rehenry-at-up.net

I have a little guitar ( S.R.A.Axefactory www.axefactory.com ) shop where
i make electric guitars.
For  1 year i use linux and in particular the EMC for my home made CNC wood
ruter.
I have build a simply isa card , 3 h-bridge motor driver, and of course
, the ruter.
The isa card have 2 8255 i/o and  8259 that i use like pulse generators
for PWM , one for each axis.
To read the encoders I use a my sistem,non conventional,but it's work!!

You can see the sch. in enkcapture.jpg

(see also http://www.axefactory.com/enk/enk.html )

<s>
__________________________________________________________________
Tiscali ADSL, fino a 9 MESI GRATIS sull'offerta Tiscali ADSL Light Mega!
Tiscali ADSL non teme confronti! Abbonati subito.
http://point.tiscali.it/adsl/index.shtml

-------------------------------------------------------




I have a little guitar ( S.R.A.Axefactory www.axefactory.com ) shop where i make electric guitars.
For  1 year i use linux and in particular the EMC for my home made CNC wood ruter.
I have build a simply isa card , 3 h-bridge motor driver, and of course , the ruter.
The isa card have 2 8255 i/o and  8259 that i use like pulse generators for PWM , one for each axis.
To read the encoders I use a my sistem,non conventional,but it's work!!

You can see the sch. in enkcapture.jpg







the address that i use are:



#define POUT_STARTER 648 	/* starter =	0 1 2 3 4 5 6 7
						x y z g g g
						p p p a a a
						w w w t t t
						m m m e e e
						      x y z
						      v v v     */

#define POUT_DIR 652			/* poutdir = 	0 2 3 = dir x 
							4 8 12 = dir y
							16 32 48 = dir z   */

#define PIN_ENC 649			/* read encoder = 	0 a di x
								2 b di x
								4 a di y
								8 b di y
								16 a di z
								32 b di z	*/

#define POUT_ENC 653			/* reset encoder  irq
								0 a di x
								2 b di x
								4 a di y
								8 b di y
								16 a di z
								32 b di z	*/

#define ONX 645				/*contatore timer attivitą pwm di x */
#define OFFX 644			/*contatore timer inattivitą pwm di x */

#define ONY 640				/*contatore timer attivitą pwm di y */
#define OFFY 641			/*contatore timer inattivitą pwm di y */

#define ONZ 642				/*contatore timer attivitą pwm di z */
#define OFFZ 646			/*contatore timer inattivitą pwm di z */




#define CONTR1W8254 643			/* controllo generatore pwm 1 */
#define CONTR2W8254 647			/* controllo generatore pwm 2 */


#define CONTR1W8255 651			/* controllo porta i/o a=out starter b=input encoder */

#define CONTR2W8255 655			/* controllo porta i/o a=out direzione pwm x y z
					b=out controllo encoder */



The IRQ that I use are 3,4,5 




this is the software to read the encoders:


#include <mbuff.h>
#include <asm/io.h>
#include <rtl_core.h>
#include <rtl.h>



#define POUT_STARTER 	648

#define PIN_ENC 	649
#define POUT_ENC 	653
#define CONTR1W8255 	651
#define CONTR2W8255 	655





unsigned char abval[4][4]={{0,1,2,3},{2,0,3,1},{1,3,0,2},{3,2,0,1}} ;
unsigned char portaenc ;

unsigned char abx;
unsigned char abxvecc;

unsigned char aby;
unsigned char abyvecc;

unsigned char abz;
unsigned char abzvecc;

struct encoder
	{
	long int passo;
	int errore;
	};

struct encoder encx;
struct encoder ency;
struct encoder encz;
struct encoder* shared_memory;
char nome[]="memencxyz";

unsigned int intr_handler_encx(unsigned int irq, struct pt_regs *regs) {

	abx=(inb(PIN_ENC) & 3);
	portaenc=(portaenc & 252 ) | abx ;
	outb(portaenc,POUT_ENC);


	switch(abval[abx][abxvecc])
	{
		case 0:
		case 1: encx.passo++;
		case 2: encx.passo--;
		case 3: encx.errore++;
	}

	shared_memory[1] = encx;

	abxvecc=abx;

	rtl_hard_enable_irq (5);
	return 0;
}



unsigned int intr_handler_ency(unsigned int irq, struct pt_regs *regs) {

	aby=(inb(PIN_ENC) & 12);
	portaenc=(portaenc & 243 ) | aby ;

	aby=aby<<2;

	outb(portaenc,POUT_ENC);


	switch(abval[aby][abyvecc])
	{
		case 0:
		case 1: ency.passo++;
		case 2: ency.passo--;
		case 3: ency.errore++;
	}

	shared_memory[2] = ency;

	abyvecc=aby;

	rtl_hard_enable_irq (4);
	return 0;
}

unsigned int intr_handler_encz(unsigned int irq, struct pt_regs *regs) {

	abz=(inb(PIN_ENC) & 48);
	portaenc=(portaenc & 207 ) | abz ;

	abz=abz<<4;

	outb(portaenc,POUT_ENC);

	switch(abval[abz][abzvecc])
	{
		case 0:
		case 1: encz.passo++;
		case 2: encz.passo--;
		case 3: encz.errore++;
	}

	shared_memory[3] = encz;

	abzvecc=abz;

	rtl_hard_enable_irq (3);
	return 0;
}


int init_module(void)
{

	encx.errore=0;
	encx.passo=0;

	ency.errore=0;
	ency.passo=0;

	encz.errore=0;
	encz.passo=0;


	outb(130,CONTR1W8255);
	outb(133,CONTR2W8255);

	outb(7,POUT_STARTER);
	portaenc=inb(PIN_ENC);

	shared_memory=mbuff_alloc(nome, 30);


	abx=portaenc & 3 ;
	abxvecc=abx;

	aby=(portaenc & 12)<<2 ;
	abyvecc=aby;

	abz=(portaenc & 48)<<4 ;
	abzvecc=abz;


	rtl_request_irq (5, intr_handler_encx);
	rtl_request_irq (4, intr_handler_ency);
	rtl_request_irq (5, intr_handler_encz);

	rtl_hard_enable_irq (5);
	rtl_hard_enable_irq (4);
	rtl_hard_enable_irq (3);

	return 0;

}


void cleanup_module(void)
{
	rtl_free_irq(5);
	rtl_free_irq(4);
	rtl_free_irq(3);

}










________________________________________________________________________________
__________________________________________
________________________________
_________________________
________________
________
_
_









I have modify stg modul to use my isa card:



/*
  extstgmot.c

  Dispatcher of external motion functions for Servo To Go board.

  Modification history:

  20-Mar-2000 WPS added unused attribute to ident to avoid 'defined but not used' compiler warning.
  24-Jun-1999  FMP created from extshvmot.c and extmmmot.c, which were
  so similar that I decided to combine them and make them obsolete. Also
  added NO_LIMIT_SWITCH.
  */


/*#include <stdio.h>
#include <math.h>*/

#include <asm/io.h>
#include <mbuff.h>
#include "extintf.h"            /* these decls */
#include "stg.h"                /* decls for stg implementation */

/* ident tag */
#ifndef __GNUC__
#ifndef __attribute__
#define __attribute__(x)
#endif
#endif



#define POUT_STARTER 648 	

#define POUT_DIR 652			
#define PIN_ENC 649			

#define POUT_ENC 653

#define ONX 645
#define OFFX 644

#define ONY 641			
#define OFFY 640

#define ONZ 642
#define OFFZ 646			

#define CVX 656
#define CVY 657
#define CVZ 658


#define CONTR1W8254 643
#define CONTR2W8254 647
#define CONTR3W8254 659

#define CONTR1W8255 651
#define CONTR2W8255 655

char poutdir;
/*
unsigned long int pappa;
double pappav;
*/
char nome[]="memencxyz";

struct encoder
	{
	long int passo;
	int errore;
	};

struct encoder* shared_memory;

static char __attribute__((unused))  ident[] = "$Id: extstgmot.c,v 1.2 2000/10/27 20:34:42 terrylr Exp $";

/* Uncomment any of the following declarations to inhibit
   the use of home switches or index pulses when homing, or to
   ignore limit switches if you don't have them. */

/* Uncomment NO_HOME_SWITCH if you want homing sequence to
   ignore the home switch, and only use the index pulse for homing.
   This has the effect of making the home switches always appear tripped. */
/* #define NO_HOME_SWITCH */

/* Uncomment NO_INDEX_PULSE if you want homing sequence to
   ignore the index pulse, and only use the home switch for homing.
   This has the effect of making the index pulse always appear present. */
/* #define NO_INDEX_PULSE */

/* Uncomment NO_LIMIT_SWITCH if you don't have limit switches.
   This has the effect of making the positive and negative travel
   limit switches never appear tripped. */
/* #define NO_LIMIT_SWITCH */

int extMotInit(const char * stuff)
{

shared_memory = mbuff_alloc(nome, 30);
  
  return 0;
}

int extMotQuit(void)
{
  
  return 0;
}

int extDacNum(void)
{
shared_memory = mbuff_alloc(nome, 30);

  return 3;
}

int extDacWrite(int dac, double volts)
{


unsigned long int pippo;
unsigned long int pappa;

unsigned char t0_valueMSB ,t0_valueLSB;
unsigned char t1_valueMSB ,t1_valueLSB;




pappa=(unsigned long int)(abs(volts*10000));



if (pappa>65536) {


	pippo=(unsigned int)(131072-pappa);
	t0_valueMSB = 255;
	t0_valueLSB = 255;
	t1_valueMSB = (char)(pippo/256);
	t1_valueLSB = (char)(pippo-t1_valueMSB * 256);


	}

	else 

	{


	pippo=(unsigned int)pappa;
	t1_valueMSB = 255;
	t1_valueLSB = 255;
	t0_valueMSB = (char)(pippo/256);
	t0_valueLSB = (char)(pippo-t0_valueMSB * 256);


	}
if (pappa==0)
 
{


	pippo=(unsigned int)pappa;
	t1_valueMSB = 255;
	t1_valueLSB = 255;
	t0_valueMSB = (char)(0);
	t0_valueLSB = (char)(1);


	}


switch (dac){

	case 0:
	{
	outb(t0_valueLSB,ONX);
	outb(t0_valueMSB,ONX);
	outb(t1_valueLSB,OFFX);
	outb(t1_valueMSB,OFFX);
	if (volts>0) poutdir=(poutdir&252)|1;
	if (volts<0) poutdir=(poutdir&252)|2;
	if (volts==0) poutdir=(poutdir&252);
	outb(poutdir,POUT_DIR);
	}
	break;
	
	case 1:
	{
	outb(t0_valueLSB,ONY);
	outb(t0_valueMSB,ONY);
	outb(t1_valueLSB,OFFY);
	outb(t1_valueMSB,OFFY);
	if (volts>0) poutdir=(poutdir&243)|4;
	if (volts<0) poutdir=(poutdir&243)|8;
	if (volts==0) poutdir=(poutdir&243);
	outb(poutdir,POUT_DIR);	

	}

	break;

	case 2:
	{
	outb(t0_valueLSB,ONZ);
	outb(t0_valueMSB,ONZ);
	outb(t1_valueLSB,OFFZ);
	outb(t1_valueMSB,OFFZ);
	if (volts>0) poutdir=(poutdir&207)|16;
	if (volts<0) poutdir=(poutdir&207)|32;
	if (volts==0) poutdir=(poutdir&207);
	outb(poutdir,POUT_DIR);
	}

	break;

	}

    return 0;
}

int extDacWriteAll(int max, double * volts)
{

 extDacWrite(0, volts[0]);
 extDacWrite(1, volts[1]);
 extDacWrite(2, volts[2]);

  return 0;
}

int extEncoderSetIndexModel(unsigned int model)
{

shared_memory = mbuff_alloc(nome, 30);

  return 0;
}

int extEncoderNum(void)
{
  shared_memory = mbuff_alloc(nome, 30);
  return 2;
}

int extEncoderRead(int encoder, double * counts)
{
  *counts= shared_memory[encoder].passo;
  return 0;
}

int extEncoderReadAll(int max, double * counts)
{




    	counts[0] = (double) shared_memory[0].passo;
   	counts[1] = (double) shared_memory[1].passo;
	counts[2] = (double) shared_memory[2].passo;


  
return 0;
}

int extEncoderResetIndex(int encoder)
{

	shared_memory = mbuff_alloc(nome, 30);
  
  return 0;
}





int extEncoderReadLatch(int encoder, int * flag)
{
  *flag = 1;
  return 0;

}

int extEncoderReadLevel(int encoder, int * flag)
{
  return 0;
}

int extMaxLimitSwitchRead(int axis, int * flag)
{

  *flag = 0;
  return 0;
}

int extMinLimitSwitchRead(int axis, int * flag)
{

  *flag = 0;
  return 0;

}

int extHomeSwitchRead(int axis, int * flag)
{

  *flag = 1;
  return 0;

}

int extAmpEnable(int axis, int enable)
{
  return 0;
}

int extAmpFault(int axis, int * fault)
{
  return 0;
}

int extDioInit(const char * stuff)
{
  return 0;
}

int extDioQuit(void)
{
  return 0;
}

int extDioMaxInputs(void)
{
  return 0;
}

int extDioMaxOutputs(void)
{
  return 0;
}

int extDioRead(int index, int *value)
{
  return 0;
}

int extDioWrite(int index, int value)
{
  return 0;
}

int extDioCheck(int index, int *value)
{
  return 0;
}

int extDioByteRead(int index, unsigned char *byte)
{
  return 0;
}

int extDioShortRead(int index, unsigned short *sh)
{
  return 0;
}

int extDioWordRead(int index, unsigned int *word)
{
  return 0;
}

int extDioByteWrite(int index, unsigned char byte)
{
  return 0;
}

int extDioShortWrite(int index, unsigned short sh)
{
  return 0;
}

int extDioWordWrite(int index, unsigned int word)
{
  return 0;
}

int extDioByteCheck(int index, unsigned char *byte)
{
  return 0;
}

int extDioShortCheck(int index, unsigned short *sh)
{
  return 0;
}

int extDioWordCheck(int index, unsigned int *word)
{
  return 0;
}

int extAioInit(const char * stuff)
{
  return 0;
}

int extAioQuit(void)
{
  return 0;
}

int extAioMaxInputs(void)
{
  return 0;
}

int extAioMaxOutputs(void)
{
  return 0;
}

int extAioRead(int index, double *volts)
{
  return 0;
}

int extAioWrite(int index, double volts)
{
  return 0;
}

int extAioCheck(int index, double *volts)
{
  return 0;
}






________________________________________________________
________________________________________
_________________________________
__________________________-
____________________
_____________
_______
_
_




i have modify installrtlinuxbase:


#!/bin/sh


rev=`uname -r`

# This is for rtlinux09J the file is not expected to exist for rtlinux_2_0

# Install RT-Linux scheduler module, if it's not installed
if ! /sbin/lsmod | grep rtl_sched 1> /dev/null 2> /dev/null ; then
  if test -f /usr/src/rtl/modules/rtl_sched 1> /dev/null 2> /dev/null ; then
    echo /sbin/insmod -f /usr/src/rtl/modules/rtl_sched
    /sbin/insmod -f /usr/src/rtl/modules/rtl_sched
  fi
fi

#
# This is for rtlinux-2_3 the file is not expected to exist for rtlinux_2_0
# or rtlinux_2_2
#

#
# Install RT-Linux core module, if it is  not installed check to see
# if it exists.
# added by terrylr 16 oct 2000
#
if ! /sbin/lsmod | grep -v rtl_ | grep rtl 1> /dev/null 2> /dev/null ; then
  if test -f /lib/modules/$rev/misc/rtl.o 1> /dev/null 2> /dev/null ; then
    echo /sbin/insmod -f /lib/modules/$rev/misc/rtl.o
    /sbin/insmod -f /lib/modules/$rev/misc/rtl.o
  fi
fi

# The rest are for rtlinux_2_0, the files will not be there for rtlinux_09J

# Install RT-Linux mbuff  module, if it's not installed
if ! /sbin/lsmod | grep mbuff 1> /dev/null 2> /dev/null ; then
  if test -f /lib/modules/$rev/misc/mbuff.o 1> /dev/null 2> /dev/null ; then
    echo /sbin/insmod -f /lib/modules/$rev/misc/mbuff.o
    /sbin/insmod -f /lib/modules/$rev/misc/mbuff.o
  fi
fi

# Install RT-Linux time  module, if it's not installed
if ! /sbin/lsmod | grep rtl_time 1> /dev/null 2> /dev/null ; then
  if test -f /lib/modules/$rev/misc/rtl_time.o 1> /dev/null 2> /dev/null ; then
    echo /sbin/insmod -f /lib/modules/$rev/misc/rtl_time.o
    /sbin/insmod -f /lib/modules/$rev/misc/rtl_time.o
  fi
fi

# Install RT-Linux sched  module, if it's not installed
if ! /sbin/lsmod | grep rtl_sched 1> /dev/null 2> /dev/null ; then
  if test -f /lib/modules/$rev/misc/rtl_sched.o 1> /dev/null 2> /dev/null ; then
    echo /sbin/insmod -f /lib/modules/$rev/misc/rtl_sched.o
    /sbin/insmod -f /lib/modules/$rev/misc/rtl_sched.o
  fi
fi

# Install RT-Linux posixio  module, if it's not installed
if ! /sbin/lsmod | grep rtl_posixio 1> /dev/null 2> /dev/null ; then
  if test -f /lib/modules/$rev/misc/rtl_posixio.o 1> /dev/null 2> /dev/null ; then
    echo /sbin/insmod -f /lib/modules/$rev/misc/rtl_posixio.o
    /sbin/insmod -f /lib/modules/$rev/misc/rtl_posixio.o
  fi
fi

# Install RT-Linux fifo  module, if it's not installed
if ! /sbin/lsmod | grep rtl_fifo 1> /dev/null 2> /dev/null ; then
  if test -f /lib/modules/$rev/misc/rtl_fifo.o 1> /dev/null 2> /dev/null ; then
    echo /sbin/insmod -f /lib/modules/$rev/misc/rtl_fifo.o
    /sbin/insmod -f /lib/modules/$rev/misc/rtl_fifo.o
  fi
fi

    echo /sbin/insmod -f /usr/rtlinux-3.0/examples/prove/encxyz.o
    /sbin/insmod -f /usr/rtlinux-3.0/examples/prove/encxyz.o   



exit 0


__________________________________-
______________________
_____________
_______
_




I use a PC 255Mhz with 32 Mb ram a Svga and eth card and It's work very well!!!!!!!!!!!!


So thank you very much for your good EMC!

If you think that my system can be useful i'm happy to mail more doc about this!




						Best regards
						
						Spezia Raffaele Antonio
						


P.S. Excuse me for my bad english...and for my mistakes but are several yaers thet i don't write in english,
 and i now only 20 words!!!




I have 3 question:

When i use this system with a low rotation of encoder (500 - 600 rpm ) its all work very well , but why while the 
enkcapture routine can read very fast rotation of encoder emc interface have problem to display the step?

Make I the rigth thing when i use shared_memory to exacnge the step encoder position?

It's possible make a prg in rtlinux to generate pulse for pwm to pilot directli the h-bridge motor driver?

My personal goal is to make a motion control with a low number of componets that is possible .
 And i think that this can be useful!



Date Index | Thread Index | Back to archive index | Back to Mailing List Page

Problems or questions? Contact