[HECHO] espectroduino, automatizacion de espectrometro.

Todo cuanto tiene que ver con la obtención, almacenamiento y proceso de la información digital, sus aplicaciones y el software y hardware utilizado.
Mensaje
Autor
Avatar de Usuario
baldo
Mensajes: 1514
Registrado: Vie Dic 23, 2005 7:54 pm
País: españa
Ciudad: coruña y madrid
Ubicación: Galicia
Contactar:

[HECHO] espectroduino, automatizacion de espectrometro.

#1 Mensaje por baldo »

tenia el profe un espectrometro viejo, que queria automatizar.

Hard: motor paso a paso, lectura del detector, y dos finales de carrera, el de cero muy curioso, el micro contacto alimenta al diodo IR, de forma que la muesca en el disco al eje, detectada por el foto diodo, clava la posicion, aumenta la precision del microcontacto.

se pudo haber hecho un programilla que a golpe de pulsador se resetease y enviase un espectro, pero no tendria opciones.

y entonces me lie de mala manera, demasiado para lo que se necesitaba.
Si queremos atender a la vez: el puerto de comunicaciones, el motor, y la lectura,,,, no queda otra que usar interrupciones para los 3.

la cosa resulto bastante enorme, como tal espectrometro no creo que interese a nadie, pero por trocitos si.
de todas formas podeis simular su funcionamiento, 4 leds en vez de motor, dos pulsadores como finales carrera, y tocais con el dedito para simular la lectura.

Avatar de Usuario
baldo
Mensajes: 1514
Registrado: Vie Dic 23, 2005 7:54 pm
País: españa
Ciudad: coruña y madrid
Ubicación: Galicia
Contactar:

Re: [HECHO] espectroduino, automatizacion de espectrometro.

#2 Mensaje por baldo »

test7.ino

Código: Seleccionar todo

//aqui poner cualquier tonteria, 
//
//el .ino lo usa el entorno arduino para arrancar el proyecto. 
//
//el arduino es para niños
//el wiring  es para niños pequeños
//los hombres usamos c
pues eso, yo no uso wiring, me parece una kk, es lento como vimos en la flecha del anajesusa, sentencias potentes a costa de perder flexibilidad, memoria, y rapidez.

parece que el IDE necesita una carpeta unica, llamada como el proyecto, dentro lo demas, Y EL .ino. da igual lo que ponga, pero que ponga algo.

Avatar de Usuario
baldo
Mensajes: 1514
Registrado: Vie Dic 23, 2005 7:54 pm
País: españa
Ciudad: coruña y madrid
Ubicación: Galicia
Contactar:

Re: [HECHO] espectroduino, automatizacion de espectrometro.

#3 Mensaje por baldo »

MAIN.c

Código: Seleccionar todo

#include <avr/io.h>
#include <string.h>
#include "usart2.h"
#include "interprete.h"    //
#include "salto.h"    //
#include "motor.h"    //
#include "adc2.h"    //
#include "landas.h"    //


int	main(void){
	SerialInit();
	TXdirec_s("test de TXdirec_s.  ");
	TX_s_n("type h para help ");
	MotorReset();	
	LandaReset();	
	ADCInit();
	
	while (1){
		if (RXstatus==1){
			if(eco){
				strcpy(bufTX,bufRX);
				TXLanza();
				while(bitRead(UCSR0B,UDRIE0)){}         //espera a terminar, hasta no interrupcion
				}
			Interprete(bufRX);
			RXReset();
			}
		if(RXerror){TXdirec_s("* * * ERROR EN RX ");TXdirec(RXerror);	TXdirec_s(" \n"); RXerror=0;}
		if(TXerror){TXdirec_s("* * * ERROR EN TX ");TXdirec(TXerror);	TXdirec_s(" \n"); TXerror=0;}
		if(motorerror=='E'){	MotorTexto(3);	motorerror=0;}//FC inesperado
		if(motorerror){			TX_s(str[1].str);	TX(motorerror);	TX('\n'); motorerror=0;}
		}
	}

esta es la main, el bucle principal que lo controla todo,
los includes,
las inicializaciones de todo, (el setup() de arduino), usart, motor, lector.

entra en bucle, si recibio un parrafo (RXstatus==1) si esta en eco lo reenvia,
lo pasa al interprete, (y alli,,,,)
lo borra,
si hay errores los canta.

Avatar de Usuario
baldo
Mensajes: 1514
Registrado: Vie Dic 23, 2005 7:54 pm
País: españa
Ciudad: coruña y madrid
Ubicación: Galicia
Contactar:

Re: [HECHO] espectroduino, automatizacion de espectrometro.

#4 Mensaje por baldo »

usart2.h

Código: Seleccionar todo

#ifndef usart2    
#define usart2

#ifndef Arduino_h      //para compatib AVStudio
#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
#define bitXor(value, bit) ((value) ^= (1UL << (bit)))
#endif

#define UBRRn 103 				// 16MHz, 9600 BAUD rate
#define BUF_SIZE 50
//#define PINLED 0x20 //del puerto  B, en placa D13  //ESTA ES LA  MASCARA, no el nº de bit
#define PINLED 5 				//del puerto  B, en placa D13

char	bufRX[BUF_SIZE+3];  	//le da un poco mas de bufer, porsi
char	*ptrRXfin;
char	*ptrRXin;
char	*ptrRXout;
char	volatile  RXstatus;		//EL STATUS ES LO QUE HAY QUE MIRAR POR SI LLEGO PARRAFO
char	volatile  RXerror;	 	//volatiles porque pas puede cambiar interrupcion
char	volatile  RXllegoc;

char	bufTX[BUF_SIZE+3];
char	*ptrTXfin;
char	*ptrTXin;
char	*ptrTXout;
char	volatile  TXstatus;
char	volatile  TXerror;


void	SerialInit(void);
void	RXReset(void);
void	TXReset(void);
char	RXBuferMete(char c);
char	RXBuferMete_s(char *s);
char	RXBuferSaca(void);

char	TXuferMete(char c);
char	TXuferMete_s(char *s);
char	TX(char c);				//ABREVIACION DE BUFER METER c// ESTAS SON LAS QUE HAY QUE USAR, 
char	TX_s(char *s);			//ABREVIACION DE BUFER METER s
char	TX_s_n(char *s);		//ABREVIACION DE BUFER METER s, + salto linea
char	TXBuferSaca(void);

void	TXLanza(void);			//una vez lleno el bufer TX, lo lanza, mediante interrupciones
char	TXLanzaTest(void);
void	TXLanzaEspera(void);	//ESPERA A TERMINAR

void	TXdirec(char dato);			//ENVIA DATO A CAÑON //USADO EN DEBUG 
void	TXdirec_s(char *s);			//ENVIA PARRAFO, por libre, no bufer

//ISR(USART_RX_vect);
//ISR(USART_UDRE_vect);

#endif

usart2.c

Código: Seleccionar todo

#include <avr/io.h>
#include <avr/interrupt.h>
#include "usart2.h"

void	SerialInit(void) {							//INICIO DE USART
	UBRR0H = (unsigned char)(UBRRn>>8);		UBRR0L = (unsigned char)UBRRn;	//baudios

	DDRD |= (1<<DDD3);	//puerto out
	UCSR0B = (1<<RXEN0) | (1<<TXEN0);
	UCSR0C = (1<<USBS0) | (3<<UCSZ00);
	
	cli();
	UCSR0B |= (1<<RXCIE0);// | (1<<UDRIE0);// | (1<<TXCIE0);
	sei();

	ptrRXfin=bufRX + BUF_SIZE;					//puntero fin, usado para ver si se desmadro
	ptrTXfin=bufTX + BUF_SIZE;					//se pone aqui para ahorrar tiempo en resets
	RXReset();		TXReset();					//reset de variables
	}
//-------------------	
void	RXReset(void) {							//RX reset
	ptrRXin=bufRX;		ptrRXout=bufRX;			//punteros de meter y sacar a inicio
	*ptrRXin=0;									//pone 0 como marca de final
	RXstatus=0;			RXerror=0;				//status y error a 0
//	RXllegoc=0;									//usado en interrup motor  para parar 
	}
void	TXReset(void) {							//TX reset
	ptrTXin=bufTX;		ptrTXout=bufTX;			//lo mismo
	*ptrTXin=0;
	TXstatus=0;			TXerror=0;
	}
//-------------------	
char	RXBuferMete(char c){					//METE UN c EN EL BUFER
	if(ptrRXfin<ptrRXin){						//si se desmadro
		RXReset();		RXerror='1';	return(RXstatus);
		}										//lo resetea, y marca error
	switch(c){									//segun lo que llegue
		case 0:		case '\n':		case '\r':	//si 0 cr lf 
					if(ptrRXin==bufRX){			//si no habia nada en el bufer
						RXstatus=0;	return(RXstatus);	//lo ignora, seguramente un cr y lf 
						}
					RXstatus=1;					//fin de parrafo, lo marca. 
					break;
		default:	RXstatus=0;					// caracter normal,
					*ptrRXin=c;	ptrRXin++;	*ptrRXin=0; //pone, incrementa, y marca final
					break;
		}	
	return(RXstatus);							//retorna el status. 
	}
char	RXBuferMete_s(char *s){					//METE UN PARRAFO EN BUFER
	while(*s){RXBuferMete(*s);   s++;}
	return(RXstatus);
	}
char	RXBuferSaca(void){						//SACA DEL BUFER
	if(ptrRXfin<ptrRXin){						//si se desmadra leyendo
		RXReset();		RXerror='2';	return(0);	//lo resetea, marca error, sale diciendo que termino
		}
	char c=*ptrRXout;							//lee segun puntero out
	ptrRXout++;									//incrementa puntero
	return(c);									//reorna caracter
}
//-------------------	
char	TXBuferMete(char c){					//METE UN c EN EL BUFER //   S I   \n   L A N Z A   A U T O M A T I C O
  TXLanzaEspera();                  	    //SI ESTA LANZANDO, ESPERA
	if(ptrTXfin<ptrTXin){									//lo mismo que arriba,,,,
		TXReset();		TXerror='1';	return(TXstatus);
		}
	switch(c){
		case 0:		break;				//aqui distinto arriba, si entra 0 lo ignora
		case '\n':		case '\r':
					if(ptrTXin==bufTX){
						TXstatus=0;	return(TXstatus);
						}
					TXstatus=1;
					TXLanza();			// S I   L L E N A   L O   L A N Z A 
					break;
		default:	TXstatus=0;
					*ptrTXin=c;		ptrTXin++;		*ptrTXin=0;
					break;
		}	
	return(TXstatus);
	}
char	TXBuferMete_s(char *s){
	while(*s){TX(*s);   s++;}
	return(TXstatus);
	}
char	TXBuferSaca(void){
	if(ptrTXfin<ptrTXin){	
		TXReset();		TXerror='2';	return(0);
		}
	char c=*ptrTXout;
	ptrTXout++;
	return(c);
	}

//-------------------	
void	TXLanza(void){										//INICIA SALIDA DEL TX  
	TXLanzaEspera();
	while(!bitRead(UCSR0A,UDRE0)){   }   					//espera a libre
	UDR0 = TXBuferSaca();									// a usart lo que lee
	UCSR0B |= (1<<UDRIE0);									//enabla interrupcion de registro de salida libre
	}
char	TXLanzaTest(void){									//PREGUNTA SI AUN ACTIVA
	return(bitRead(UCSR0B,UDRIE0));         				//pregunta si aun interrupcion
	}
void	TXLanzaEspera(void){								//ESPERA A TERMINAR
	while(TXLanzaTest()) {}       							//pregunta si aun interrupcion
	}
//-------------------	
char	TX(char c){											//ABREVIACION DE BUFER METER c
	TXBuferMete(c);
	}
char	TX_s(char *s){										//ABREVIACION DE BUFER METER s
	TXBuferMete_s(s);
	return(TXstatus);
	}
char	TX_s_n(char *s){									//ABREVIACION DE BUFER METER s, + salto de linea
	TXBuferMete_s(s);
	TXBuferMete('\n');
	return(TXstatus);
	}
//-------------------	
//-------------------										// U S A D O   E N   D E B U G  
void	TXdirec(char dato){         						//ENVIA DATO A CAÑON, sin interrupciones ni bufer
	while(!bitRead(UCSR0A,UDRE0)){   }  					//espera a libre
	UDR0 = dato;
	}
void  TXdirec_s(char *s){         							//ENVIA PARRAFO, por libre, no bufer
	while(*s){TXdirec(*s);   s++;}
	}   

//-------------------	
//-------------------	
ISR(USART_RX_vect) {										//RUTINA DE INTERRUPCION DE RECEPCION
	RXBuferMete(UDR0);										//mete en bufer lo que llega
	RXllegoc++;												//USADO PARA PARAR MOTOR
	}

ISR(USART_UDRE_vect) {										//RUTINA DE INTERRUPCION DE REGISTRO LIBRE
	unsigned char c;	// M I R A R   L A   I N T   D A T O   E N V I A D O , esta tiene = prioridad que TXdirec(), no interesa
	c=TXBuferSaca();										//saca del bufer
	switch(c){												//segun lo que sea
		case 0:		case '\n':		case '\r':				//si es algun final
					UDR0 = '\n';							//envia un salto de linea
					UCSR0B ^= (1<<UDRIE0);					//inhabilita la interrupcion
					TXReset();								//resetea el bufer
					break;
		default:	
					UDR0 = c;								// si es c normal, lo envia. 
					break;
		}	
	}   
	
lo 1º es comunicarse.
la gestion se hace por parrafos, no letrita a letrita,
letrita que llega, salta la interrupcion, y alli se encarga de ponerla en un bufer,
si llega un final, un caracter '\n', o '\r', levanta bandera de RXstatus que ya vimos, que indica parrafo listo para gestionar.
dependiendo los equipos, o llega "nueva linea", o "carri return", o los dos, lo que complica algo la cosa.

ES POR ESTO QUE DESDE LA CONSOLA DE ARDUINO HAY QUE SELECIONAR, \n COMO FINAL DE PARRAFO. (abajo derecha)

para emitir tambien, bufer,,, y \n, para decirle que ya lo puede enviar (con su interrupcio).

ademas de este metodo, contaba con otro que lanza a cañon sin interrupciones, el TXdirec(), esto lo use para depurar el metodo de interrupciones, y siempre viene bien tenerlo porsi,

cuando queremos transmitir, se escribe en una memoria, y el hard lo envia, si aun envia el anterior tiene que esperar, hay dos interrupciones, enviado y memoria libre, ahora mismo no se cual use, en otros micros esto me calento cabeza, no iba como dicen, la idea es que TXdirect tenga preferencia, pero me entran dudas.

Avatar de Usuario
baldo
Mensajes: 1514
Registrado: Vie Dic 23, 2005 7:54 pm
País: españa
Ciudad: coruña y madrid
Ubicación: Galicia
Contactar:

Re: [HECHO] espectroduino, automatizacion de espectrometro.

#5 Mensaje por baldo »

interprete.h

Código: Seleccionar todo

#ifndef interprete
#define interprete

#define	coman_ancho 16		// A Q U I   S E   D E F I N E   E L   A N C H O   D E   P A R R A F O   P A T R O N

//	typedef void (*pf)(void);	//void  *(pf) (void); ASI NO	
//	static 	pf tabsal[2];		//ejemplo sencillo
	typedef struct {			//plantilla de un renglon de la tabla de saltos
		char coman[coman_ancho];//comando en prosa	
		void (*pf)(void);		//puntero a la funcion	
		}saltos_InitTypeDef;	//nombre de la plantilla

		
	char 	*patron_ptr;		//puntero a parrafo patron
	char	k;					//numero de parrafo patron
	char	n;					//numero de letra
	char	c;					//letra de entrada comparando
	char	p;					//letra del patron
	
	char 	Interprete(char *s);		//en s el string a comparar, ret 1 si encontro, 0 no
//	static 	void 	Ejemplo(void);	//P O N E R   S T A T I C,   O   L O C U R A //en SMT32, en arduino parece que no haace falta
	char 	InterpreteBuscar(char *s);

	//-------------------	

char	bd[6];		//resultado de chart o int a asci decimal
char	hexa[5];	//resultado de chart o int a asci hexadecimal
int 	di;			//resultado de decimal a int

char*	ByteDeci_cc(char ch,char cl);   //PASA 2 CHAR A 5 DECI
char*	ByteDeci_i(int i);      //PASA 1 INT A 5 DECI
char*	IntDeci(int i);      //PASA 1 INT A 5 DECI  //lo mismo de arriba con otro nombre
int		DeciInt(char c4,char c3,char c2,char c1,char c0);   //PASA 5 CHAR A INT
char	DeciInt2(unsigned char c);  
char	NibleHexa(char ni);
char*	CharHexa(char he);
char*	IntHexa(int in);

#endif

interprete.c

Código: Seleccionar todo

/**********************************************/
/*   I N T E R P R E T E   C O M A N D O S    */

#include "interprete.h"		//
#include "salto.h"		//
#include "usart2.h"

#include "saltostabla.c"   //  S I ,   S E   I N C L U D E   U N   . C ,,,, bueno,,, en fin,,,

//-------------------	
//-------------------	
char 	Interprete(char *s){		// E N   * s   A P U N T A   A   P A R R A F O   A   C O M P A R A R
	char ret=InterpreteBuscar(s);
	if(ret){
		tabsal[k].pf();//DISPARA,  ASI, O NO VA	
		}
	else	{TX_s("COMANDO MAL, type h para help \n");	}
	return(ret);//
	}
//	@=comodin,	$=signo {+, -,' '}	%=decimal	#=hexade	|=fin obligado
char 	InterpreteBuscar(char *s){		//en *s el parrafo a comparar
	char *patron_ptr;				//DEVUELVE 0=FRACASO, 1=ENCONTRO CADENA
	k=0;						//1' parrafo
	while(1){
		n=0; 					//1' letra
		patron_ptr=tabsal[k].coman; 		//puntero a tabla saltos[k]
		while(1){				//
			c=*(s+n);			//c=letra comparar, matrices lentas
			p=*(patron_ptr+n);		//letra del patron
			n++;				//apunta a siguiente
			if(p==0){	if(n==1){	return(0);}  //acabo candidatos
					else{		return(1);}} //termino, OK
		//	if(p=='|'){	if(c!='\r'){	break;}	//no fin obligado  //version original co \r como final
			if(p=='|'){	if(c!=0){	break;}	//no fin obligado	
					else{		return(1);}}//sale por coincidir con final obligado
			if(p=='@'){	continue;} 	//llego COMODIN, a por otra letra
			if(p=='$'){			//tiene que llegar un SIGNO
				if(c==' '){continue;}	//llego ' ' 
				if(c=='-'){continue;}	//llego -
				if(c=='+'){continue;}	//llego +
				}
			if(p=='%'){			//tiene que llegar un DECIMAL
				if(c<'0'){break;}	//menor que 0, no vale
				if(c>'9'){break;}	//mallor que 9, no vale
				continue;		//lo que queda vale
				}
			if(p=='#'){			//tiene que llegar un HEXADE
				if((c>='0')&(c<='9')){continue;} //entran numeros
				if((c>='A')&(c<='F')){continue;} //entran A,,F
				if((c>='a')&(c<='f')){continue;} //entran a,,f
				}
						
			if(p!=c){	break;}		//no coincide, a por otro parrafo
			if(!c){		break;}		//fin llave
				
			}//fin de bucle, entonces es que coinciden letras, a por otra	
		k++;	//termino el patron, no salto, a por otro parrafo
		}
	}

	
//-------------------	
//-------------------	
char*   ByteDeci_cc(char ch,char cl){   //PASA 2 CHAR A 5 DECI
	unsigned char c0,c1,c2,c3,c4;
	c0=cl&0x0F;   c1=cl&0xF0;   c1=c1>>4;
	c2=ch&0x0F;   c3=ch&0xF0;   c3=c3>>4;//miro y corrijo desmadre
	c0+=6*c1;   while(c0>9){   c0-=10; c1++;}   c0+=6*(c2+c3);   
	c1+=5*c2 + 9*c3;   c2*=2;      c3*=4;   c4=0x00;      
	while(c0>9){   c0-=10; c1++;}   c0+=0x30;//+0x30 para tener el ascii   
	while(c1>9){   c1-=10; c2++;}   c1+=0x30;      
	while(c2>9){   c2-=10; c3++;}   c2+=0x30;   
	while(c3>9){   c3-=10; c4++;}   c3+=0x30;   c4+=0x30;   
	bd[0]=c4;	bd[1]=c3;	bd[2]=c2;	bd[3]=c1;	bd[4]=c0; bd[5]=0;	
	return(&bd);										//devuelve la direcion de la conversion
	}

char*   ByteDeci_i(int i){      //PASA 1 INT A 5 DECI
	ByteDeci_cc((char)((i>>8)&0x00FF),(char) (i&0x00FF));
	return(&bd);										//devuelve la direcion de la conversion
	}
char*   IntDeci(int i){      //PASA 1 INT A 5 DECI  //lo mismo de arriba con otro nombre
	ByteDeci_cc((char)((i>>8)&0x00FF),(char) (i&0x00FF));
	return(&bd);										//devuelve la direcion de la conversion
	}
//-------------------	
int   DeciInt(char c4,char c3,char c2,char c1,char c0){   //PASA 5 CHAR A INT
	c4=DeciInt2(c4);	c3=DeciInt2(c3);	c2=DeciInt2(c2);	c1=DeciInt2(c1);	c0=DeciInt2(c0);
	di=c0 + (c1*10) + (c2*100) + (c3*1000) + (c4*10000);
	return(di);
	}
char   DeciInt2(unsigned char c){  
	c=c-0x30; if(c>9){c=9;}
	return(c);
	}
//-------------------  
char   NibleHexa(char ni){								//un nible lo pasa a ascii
	char c;
	ni=ni&0x0F;
	c=(ni+0x30);	if(c>0x39){c+=6;}
	return(c);											//return el ascii
	}

char*   CharHexa(char he){								//un char lo pasa a 2 ascii
	char c;
	c=he&0xF0;	c=c>>4;	hexa[0]=NibleHexa(c);
	c=he&0x0F;			hexa[1]=NibleHexa(c);
	hexa[2]=0;
	return(&hexa);										//devuelve la direcion de la conversion
	}
char*   IntHexa(int in){								//un int lo pasa a 4 ascii
	int i;
	i=in&0xF000;	i=i>>12;	hexa[0]=NibleHexa((char)i);
	i=in&0x0F00;	i=i>>8; 	hexa[1]=NibleHexa((char)i);
	i=in&0x00F0;	i=i>>4; 	hexa[2]=NibleHexa((char)i);
	i=in&0x000F;	    		hexa[3]=NibleHexa((char)i);
	hexa[4]=0;
	return(&hexa);										//devuelve la direcion de la conversion
	}

Despues de recibir parrafo, lo interpreta.
para eso este motorcillo interprete,
compara letrita a letrita del bufer de entrada con una tabla que veremos.
si coinciden todas debe de ser eso, y si no canta "mal comando".
hay comodines, para meter numeros, y signos,
y otro para forzar final, por ejemplo, hay comando "h" y "h2", escribes h2 y se cuela en el h, que es lo 1º que cumple.

tambien aqui un interprete de ascii a bytes, y al reves.

Avatar de Usuario
baldo
Mensajes: 1514
Registrado: Vie Dic 23, 2005 7:54 pm
País: españa
Ciudad: coruña y madrid
Ubicación: Galicia
Contactar:

Re: [HECHO] espectroduino, automatizacion de espectrometro.

#6 Mensaje por baldo »

salto.h

Código: Seleccionar todo

#ifndef salto	
#define salto

#ifndef Arduino_h      //para compatib AVStudio
#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
#define bitXor(value, bit) ((value) ^= (1UL << (bit)))
#endif

char 	eco;

void	SaltoLed0(void);
void	SaltoLed1(void);
void	SaltoLedx(void);

void	SaltoEco0(void);
void	SaltoEco1(void);

void	SaltoH(void);

void	SaltoPredefVer(void);
void	SaltoPredefinido(void);		//"predefinido %",

void	SaltoRetardo(void);			//"retardo %"
void	SaltoRetardoRap(void);		//"retardo rap %"
void	SaltoPasos_lectura(void);	//"pasos_lectura %%%"
void	SaltoNlecturas(void);		//"nlecturas %%"
void	SaltoCotah(void);			//"cotah %%%%%"
void	SaltoCotal(void);			//"cotal %%%%%"

void	SaltoPortCLeer(void);
void	SaltoMotorReset(void);
void	SaltoMotorPotencia(void);
void	SaltoMotorSube(void);
void	SaltoMotorBaja(void);
void	SaltoMotorSubeN(void);
void	SaltoMotorBajaN(void);
void	SaltoMotorAparca1(void);
void	SaltoMotorACotaA(void);
void	SaltoMotorACotaB(void);
void 	SaltoMotorTestCarrera(void);
void 	SaltoMotorEspectro1(void);

void	Debug1(void);			//
void	Debug2(void);			//

#endif
saltostabla.c

Código: Seleccionar todo

#include "interprete.h"    //
#include "salto.h"    //
#include "landas.h"   //

typedef void (*fptr) (void); 	//define una funcion generica, entra void, sale void.
					
//	static 	pf tabsal[2]={		//del ejemplo sencillo
	static 	saltos_InitTypeDef tabsal[]={
//    #include "tabla.txt"    //!!! INCLUDE UN .TXT  //arruino = KK, no deja include un .txt
//#define  coman_ancho 20  O J O con el ancho, esta en el .h
//  @=comodin,  $=signo {+, -,' '}  %=decimal #=hexade  |=fin obligado
//  "comando ",   Salto.,
//  "012345678901234"  !       O J O con el ancho, tampoco pasarse, come mucha ram
//-------------------	
    "led 1",			SaltoLed1,  //con o sin &
    "led 0",			SaltoLed0,
    "led x",			SaltoLedx,
	
    "eco 1",			SaltoEco1,
    "eco 0",			SaltoEco0,
	
	"h2",				SaltoH,

	"predef ver",   	SaltoPredefVer,
	"predefinido %",	SaltoPredefinido,
	
	"retardo %",		SaltoRetardo,
	"retardo rap %",	SaltoRetardoRap,
	"pasos/lect %%%",	SaltoPasos_lectura,
	"cotah %%%%%",		SaltoCotah,
	"cotal %%%%%",		SaltoCotal,
	"debug 1",			Debug1,
	"debug 2",			Debug2,
	
	"reset",			SaltoMotorReset,
	"potencia %",		SaltoMotorPotencia,
	"sube|",			SaltoMotorSube,
	"baja|",			SaltoMotorBaja,
	"sube %%%%",		SaltoMotorSubeN,
	"baja %%%%",		SaltoMotorBajaN,
	"aparca1",			SaltoMotorAparca1,
	"a cota baja",		SaltoMotorACotaB,
	"a cota alta",		SaltoMotorACotaA,
	"test carrera",		SaltoMotorTestCarrera,
	"espectro1",		SaltoMotorEspectro1,
//-------------------		usando landas
	"h|",				LandaHelp,
	"espectro",			LandaEspectro,
	"aparca",			LandaAparca,
	"landal %%%%",		LandaBaja,
	"landah %%%%",		LandaAlta,
	"ir a %%%%",		LandaIrA,
	"dump",				LandaDumpParametros,

		"",	0,//DEJAR SIEMPRE, MARCA EL FINAL !!!!
		};

como veis hay dos columnas, la izquierda son los parrafos a comparar, y derecha, la funcion asociada, que la dispara el propio interprete.

Me hubiese gustado ponerlo como un .txt sin mas historias por arriba, asi lo hice en el c++ de los STMs, mas limpio mas elegante, con el ardu no pude/supe.

LA tabla TERMINA como veis, es la marca de final, y hay que dejarla,
En ningun lado hay que decir cuantas lineas tiene, (ventaja).
pero cada parrafo tiene ancho fijo, no os paseis o machacais al vecino, y entonces lio.
tampoco pasarse de generosos, porque esto come memoria.

salto.c

Código: Seleccionar todo

#include <avr/io.h>
#include "usart2.h"
#include "salto.h"		//
#include "interprete.h"		//
#include "motor.h"		//
#include "help.h"		//

void	SaltoLed0(void){	bitClear(PORTB, PINLED);	TX_s("Led a 0\n");	}
void	SaltoLed1(void){	bitSet  (PORTB, PINLED);	TX_s("Led a 1\n");	}
void	SaltoLedx(void){	bitXor  (PORTB, PINLED);	TX_s("Led inv\n");	}

void	SaltoEco0(void){	eco=0;	TX_s("Eco 0\n");	}
void	SaltoEco1(void){	eco=1;  TX_s("Eco 1\n");	}

void	SaltoH(void){				TX_s_PGM(); }		//vuelca help

void	SaltoPredefVer(void){		DumpPredefinidos();	}
void	SaltoPredefinido(void){		CargaParametros(DeciInt('0','0','0','0',bufRX[12]));					DumpParametros();}	//"predefinido %",

void	SaltoRetardo(void){			motorretardo=	DeciInt('0','0','0','0',bufRX[8]);						DumpParametros();}	//"retardo %"
void	SaltoRetardoRap(void){		motorretardorap=DeciInt('0','0','0','0',bufRX[12]);						DumpParametros();}	//"retardo %"
void	SaltoPasos_lectura(void){	pasos_lectura=	DeciInt('0','0',bufRX[11],bufRX[12],bufRX[13]);			DumpParametros();}	//"pasos_lectura %%%"
void	SaltoCotah(void){			cotah=			DeciInt(bufRX[6],bufRX[7],bufRX[8],bufRX[9],bufRX[10]);	DumpParametros();}	//"cotah %%%%%"
void	SaltoCotal(void){			cotal=			DeciInt(bufRX[6],bufRX[7],bufRX[8],bufRX[9],bufRX[10]);	DumpParametros();}	//"cotal %%%%%"

void	SaltoMotorReset(void){		MotorReset();	}
void	SaltoMotorPotencia(void){	motorpotencia=	(char)DeciInt('0','0','0','0',bufRX[9]);				DumpParametros();}
void	SaltoMotorSube(void){		MotorSube();	}
void	SaltoMotorBaja(void){		MotorBaja();	}
void	SaltoMotorSubeN(void){		MotorSubeN(		DeciInt('0',bufRX[5],bufRX[6],bufRX[7],bufRX[8]));}
void	SaltoMotorBajaN(void){		MotorBajaN(		DeciInt('0',bufRX[5],bufRX[6],bufRX[7],bufRX[8]));}
void	SaltoMotorAparca1(void){	MotorAparca();	}			
void	SaltoMotorACotaB(void){		MotorA(cotal);	}
void	SaltoMotorACotaA(void){		MotorA(cotah);	}
void 	SaltoMotorTestCarrera(void){MotorTestCarrera();	}
void 	SaltoMotorEspectro1(void){	MotorEspectro();}
y estos son algunos saltos, que incluso interpretan numeros desde el bufer

Avatar de Usuario
baldo
Mensajes: 1514
Registrado: Vie Dic 23, 2005 7:54 pm
País: españa
Ciudad: coruña y madrid
Ubicación: Galicia
Contactar:

Re: [HECHO] espectroduino, automatizacion de espectrometro.

#7 Mensaje por baldo »

motor.h

Código: Seleccionar todo

#ifndef motor	
#define motor

#ifndef Arduino_h      //para compatib AVStudio
#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
#define bitXor(value, bit) ((value) ^= (1UL << (bit)))
#endif

#define MOTORMASCARA   	0xF0 //del puerto  B, en placa marcado de D8,,,11,  a 0s los cables motor
#define PINLED   		5 //del puerto  B, en placa D13


#define FCMASCARA		3
#define PINFINBAJO     	1 //del puerto  C, en placa A0
#define PINFINALTO   	2 //del puerto  C, en placa A1
#define PINFINADC   	3 //del puerto  C, en placa A2

#define MOTORPARAR   	0
#define MOTORNADA   	1
#define MOTORSALIRFC   	2
#define MOTORSUBIR   	3
#define MOTORBAJAR   	4
#define MOTORSUBIRN   	5
#define MOTORBAJARN   	6
#define MOTORAPARCA   	7
#define MOTORA      	8
#define MOTORHASTA   	9
#define MOTORTESTCARR  10
#define MOTORESPECTRO  11
#define MOTORESPECTRO2 12

typedef struct {			//plantilla de string 
	char str[32];
	}str_TypeDef;
static 	str_TypeDef str[]={
//	"123456789012345678901234567890"
	"ANTES APARCAR",
	"UN ERROR O ABORTO",
	"enviar algo para parar",
	"FCx inesperado",
	};

int 	pasos_lectura;    //
int 	nlecturas;      //

int 	cotah;
int 	cotal;

//char potencia; char motorretardo; char motorretardorap; int pasos_lectura; int cotah; int cotal;
typedef struct {			//plantilla de parametros 
		char 	potencia;
		char 	retardorap;			//
		char 	retardo;			//
		int 	cotal;
		int 	cotah;
		int 	pasos_lectura;		//
		}parametros_TypeDef;	//nombre de la plantilla

char	volatile	motorproceso;
char	motoraparco;
char	motorasalirfc;

char	motorcosahacer;
char	motorcosahacerbak;
char	PINCbak;
char	motorFCx;		//fin carrera, alguno de los dos
char	motorFCA;		//fin carrera ALTO
char	motorFCB;		//fin carrera BAJO
char	motorretardo;
char	motorretardorap;
char	motorerror;
char	trace;
char	trace2;

char	motorpotencia;
char	motorpalabra0;	// asi mas rapido que con matrices						
char	motorpalabra1;							
char	motorpalabra2;							
char	motorpalabra3;							

char	motorruleta;
unsigned int	motorpaso;

int 	motorcuentaatras;
int 	cota;

void	DumpParametros(void);
void	CargaParametros(char n);

void	PortCLeer(void);
void	MotorReset(void);
void	MotorPotencia(char pot);
void	MotorSube(void);
void	MotorBaja(void);
void	MotorSubeN(int n);
void	MotorBajaN(int n);
void	MotorAparca(void);
void	MotorA(int posicion);
void	MotorHasta(int posicion);
int 	MotorTestCarrera(void);
void 	MotorEspectro(void);
void	MotorComunFinal(char cosa, char retar);
void	MotorDescansa(char veces);

void	T2On(void);
void	PreparaTemporizador(char intervalo);
void	EnablaInterrup(void);
void	DisablaInterrup(char err);
char	ProcesoTest(void);
void	ProcesoEsperaFin(void);
void	PortCLeer(void);
void	Paso(char p);									//MUEVE MOTOR

#endif
motor.c

Código: Seleccionar todo

#include <avr/io.h>
#include <avr/interrupt.h>
#include "usart2.h"
#include "interprete.h"
#include "motor.h"
#include "debug.h"   //
#include "adc2.h"   //
#include "landas.h"   //

/*static 	str_TypeDef str[]={
//	"123456789012345678901234567890"
	"ANTES APARCAR",
	"UN ERROR O ABORTO",
	"enviar algo para parar",
	"FCx inesperado",
	};*/

static 	parametros_TypeDef parametro[]={
//char potencia; char motorretardorap; char motorretardo; int cotal; int cotah; int pasos_lectura;
	0, 1, 2,  100, 18900, 20,	// 1 ยบ predefinido
	0, 7, 9,   10,  1000, 10,	//
	0, 5, 7,    1, 10000, 20,	//
	1, 9, 9,   10,  1000, 30,	//
	};

//-------------------	
void	MotorReset(void){
	DDRC=0x00;         //PUERTO C: todo in
	DDRB=0x2F;         //PUERTO B: led y motor en out
	motorproceso=0;
	motorcosahacer=0;
	motorcosahacerbak=0;
	motorruleta=0;
	motorpaso=0x8000;
	motoraparco=0;
//	DumpPredefinidos();
	CargaParametros(0);
//	DumpParametros();
	T2On();
	}
void	DumpPredefinidos(void){
	TX_s_n("Parametros predefinidos:");
	TX_s_n("Pot\tret rap\tretar\tcotaA\tcotaB\tpasos lect");
	for(char n=0;n<4;n++){
		TX_s(IntDeci(parametro[n].potencia)+4);			TX_s("    \t");
		TX_s(IntDeci(parametro[n].retardorap)+4);		TX_s("    \t");
		TX_s(IntDeci(parametro[n].retardo)+4);			TX_s("    \t");
		TX_s(IntDeci(parametro[n].cotal));				TX_s("\t");
		TX_s(IntDeci(parametro[n].cotah));				TX_s("\t");
		TX_s_n(IntDeci(parametro[n].pasos_lectura)+2);
		}
	}
void	CargaParametros(char n){
	if(n>3){n=0;}						//por seguridad
	motorpotencia	=parametro[n].potencia;			//mas comodo y rapido usar variables  simple 
	motorretardo  	=parametro[n].retardo;      //mas comodo y rapido usar variables  simple 
	motorretardorap	=parametro[n].retardorap;		//mas comodo y rapido usar variables  simple 
	cotal			=parametro[n].cotal;
	cotah			=parametro[n].cotah;
	pasos_lectura	=parametro[n].pasos_lectura;
	}
void  DumpParametros(void){
	TX_s_n(" ");
	TX_s_n("Dump Motor:");
	TX_s("potencia \%      \t    ");	TX_s_n(IntDeci(motorpotencia)+4);		
//	TX_s("motorretardo    \t");	TX_s_n(IntDeci(motorretardo));		
//	TX_s("motorretardorap \t");	TX_s_n(IntDeci(motorretardorap));		
	TX_s("pasos/lect \%\%\%  \t  ");	TX_s_n(IntDeci(pasos_lectura)+2);		
	TX_s("cotal \%\%\%\%\%     \t");	TX_s_n(IntDeci(cotal));				
	TX_s("cotah \%\%\%\%\%     \t");	TX_s_n(IntDeci(cotah));				
	TX_s_n(" ");
	}

//-------------------	
void	MotorPotencia(char pot){	//define las palabras al motor, NO le da ca?a
	if(pot){	motorpalabra0=0x03;	motorpalabra1=0x06;	motorpalabra2=0x0C;	motorpalabra3=0x09;	}
	else{		motorpalabra0=0x01;	motorpalabra1=0x02;	motorpalabra2=0x04;	motorpalabra3=0x08;	}
	}
//-------------------	
void	MotorSube(void){
	MotorTexto(2);	//enviar para parar 
	MotorComunFinal(MOTORSUBIR,motorretardorap);
	}
void	MotorBaja(void){
	MotorTexto(2);	//enviar para parar 
	MotorComunFinal(MOTORBAJAR,motorretardorap);
	}
void	MotorSubeN(int n){
	motorcuentaatras=n;
	MotorComunFinal(MOTORSUBIRN,motorretardorap);
	}
void	MotorBajaN(int n){
	motorcuentaatras=n;
	MotorComunFinal(MOTORBAJARN,motorretardorap);
	}
void	MotorAparca(void){
	PortCLeer();	if(motorFCx){
		MotorComunFinal(MOTORSALIRFC,motorretardorap);	ProcesoEsperaFin();}
	MotorComunFinal(MOTORAPARCA,motorretardorap);	ProcesoEsperaFin();
	if(motorerror=='A'){	MotorTexto(1);		motorerror=0;	return;}//error o abort
	if(motorerror=='E'){	MotorTexto(3);		motorerror=0;	return;}//FC inesperado
	MotorDescansa(8);
	MotorComunFinal(MOTORSALIRFC,motorretardorap);	ProcesoEsperaFin();
	if(motorerror=='E'){	MotorTexto(3);		motorerror=0;	return;}//FC inesperado
	TX_s("APARCA: PasosMotor ahora = 0 : antes = ");	TX_s_n(IntDeci(motorpaso));	
	motorpaso=0;
	motoraparco=1;
	}
void	MotorA(int posicion){	//A cotal
	if(!motoraparco){MotorTexto(0);	return;}	//necesita aparcar
	cota=posicion;
	MotorComunFinal(MOTORA,motorretardorap);
	}
int 	MotorTestCarrera(void){
	if(!motoraparco){MotorTexto(0);	return;}	//necesita aparcar
	MotorComunFinal(MOTORTESTCARR,motorretardorap);		ProcesoEsperaFin();
	if(motorerror=='E'){	MotorTexto(3);		motorerror=0;	return;}//FC inesperado
	MotorDescansa(8);
	MotorComunFinal(MOTORSALIRFC,motorretardorap);	ProcesoEsperaFin();
	if(motorerror){			MotorTexto(1);		motorerror=0;	return;}//error o abort
	TX_s("TEST CARRERA: PasosMotor = ");				TX_s_n(IntDeci(motorpaso));	
	//TEST CARRERA: PasosMotor = 19001 , 18996
	}
void 	MotorEspectro(void){
	if(!pasos_lectura){	TX_s_n("ERROR: ! pasos_lectura");		return;}
	if(cotal>cotah){	TX_s_n("ERROR: cotal>cotah");			return;}
	if(!motoraparco){	MotorAparca();}
	ProcesoEsperaFin();
	if(!motoraparco){		MotorTexto(0);						return;}	//necesita aparcar
	MotorDescansa(8);
//	MotorA(cotal);
	MotorA(cotah);
	ProcesoEsperaFin();
	if(motorerror=='E'){	MotorTexto(3);		motorerror=0;	return;}//FC inesperado
	if(motorerror){			MotorTexto(1);		motorerror=0;	return;}	//error o abort
//	cota=cotah;
	cota=cotal;
	DumpParametros();	//cabecera antes de los numeros. 
	ADCOn();		//arranca el ADC
	MotorDescansa(8);
	MotorComunFinal(MOTORESPECTRO,motorretardo);
	ProcesoEsperaFin();
	if(motorerror=='E'){	MotorTexto(3);		motorerror=0;	return;}//FC inesperado
	if(motorerror){			MotorTexto(1);		motorerror=0;	return;}	//error o abort
	ADCOff();		//apaga el ADC
	if(motorerror=='E'){	MotorTexto(3);		motorerror=0;	return;}//FC inesperado
	if(motorerror){			MotorTexto(1);		motorerror=0;	return;}	//error o abort
	MotorDescansa(8);
	MotorA(cotah);
//	MotorAparca();
	ProcesoEsperaFin();
	if(motorerror=='E'){	MotorTexto(3);		motorerror=0;	return;}//FC inesperado
	if(motorerror){			MotorTexto(1);		motorerror=0;	return;}	//error o abort
	}
//-------------------	
void	MotorComunFinal(char cosa, char retar){
	motorcosahacer=cosa;
	MotorPotencia(motorpotencia);		//se entera palabras motor, NO LE DA POTENCIA
	PreparaTemporizador(retar);
	EnablaInterrup();
	}
void	MotorDescansa(char veces){
	while(veces){
		veces--;
		MotorComunFinal(MOTORPARAR,motorretardorap);	ProcesoEsperaFin();
		}
	}
//-------------------	
void	MotorTexto(char txt){
	TX_s_n(str[txt].str);
	}
motorint.c

Código: Seleccionar todo

#include <avr/io.h>
#include <avr/interrupt.h>
#include "usart2.h"
#include "motor.h"
#include "debug.h"   //
#include "adc2.h"   //

void  T2On(void){
//	bitSet(PRR,PRTIM2);//enciende el temporizador 2, (estaba a 0 para ahorrar ) NO EN EJEMPLO
//	bitSet(ASSR,AS2); // T2 a reloj interno   NO EN EJEMPLO
	TCCR2B = 0x07;	// DON'T FORCE COMPARE, 1024 PRESCALER 
	TCCR2A = 0x02;	// DISABLE PWM ON DIGITAL PINS 3 AND 11, AND GO INTO CTC MODE
	OCR2A  = 0XFF;	// SET THE TOP OF THE COUNT                  sera cambiado en PreparaTemporizador()
	}
//-------------------	
void  PreparaTemporizador(char intervalo){
	switch(intervalo){
		case 9:	OCR2A=0xFF;	break;//contador a 0, tarda maximo en overflou
		case 8:	OCR2A=0xE0;	break;//
		case 7:	OCR2A=0xC0;	break;//
		case 6:	OCR2A=0xA0;	break;//
		case 5:	OCR2A=0x80;	break;//
		case 4:	OCR2A=0x50;	break;//
		case 3:	OCR2A=0x40;	break;//
		case 2:	OCR2A=0x35;	break;//
		case 1:	OCR2A=0x30;	break;//
		case 0:	OCR2A=0x25;	break;//
		}	 
	}	
//-------------------	
void	EnablaInterrup(void){
	ProcesoEsperaFin();
	motorproceso=1;
	RXllegoc=0;				//esta en USART2.H si llega caracter para, 
	bitSet(GTCCR,PSRSYNC);	//preescaler reset
	TCNT2=0;				//reset contador T2
	cli();					//no se porque se hace esto, lo hacen todos
//	TIFR2 = bit (OCF2A);   // clear any pending interrupt
	bitClear(TIFR2,OCF2A);// clear any pending interrupt
	TIMSK2 = 0x02;     // ENABLE INTERRUPT ON MATCH BETWEEN TIMER2 AND OCR2A
	sei();             // MAKE SURE GLOBAL INTERRUPTS ARE ENABLED      
	}
void	DisablaInterrup(char err){
	motorerror=err;
	cli();
	bitClear(TIMSK2,OCIE2A);	//disabla interrupcion T2_OCA
	sei();
	PORTB&=MOTORMASCARA;		//apaga motor
	motorcosahacerbak=motorcosahacer;	//para saber que es lo ultimo que hizo
	motorcosahacer=0;					//motorcosahacer a 0 
	motorproceso=0;
//	Debug1();
	}
//-------------------	
char	ProcesoTest(void){
	return(motorproceso);
	}
void	ProcesoEsperaFin(void){
//	if(motorproceso){	TX_s("en espera,,,\n");}
	while(motorproceso){}
	}
//-------------------	
void	PortCLeer(void){
	PINCbak=PINC;			//lee finales de carrera
	PINCbak&=FCMASCARA;
	switch(PINCbak){
		case  0x00:	motorFCA=1;		motorFCB=1;	motorerror='B';		break;
		case  0x01:	motorFCA=1;		/*motorFCB=0;*/					break;//como nunca las dos, pa q?
		case  0x02:	/*motorFCA=0;*/	motorFCB=1;						break;
		case  0x03:	motorFCA=0;		motorFCB=0;						break;
		}
	motorFCx = motorFCA + motorFCA + motorFCB;
	}
//-------------------	
void	Paso(char p){									//MUEVE MOTOR
	switch(p){
		case  1:
			switch(motorruleta){
				case 0:	motorruleta++;	PORTB|=motorpalabra0;	break;
				case 1:	motorruleta++;	PORTB|=motorpalabra1;	break;
				case 2:	motorruleta++;	PORTB|=motorpalabra2;	break;
				case 3:	motorruleta=0;	PORTB|=motorpalabra3;	break;
				}
			motorpaso++;
			break;
		case -1:
			switch(motorruleta){
				case 0:	motorruleta=3;	PORTB|=motorpalabra0;	break;
				case 1:	motorruleta--;	PORTB|=motorpalabra1;	break;
				case 2:	motorruleta--;	PORTB|=motorpalabra2;	break;
				case 3:	motorruleta--;	PORTB|=motorpalabra3;	break;
				}
			motorpaso--;
			break;
		}
	}
  
//-------------------	
ISR(TIMER2_COMPA_vect){
	PORTB&=MOTORMASCARA;	//comun a todo, apaga motor
	if(RXllegoc){	DisablaInterrup('A');	goto fin;}
	PortCLeer();	//lee finales de carrera, 
	TCNT2=0; //reset contador, 
	switch(motorcosahacer){
		case MOTORPARAR:	//NO hace nada, pierde un tiempo
			DisablaInterrup(0);
			break;
		case MOTORSALIRFC:
			switch(motorFCx){
				case  0x00:	switch(motorasalirfc){	//le da dos pasos de mas, porsi
						case  2:	case  1: Paso( 1);	motorasalirfc--;	break;
						case -2:	case -1: Paso(-1);	motorasalirfc++;	break;
						case  0:	DisablaInterrup(0);	goto fin;		break;}
															break;
				case  0x01:	Paso( 1);	motorasalirfc= 2;	break;
				case  0x02:	Paso(-1);	motorasalirfc=-2;	break;
				case  0x03:	DisablaInterrup('E');			break;
				}
			break;
		case MOTORSUBIR:
			if(motorFCx){	DisablaInterrup('E');	goto fin;}//FCx inesperado
			Paso(1);						//TXdirec(NibleHexa(PINB));
			break;
		case MOTORBAJAR:	
			if(motorFCx){	DisablaInterrup('E');	goto fin;}//FCx inesperado
			Paso(-1);
			break;
		case MOTORSUBIRN:
			if(motorFCx){	DisablaInterrup('E');	goto fin;}//FCx inesperado
			if(motorcuentaatras){
				Paso(1);
				motorcuentaatras--;
				}
			else{			DisablaInterrup(0);		goto fin;	}			//si termino
			break;
		case MOTORBAJARN:
			if(motorFCx){	DisablaInterrup('E');	goto fin;}//FCx inesperado
			if(motorcuentaatras){
				Paso(-1);
				motorcuentaatras--;
				}
			else{			DisablaInterrup(0);		goto fin;	}			//si termino
			break;
		case MOTORAPARCA:
			if(motorFCB){	DisablaInterrup(0); 	goto fin;}//si llego a FCB, termina
			if(motorFCA){	DisablaInterrup('E');	goto fin;}//FCx inesperado
			Paso(-1);
			break;
		case MOTORTESTCARR:				//tes carrera es lo mismo que subir
			if(motorFCA){	DisablaInterrup(0); 	goto fin;}//si llego a FCA, termina
			if(motorFCB){	DisablaInterrup('E');	goto fin;}//FCx inesperado
			Paso(1);						//TXdirec(NibleHexa(PINB));
			break;
		case MOTORA:
			if(cota==motorpaso){DisablaInterrup(0);		goto fin;}	//ya son los dos iguales
			if(cota<motorpaso){	//tiene que bajar
				if(motorFCx){	DisablaInterrup('E');	goto fin;}//FCx inesperado
				Paso(-1);
				}
			if(cota>motorpaso){	//tiene que subir
				if(motorFCx){	DisablaInterrup('E');	goto fin;}//FCx inesperado
				Paso(1);
				}		
			break;
		case MOTORESPECTRO:
			if(adc_cerrado){		//si hay un balance cerrado, lo lanza
				adc_cerrado=0;		//limpia la orden
				TX_s_n(IntDeci(adc_resul));		//aqui lanza el resultado
				}
			adc_ruleta++;
			if(adc_ruleta==pasos_lectura){
				adc_ruleta=0;
				adc_cerrar=1;	//ordena a ADC cerrar balance, 
				}
			if(cota>motorpaso){		ADCOff();	DisablaInterrup(0);	goto fin;	}//
			if(motorFCx){	DisablaInterrup('E');	goto fin;}//FCx inesperado
			Paso(-1);
			break;
		case MOTORESPECTRO2:
			if(adc_cerrado){		//si hay un balance cerrado, lo lanza
				adc_cerrado=0;		//limpia la orden
				}
			adc_ruleta++;
			if(adc_ruleta==pasos_lectura){
				adc_ruleta=0;
				adc_cerrar=1;	//ordena a ADC cerrar balance, 
				}
			if(cota>motorpaso){		ADCOff();	DisablaInterrup(0);	goto fin;	}//
			if(motorFCx){	DisablaInterrup('E');	goto fin;}//FCx inesperado
			Paso(-1);
			break;
		}	
fin:
	sei();			// MAKE SURE GLOBAL INTERRUPTS ARE ENABLED  seguramente no hace falta.    
	}
y ya por fin vemos algo de movimiento.

el motor siempre se mueve desde la interupcion, por un temporizador.
cuando salta la interrup, ella sabe que tiene que hacer, porque desde fuera se ha programado un codigo.
el "desde fuera" son las distintas opciones: motor a,,, motro subir,,, busca final carrera,,, vete a abajo,,,,
cuando de la int le parece que termino, pone "proceso" a 0, y desde afuera saben que termino.

Avatar de Usuario
baldo
Mensajes: 1514
Registrado: Vie Dic 23, 2005 7:54 pm
País: españa
Ciudad: coruña y madrid
Ubicación: Galicia
Contactar:

Re: [HECHO] espectroduino, automatizacion de espectrometro.

#8 Mensaje por baldo »

adc2.h

Código: Seleccionar todo

#ifndef adc2	
#define adc2

volatile	unsigned char 	adcl;
volatile	unsigned char 	adch;
volatile	unsigned int 	adcVal;
volatile	unsigned int 	adc_lecturas;
volatile	unsigned long	adc_acum;
volatile	unsigned int 	adc_resul;		//esto es lo unico que interesa
volatile			 char	adc_cerrar;		//orden de hacer balance
volatile			 char	adc_cerrado;	//balance hecho
volatile			 char adc_ruleta;		//usada para contar pasos lectura
volatile			 char adc_listo;		//usada para decir a capa motor que ya tiene un resltado, 

void	ADCInit(void);	//inicia el asunto
void	ADCOn(void);	//arranca las interupciones
void	ADCOff(void);	//para de leer

#endif
adc2.c

Código: Seleccionar todo

#include <avr/io.h>
#include <avr/interrupt.h>
#include "adc2.h"   //

void	ADCInit(void){	//inicia el asunto ADC
//	ADMUX=0x42;	//ADC Multiplexer Selection Register, Vdd, derecha, A2
	ADMUX  =0b11000101;	//ADC Multiplexer Selection Register, 1v1, derecha, A2
//	ADCSRA =0b10101111;	//Control and Status Register A,  ON, no dispara, auto, ?,interup, /128
	ADCSRA=0b11101111;
//  ADCSRA = B10011111; // ADC enable, manual trigger mode, ADC interrupt enable, prescaler = 128
//  ADCSRA = B11001111;   // ADC enable, ADC start, manual trigger mode, ADC interrupt enable, prescaler = 128
//	ADCSRB=0x00;	//,,?,,fre run
	DIDR0=0x04;		//Digital Input Disable Register 0 , analogico el pin A2
	}
void	ADCOn(void){	//se dispara la lectura continua
	adc_acum=0;		adc_lecturas=0;		adc_ruleta=0;	adc_listo=0;//reset de variables
//	ADCSRA=0b11101111;
	}
void	ADCOff(void){	//se para la lectura  continua
//	ADCSRA=0b10101111;
	}

ISR(ADC_vect){ 
	adcl = ADCL;					//lo saque de un ejemplo ???
	adch = ADCH;					//lo saque de un ejemplo ???
	adcVal = (adch << 8) | adcl;	//lo saque de un ejemplo, esto lo entiendo
	adc_acum+=adcVal;
	adc_lecturas++;
	if(adc_cerrar){
//		adc_acum=adc_acum<<2;		//multiplica x4, sin perder info, 
		adc_acum=adc_acum<<1;		//multiplica x2, sin perder info, 
		adc_resul=(int)(adc_acum/adc_lecturas);
		adc_acum=0;		adc_lecturas=0;		adc_cerrar=0;	adc_cerrado=1;	adc_listo=1;
		}
	}
esto es lo de las lecturas, del ADC,
¿1 lectura / paso?, ¿varias?, ¿muchas?.
al final se puso leyendo continuo,

desde la interrupcion de motor modo espectro, le da orden de cerrar el balance, con "adc_cerrar", en la interrupcion del ADC (a caada nueva lectura) multiplica x2 para mas precision, como hizo un porron de ellas no es solo oner un cero a derecha, haya la media, lo pone en resultado, borra la orden de cerrar, y pone un cerrado y listo, cada uno se usara en una parte del programa.

el detector es como una peseta, y da unos dos voltios, el jefe dijo, "leer 2000 cuando 2 voltios", por lo que la referencia se cambio a 1.1v de ref interna, y se puso un potenciometro en la entrada, sin amplis ni gaitas.

tras hacer el espectro tenia idea de apagar el ADC, pero se me colgaba, asi que aun debe seguir leyendo.

la ventaja de lecturas continuas con media, es mas precision, y que no varia la salida dependiendo de cuantas se hagan.

Avatar de Usuario
baldo
Mensajes: 1514
Registrado: Vie Dic 23, 2005 7:54 pm
País: españa
Ciudad: coruña y madrid
Ubicación: Galicia
Contactar:

Re: [HECHO] espectroduino, automatizacion de espectrometro.

#9 Mensaje por baldo »

landas.h

Código: Seleccionar todo

#ifndef debug	
#define debug

//carrera 18952, ->   15nm, (  10 de contador)
//0 pasos motor, -> 1500nm, (1000 de contador)

#define CTEx        13.33
#define CTEoffset   19143  ///REPASAR OFFSET

void	LandaReset(void);
//-------------------	
int 	SaberLanda(int paso);
int 	SaberPaso (int land);
//-------------------	
void	LandaHelp(void);	
//-------------------	
void	LandaAparca(void);	
void	LandaBaja(void);					//"landa baja %%%%"
void	LandaAlta(void);					//"landa alta %%%%"
void	LandaIrA(void);						//"ir a %%%%"
void	LandaEspectro(void);
void	LandaDumpParametros(void);

int 	landal;	//"landal %%%%"
int 	landah;	//"landah %%%%"

#endif
landas.c

Código: Seleccionar todo

#include <avr/io.h>
#include <avr/interrupt.h>
#include "usart2.h"
#include "motor.h"
#include "adc2.h"   //
#include "landas.h"   //

void	LandaReset(void){
	landal=240;
	landah=1200;
	LandaDumpParametros();
	}
//-------------------	

int 	SaberLanda(int paso){	return((int)((CTEoffset-paso)/CTEx));	}
int 	SaberPaso (int land){	return((int)(CTEoffset-(CTEx*land)));	}
//-------------------	
void	LandaHelp(void){	TX_s_PGM2();	}	//saca help de capa landas
//-------------------	
void	LandaAparca(void){	MotorAparca();	}	//
void	LandaBaja(void){landal=	DeciInt('0',bufRX[7],bufRX[8],bufRX[9],bufRX[10]);	LandaDumpParametros();}//"landal %%%%"
void	LandaAlta(void){landah=	DeciInt('0',bufRX[7],bufRX[8],bufRX[9],bufRX[10]);	LandaDumpParametros();}//"landah %%%%"
/*void	LandaAlta(void){
	LandaDumpParametros();
	landah=	DeciInt('0',bufRX[7],bufRX[8],bufRX[9],bufRX[10]);	
	TX_s_n(bufRX);
	LandaDumpParametros();}//"landah %%%%"*/
void	LandaIrA(void){	MotorA(SaberPaso(DeciInt('0',bufRX[5],bufRX[6],bufRX[7],bufRX[8])));}//"ir a %%%%"
//-------------------	
void	LandaEspectro(void){
	if(!pasos_lectura){	TX_s_n("ERROR: ! pasos_lectura");		return;}
	if(landal>landah){	TX_s_n("ERROR: landal>landah");			return;}
	if(!motoraparco){	MotorAparca();}
	ProcesoEsperaFin();
	if(!motoraparco){		MotorTexto(0);						return;}	//necesita aparcar
	MotorDescansa(8);
	MotorA(SaberPaso(landal));
	ProcesoEsperaFin();
	if(motorerror=='E'){	MotorTexto(3);		motorerror=0;	return;}//FC inesperado
	if(motorerror){			MotorTexto(1);		motorerror=0;	return;}	//error o abort
	cota=SaberPaso(landah);
	LandaDumpParametros();	//cabecera antes de los numeros. 
	ADCOn();		//arranca el ADC
	MotorDescansa(8);
	MotorComunFinal(MOTORESPECTRO2,motorretardo);

	while(motorproceso){
		if(adc_listo){
			adc_listo=0;
			TX_s(IntDeci(SaberLanda(motorpaso))+1);	TX_s("\t");	TX_s_n(IntDeci(adc_resul)+1);
			}
		if(motorerror=='E'){	MotorTexto(3);		motorerror=0;	return;}//FC inesperado
		if(motorerror){			MotorTexto(1);		motorerror=0;	return;}	//error o abort
		}
	if(adc_listo){		//otra vez por si quedaba despistado. 
		adc_listo=0;
		TX_s(IntDeci(SaberLanda(motorpaso))+1);	TX_s("\t");	TX_s_n(IntDeci(adc_resul)+1);
		}
	
	ADCOff();		//apaga el ADC
	MotorDescansa(8);
	MotorA(SaberPaso(landal));
	ProcesoEsperaFin();
	if(motorerror=='E'){		MotorTexto(3);		motorerror=0;	return;}//FC inesperado
	if(motorerror){				MotorTexto(1);		motorerror=0;	return;}	//error o abort
	}

void	LandaDumpParametros(void){
	TX_s_n(" ");
	TX_s_n("Dump:");
	TX_s("retardo rap \%   \t    ");	TX_s_n(IntDeci(motorretardorap)+4);		
	TX_s("retardo \%       \t    ");	TX_s_n(IntDeci(motorretardo)+4);		
	TX_s("pasos/lect \%\%\%  \t  ");	TX_s_n(IntDeci(pasos_lectura)+2);		
	TX_s("landal \%\%\%\%     \t ");	TX_s_n(IntDeci(landal)+1);				
	TX_s("landah \%\%\%\%     \t ");	TX_s_n(IntDeci(landah)+1);		
	TX_s("landa actual    \t ");	TX_s_n(IntDeci(SaberLanda(motorpaso))+1);		
	TX_s("en pasos motor  \t");	TX_s_n(IntDeci(motorpaso));			
	TX_s_n(" ");
	}

"CREO" que esto es la version de hacer espectro, lo ultimo que se puso en el programa, el añadir la lectura cuando ya se controlaba el rollo del motor, en hoja aparte,

segun el paso motor calcula landa, y lo pone a izquierda de la lectura,
en la consola arduino se recogen filas con los dos numeros, hay que copiarlos y pegarlos en hoja de calculo para sacar la grafica.

un lio con el profe, un quisqui, no se conformo con el proograma, tambien queria que lo afinase.
al principio no sabiamos donde estaba el rojo ni el azul,,, lamparas de mercurio,,, laseres,,, abrir, tripas mirar,,,,

al final parece que ya mide bien.

Avatar de Usuario
baldo
Mensajes: 1514
Registrado: Vie Dic 23, 2005 7:54 pm
País: españa
Ciudad: coruña y madrid
Ubicación: Galicia
Contactar:

Re: [HECHO] espectroduino, automatizacion de espectrometro.

#10 Mensaje por baldo »

help.h

Código: Seleccionar todo

#ifndef help	
#define help

void	TX_s_PGM(void);
void	TX_s_PGM2(void);

#endif
help.c

Código: Seleccionar todo

#include <avr/pgmspace.h>
#include "usart2.h"
#include "help.h"

const char help_00[] PROGMEM = "COMANDOS PRINCIPALES:\n";   
const char help_01[] PROGMEM = "PONER TAL CUAL. LITERAL.  \% es plantilla de numero\n";   
const char help_02[] PROGMEM = "led x          (invierte led, usado como test\n";
const char help_A3[] PROGMEM = "predef ver     (ver que predefinidos hay\n";
const char help_03[] PROGMEM = "predefinido \%  (de 0 a 3, carga parametros prede\n";
const char help_04[] PROGMEM = "aparca         (se va a fin carrera baja, y 0\n";
const char help_05[] PROGMEM = "espectro       (hace un espectro\n";
const char help_06[] PROGMEM = "retardo rap \%  (del motor cuando se posiciona\n";
const char help_07[] PROGMEM = "retardo \%      (cuando hace un espectro\n";
const char help_08[] PROGMEM = "pasos/lect \%\%\% (cada cuantos pasos lee\n";
//const char help_09[] PROGMEM = "  Type h2 o h3 para mas opciones\n";

const char help_09[] PROGMEM = "   otros comandos utiles\n";
const char help_10[] PROGMEM = "potencia \%     (0 una bobi mot, 1 dos\n";
const char help_11[] PROGMEM = "cotah \%\%\%\%\%    (fija una cota alta, en pasos mot\n";
const char help_12[] PROGMEM = "cotal \%\%\%\%\%    (la baja\n";
const char help_13[] PROGMEM = "a cota baja    (se mueve a cota baja\n";
const char help_14[] PROGMEM = "a cota alta\n";
const char help_15[] PROGMEM = "test carrera   (mide la carrera max\n";

const char help_20[] PROGMEM = "   usados por el programador\n";
const char help_21[] PROGMEM = "sube           (sube hasta recibir algo\n";
const char help_22[] PROGMEM = "baja\n";
const char help_23[] PROGMEM = "sube \%\%\%\%      (sube tantos pasos mot\n";
const char help_24[] PROGMEM = "baja \%\%\%\%\n";
const char help_25[] PROGMEM = "led 1\n";
const char help_26[] PROGMEM = "led 0\n";
const char help_27[] PROGMEM = "eco 0\n";
const char help_28[] PROGMEM = "eco 1\n";
const char help_29[] PROGMEM = "reset          (de parametros motor\n";
const char help_30[] PROGMEM = "debug 1\n";
const char help_31[] PROGMEM = "debug 2\n";	// 

void 	TX_s_PGM(void){
	char c;	char k;
	TX_s(" \n");
	k=0; do{c = pgm_read_byte_near(help_00 + k);	TX(c);	k++;} while(c!='\n');
	k=0; do{c = pgm_read_byte_near(help_01 + k);	TX(c);	k++;} while(c!='\n');
	k=0; do{c = pgm_read_byte_near(help_02 + k);	TX(c);	k++;} while(c!='\n');
	k=0; do{c = pgm_read_byte_near(help_A3 + k);	TX(c);	k++;} while(c!='\n');
	k=0; do{c = pgm_read_byte_near(help_03 + k);	TX(c);	k++;} while(c!='\n');
	k=0; do{c = pgm_read_byte_near(help_04 + k);	TX(c);	k++;} while(c!='\n');
	k=0; do{c = pgm_read_byte_near(help_05 + k);	TX(c);	k++;} while(c!='\n');
	k=0; do{c = pgm_read_byte_near(help_06 + k);	TX(c);	k++;} while(c!='\n');
	k=0; do{c = pgm_read_byte_near(help_07 + k);	TX(c);	k++;} while(c!='\n');
	k=0; do{c = pgm_read_byte_near(help_08 + k);	TX(c);	k++;} while(c!='\n');
	TX_s(" \n");
	k=0; do{c = pgm_read_byte_near(help_09 + k);	TX(c);	k++;} while(c!='\n');
	k=0; do{c = pgm_read_byte_near(help_10 + k);	TX(c);	k++;} while(c!='\n');
	k=0; do{c = pgm_read_byte_near(help_11 + k);	TX(c);	k++;} while(c!='\n');
	k=0; do{c = pgm_read_byte_near(help_12 + k);	TX(c);	k++;} while(c!='\n');
	k=0; do{c = pgm_read_byte_near(help_13 + k);	TX(c);	k++;} while(c!='\n');
	k=0; do{c = pgm_read_byte_near(help_14 + k);	TX(c);	k++;} while(c!='\n');
	k=0; do{c = pgm_read_byte_near(help_15 + k);	TX(c);	k++;} while(c!='\n');
	TX_s(" \n");
	k=0; do{c = pgm_read_byte_near(help_20 + k);	TX(c);	k++;} while(c!='\n');
	k=0; do{c = pgm_read_byte_near(help_21 + k);	TX(c);	k++;} while(c!='\n');
	k=0; do{c = pgm_read_byte_near(help_22 + k);	TX(c);	k++;} while(c!='\n');
	k=0; do{c = pgm_read_byte_near(help_23 + k);	TX(c);	k++;} while(c!='\n');
	k=0; do{c = pgm_read_byte_near(help_24 + k);	TX(c);	k++;} while(c!='\n');
	k=0; do{c = pgm_read_byte_near(help_25 + k);	TX(c);	k++;} while(c!='\n');
	k=0; do{c = pgm_read_byte_near(help_26 + k);	TX(c);	k++;} while(c!='\n');
	k=0; do{c = pgm_read_byte_near(help_27 + k);	TX(c);	k++;} while(c!='\n');
	k=0; do{c = pgm_read_byte_near(help_28 + k);	TX(c);	k++;} while(c!='\n');
	k=0; do{c = pgm_read_byte_near(help_29 + k);	TX(c);	k++;} while(c!='\n');
	k=0; do{c = pgm_read_byte_near(help_30 + k);	TX(c);	k++;} while(c!='\n');
	k=0; do{c = pgm_read_byte_near(help_31 + k);	TX(c);	k++;} while(c!='\n');
	}
help2.c

Código: Seleccionar todo

#include <avr/pgmspace.h>
#include "usart2.h"
#include "help.h"

const char help2_00[] PROGMEM = "COMANDOS PRINCIPALES DE CAPA LANDAS:\n";   
const char help2_01[] PROGMEM = "PONER TAL CUAL. LITERAL.  \% es plantilla de numero\n";   
const char help2_02[] PROGMEM = "espectro       (hace espectro entre cotas landas\n";
const char help2_03[] PROGMEM = "aparca         (se va a fin carrera baja, y 0\n";
const char help2_04[] PROGMEM = "landal \%\%\%\%    (fija cota baja\n";
const char help2_05[] PROGMEM = "landah \%\%\%\%    (fija cota\n ";
const char help2_06[] PROGMEM = "ir a \%\%\%\%      (se mueve hasta ,,,\n";
const char help2_07[] PROGMEM = "dump           (muestra parametros\n";
const char help2_08[] PROGMEM = "h2             (otro help de debug\n";


void 	TX_s_PGM2(void){
	char c;	char k;
	TX_s(" \n");
	k=0; do{c = pgm_read_byte_near(help2_00 + k);	TX(c);	k++;} while(c!='\n');
	k=0; do{c = pgm_read_byte_near(help2_01 + k);	TX(c);	k++;} while(c!='\n');
	k=0; do{c = pgm_read_byte_near(help2_02 + k);	TX(c);	k++;} while(c!='\n');
	k=0; do{c = pgm_read_byte_near(help2_03 + k);	TX(c);	k++;} while(c!='\n');
	k=0; do{c = pgm_read_byte_near(help2_04 + k);	TX(c);	k++;} while(c!='\n');
	k=0; do{c = pgm_read_byte_near(help2_05 + k);	TX(c);	k++;} while(c!='\n');
	k=0; do{c = pgm_read_byte_near(help2_06 + k);	TX(c);	k++;} while(c!='\n');
	k=0; do{c = pgm_read_byte_near(help2_07 + k);	TX(c);	k++;} while(c!='\n');
	k=0; do{c = pgm_read_byte_near(help2_08 + k);	TX(c);	k++;} while(c!='\n');
	}

que menos que poner una ayuda.
como la parrafada ya no cabia en RAM, hubo que ponerla en ROM.
la 1º era la que prepare al principio.
pero tan larga que necesito un resumen de principales.

Responder

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 0 invitados