State Machine

Hey ich Hab ein Verständnis Problem, warum mein Code einmal läuft und einmal nicht .
Vielleicht kann mir jemand weiter helfen

wenn ich die code zeile "this->engine_state=0b00100000; //motor sperre"
als letztes in Engine_Drivers_setup::setup(), Läuft meine State Machine und die werte passen

wenn ich diese aber vor meinen Array einfüge Läuft meine State Machine nicht !! und die werte passen
logischerweise auch nicht

Engine_Drivers_setup::Engine_Drivers_setup(){
	volatile uint8_t *enginePort;  //port of engine
	volatile  uint8_t enginePin;   //pin of engine
	volatile  uint8_t *engineDDRx; //DDRx of engine	
	unsigned long int engineDelay; // pulse witdh engine
	unsigned long gearing;  //translation engine
	int myarray[15];
	uint8_t engine_state;//=0b00000000; // engine stats
	
	/*engine_state :	
	0
	b
	0		7 = pulse state		0=off/1=on
	0		6 = engine state	0=left/1=right(l/r)(0/1)  or in/out(i/o)(1/0)
	0		5 = step enable		0=off/1=on
	0		4 = stop			0=off/1=on
	0		3 = ramp up
	0		2 = ramp down
	0		1 = limit 
	0		0 =
	*/
}
void Engine_Drivers_setup::step_engine(unsigned long *time_now){
	if((*time_now-(*global_time)>(*this->ptr_engineDelay))&&((this->engine_state& 0b00100000)== 0b00100000)){
		cli();
                USB.printChar(this->engine_state);       #bei richtiger funktion abwechselnd 32/160 sonst 15
		if(this->engine_state & (1 << 7)){
 			*this->enginePort |= (1 << this->enginePin);
 			this->engine_state &= ~(1<<7);
 		 	tims=*time_now;
			*this->ptr__pos =*this->ptr__pos+1;
			//this->influence_Axis(); //Axis 
 			sei();
		}
 		else{
 			*this->enginePort &= ~(1 << this->enginePin);
 			this->engine_state |= (1<<7);
			tims=*time_now;
 			sei();
 		}
	}
}

so läuft mein code nicht

void Engine_Drivers_setup::setup(){
	int mystate=0;
	*this->engineDDRx |= (1<<this->enginePin);
	this->engine_state=0b00100000; //motor sperre       #diese zeile
        USB.printChar(this->engine_state);                           #gibt 32 aus. hier passt der wert noch
	this->myarray[0]=10;
	this->myarray[1]=15;
	this->myarray[2]=20;
	this->myarray[3]=25;
	
	
}

so schon

void Engine_Drivers_setup::setup(){
	int mystate=0;
	*this->engineDDRx |= (1<<this->enginePin);
	this->myarray[0]=10;
	this->myarray[1]=15;
	this->myarray[2]=20;
	this->myarray[3]=25;
	this->engine_state=0b00100000; //motor sperre     #diese zeile
	USB.printChar(this->engine_state);                           #gibt 32 aus
}

Entweder bin ich zu alt für C++, oder Dein Code enthält etliche tote Variablen, die nur lokal im Konstruktor deklariert und anschließend weggeworfen werden. Wie sieht denn die Klassendeklaration aus?

Und wieso sollen diese Variablen volatile sein? Wodurch werden die sonst noch asynchron geändert?

@DrDiettrich: Du bist nicht zu alt. Das Problem liegt daran, dass uns der TO nur mit Fragmenten abspeisen will und damit mehr Verwirrung als Lösungsansätze liefert.

@TO: Gib uns einen vollständigen Sketch.

Gruß Tommy

Hallo,

mir sind das auch zu viele Stückchen, ich kann daraus nichts ableiten. Ich wette aber das Zeiger hier gar nicht notwendig sind. Übergabe als Referenz wäre wohl angebrachter, wenn überhaupt. In allen was ich in den Fragmenten sehe.

Wenn ich solche versuchten Zuweisungen sehe, dann sind diese sowieso komplett falsch.
engine_state ist kein Zeiger, dass ist ein normales Byte.

this->engine_state &= ~(1<<7);

Wenn ich solche versuchten Zuweisungen sehe, dann sind diese sowieso komplett falsch.
engine_state ist kein Zeiger, dass ist ein normales Byte.

[Select]
this->engine_state &= ~(1<<7);

Für mich sieht das eigentlich ganz gut aus.
Ob logisch richtig, weiß ich nicht.
Aber formal ist das ok.
Da wird einfach nur das höchstwertige Bit gelöscht.

Statt der Bitfummeleien wären separate Variablen einfacher und übersichtlicher. Oder Bitfields, wenn die wirklich unbedingt alle in einem Byte liegen müssen.

Hallo,
engine_state wurde als Byte deklariert und nicht als Zeiger. Der Compiler sollte mindestens Warnungen produzieren.

Hi

Diese sind aber standardmäßig ausgeschaltet, daß man sich keinen Kopf machen muß, weil nur noch ROT vom Kompiler zurück kommt :wink:

MfG

Doc_Arduino:
Hallo,
engine_state wurde als Byte deklariert und nicht als Zeiger. Der Compiler sollte mindestens Warnungen produzieren.

Nööö!

this->engine_state &= ~(1<<7);

Kein Zeiger.
OK, this ist ein Zeiger
Und engine_state ist offensichtlich ein gültiges Ziel dieses Zeigers.
Weitere, oder falsche, Zeiger sehe ich nicht und einen Grund für Warnungen/Errors erst recht nicht.

Gleichwertig:

 this->engine_state =  this->engine_state & ~(1<<7);

Ich hab mir gedacht es ist leichter das Problem runter zu brechen ,als den ganzen code zu posten .
Da es eher eine Zufalls Entdeckung war .

Ein paar leer/unnötige variablen sind vorhanden die ich aber später nutzen möchte .

#include <avr/io.h>
#include <avr/interrupt.h>
#include "usb libary/usb.h"
#include "shield libary/shield_setup.h"
#include "time/fast.h"


so sieht im Moment meine Main aus
int main(void)
{	
	
	
	USB.setUart(16000000,2000000); // set uart communication F_CPU,Baudrate
	time_int(); //initialize timer1
	Engine_Drivers_setup unten;
	Engine_Drivers_setup oben;
	oben.setup();
	oben.influence_Axis_array[0]=&unten.ptr__pos;
	*oben.ptr_influence_Axis_count=3;
	USB.printChar("okay");
    while (1) 
    {
		
		

		unsigned long gettime=fastus();
	         oben.step_engine(&gettime);
		
    }
}

SHIELD_SETUP cpp

/*
Port D     avr	|	board|	Comments 	|	cnc schild		| hardware function	| DDRx/PORTx base   |hardware comments	| software function		| software comments	|
			0	|	0	 |	rx			|		--			|					|		0/0			|					|						|					|
			1	|	1	 |	tx			|		--			|					|		0/0			|					|						|					|
			2	|	2	 |	--			|    step x-Axis	|					|		1/0			|					|						|					|
			3	|	3	 |	--			|	 step y-Axis	|	 rotation		|		1/0			|	one step		|  step_rotation()	    |				    |
			4	|	4	 |	--			|    step z-Axis	|					|		1/0			|					|						|					|
			5	|	5	 |	--			|    dir x-Axis		|					|		1/0			|					|						|					|
			6	|	6	 |	--			|    dir y-Axis		|  direction change	|		1/0			| left=on/right=off	| dir_rotation(char)	|	l=left/r=right  |
			7	|	7	 |	--			|    dir z-Axis		|					|		1/0			|					|						|					|
Port B///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			0	|	8	 |	--			|step Enable/Disable|step Enable/Disable|		1/1			|  on=off/off=on	|step_Enable(char)		| y=start/n=stop	|
			1	|	9	 |	--			|	 limit x Axis	|					|		0/0			|					|						|					|
			2	|	10	 |	--			|	 limit y Axis	|					|		0/0			|					|						|					|
			3	|	11	 |	--			|	 limit z Axis	|					|		0/0			|					|						|					|			
			4	|	12	 |	--			|   spindle enable  |					|		1/0			|					|						|					|
			5	|	13	 | build in led |    spindle dir	|					|		1/0			|					|						|					|	
			6	|	--	 |	--			|		 --			|					|		0/0			|					|						|					|	
			7	|	--	 |	--			|		 --			|					|		0/0			|					|						|					|
Port C///////////////////////////////////////////////////////////////////////////////////////////////
			0	|	0	 |	--			|	reset/abort		|					|		0/0			|					|						|					|		
			1	|	1	 |	--			|	 feed hold		|					|		0/0			|					|						|					|
			2	|	2	 |	--			|	  resume		|					|		0/0			|					|						|					|
			3	|	3	 |	--			|	coolant enable	|					|		0/0			|					|						|					|
			4	|	4	 |	--			|		--			|					|		0/0			|					|						|					|
			5	|	5	 |	--			|		--			|					|		0/0			|					|						|					|
*/	
#include "shield_setup.h"
#include "../usb libary/usb.h"
#include <avr/io.h>
#include <avr/interrupt.h>
typedef unsigned char uint8_t ;


Engine_Drivers_setup::Engine_Drivers_setup(){
	float pos;
	this->pos=0;            ///position of actuator
	float *ptr__pos=&pos;	///ptr of pos
	volatile uint8_t x;
	volatile uint8_t *enginePort;  //port of engine
	this->enginePort=&PORTB;
	volatile  uint8_t enginePin;   //pin of engine
	this->enginePin=5;
	volatile  uint8_t *engineDDRx; //DDRx of engine	
	this->engineDDRx=&DDRB;
	unsigned long int engineDelay; // pulse witdh engine
	this->engineDelay = 1000000;
	unsigned long int *ptr_engineDelay=&engineDelay; //ptr engineDelay
	unsigned long gearing;  //translation engine
	this->gearing =0;
	int micro_steps; //micro steps engine driver
	this->micro_steps =32;
	int full_step;	//engine full step base 
	this->full_step=200;
	float limit_max;	//limit max
	float limit_min;	//limit min
	float pos_target;	// position target
	float pos_actual ; // position actual
	void (*func_ptr)(float,float *pos_address);	// function to position determination (add pos vaule,memory location pos)=to function;
	float **influence_Axis_array[4];
	int influence_Axis_count;
	int *ptr_influence_Axis_count;
	float influence_vaule[4];
	float influence_vaule_dir[4];
	volatile int *ptr_influence_vaul_now;
	
	uint8_t engine_state;//=0b00000000; // engine stats
	int myarray[15];
	/*engine_state :	
	0
	b
	0		7 = pulse state		0=off/1=on
	0		6 = engine state	0=left/1=right(l/r)(0/1)  or in/out(i/o)(1/0)
	0		5 = step enable		0=off/1=on
	0		4 = stop			0=off/1=on
	0		3 = ramp up
	0		2 = ramp down
	0		1 = limit 
	0		0 =
	*/
}
void Engine_Drivers_setup::setup(){
	int mystate=0;
	*this->engineDDRx |= (1<<this->enginePin);
	this->myarray[0]=10;
	this->myarray[1]=15;
	this->myarray[2]=20;
	this->myarray[3]=25;
	this->engine_state=0b00100000; 
	USB.printChar(this->engine_state);                       
}



void Engine_Drivers_setup::ledon(){
	*this->engineDDRx |= (1<<this->enginePin);
	*this->enginePort |=(1<<this->enginePin);
}


float Engine_Drivers_setup::get_pos(){
	return *this->ptr__pos;
}
	
void Engine_Drivers_setup::set_rotation_direction(uint8_t &dir){
	if (dir=='l')
	{
		this->engine_state |= (1<<6);
		//*this->ptr_influence_vaul_now=&this->influence_vaule;
	}
	else if (dir=='r')
	{
		this->engine_state &= ~(1<<6);
		//*this->ptr_influence_vaul_now=&this->influence_vaule_dir;
	}
}

void Engine_Drivers_setup::set_axis_release(uint8_t &release){
	if (release=='y')
	{
		this->engine_state |= (1<<5);
	}
	else if (release=='n')
	{
		this->engine_state &= ~(1<<5);
	}
}

void Engine_Drivers_setup::step_engine(unsigned long *time_now){
	//USB.printChar(this->engine_state);
	if((*time_now-(*global_time)>(*this->ptr_engineDelay))&&((this->engine_state& 0b00100000)== 0b00100000)){
		cli();
		if(this->engine_state & (1 << 7)){
 			*this->enginePort |= (1 << this->enginePin);
 			this->engine_state &= ~(1<<7);
 		 	tims=*time_now;
			*this->ptr__pos =*this->ptr__pos+1;
			//this->influence_Axis(); //Axis 
			USB.printChar("step");
 			sei();
		}
 		else{
 			*this->enginePort &= ~(1 << this->enginePin);
 			this->engine_state |= (1<<7);
			tims=*time_now;
			USB.printChar("step0");
 			sei();
 		}
	}
}



void Engine_Drivers_setup::influence_Axis(){
	
	
	//for(int i=0; i<=3-1/**this->ptr_influence_Axis_count-1*/;i++){
	//	USB.printChar(*(this->ptr_influence_vaul_now+i));
	//	USB.printChar();
		//**this->influence_Axis_array[0]=**this->influence_Axis_array[0]+1;
	//}	
}

void pos_spindle1(float pos,Engine_Drivers_setup &driver){
	if(driver.engine_state & 0b01000000){
		driver.pos_ist=driver.pos_ist-pos;
	}
	else{
		driver.pos_ist=driver.pos_ist+pos;
	}
}

void angle_rotation1(float grad,Engine_Drivers_setup &driver){
	// *ptr_rotation_pos =1.5;// *ptr_rotation_pos+grad;
	if(driver.engine_state & 0b01000000){
		if(driver.pos_ist-grad <= 0){
			driver.pos_ist=360+(driver.pos_ist-grad);
		}
		else{
			driver.pos_ist=driver.pos_ist-grad;
		}
	}
	else{
		if(driver.pos_ist+grad >=360){
			driver.pos_ist=grad+(driver.pos_ist-360);
		}
		else{
			driver.pos_ist=driver.pos_ist+grad;
		}
	}
}

SHIELD_SETUP h

class Engine_Drivers_setup{
	public:
	Engine_Drivers_setup();
	float pos;
	float *ptr__pos=&pos;
 	volatile uint8_t *enginePort;
 	volatile  uint8_t enginePin;//&pins[5];
  	volatile  uint8_t *engineDDRx;
  	unsigned long int engineDelay;
  	unsigned long int *ptr_engineDelay=&engineDelay;
  	unsigned long gearing;
  	int micro_steps;
  	int full_step;
	float limit_max;
	float limit_min;
	float pos_soll;
	float pos_ist;
	float **influence_Axis_array[];
	int influence_Axis_count;
	int *ptr_influence_Axis_count;
	float influence_vaule[];
	float influence_vaule_dir[];
	volatile int *ptr_influence_vaul_now;
	
	float get_pos();
	void set_rotation_direction(uint8_t &dir);
	void set_axis_release(uint8_t &release);
	void step_engine(unsigned long *time_now);
	void influence_Axis();
	void (*func_ptr)(float,float *pos_address);
	void setup();
	
	 uint8_t engine_state;
	int myarray[];
	/*engine_state :	
	0
	b
	0		7 = pulse state		0=off/1=on
	0		6 = engine state	0=left/1=right(l/r)(0/1)  or in/out(i/o)(1/0)
	0		5 = step enable		0=off/1=on
	0		4 = stop			0=off/1=on
	0		3 = ramp up
	0		2 = ramp down
	0		1 = limit 
	0		0 =
	*/
};



void angle_rotation1(float pos,Engine_Drivers_setup &driver);

void pos_spindle1(float pos,Engine_Drivers_setup &driver);

Hab heute beide Versionen noch mal neu kompiliert und geladen ,auf einmal laufen beide Versionen !?

Hallo,

muss dennoch fragen warum du so viele überflüssige Zeiger nutzt? Außer du magst Dinge zuverkomplizieren.

Bsp.
this->engine_state |= (1<<5)
wäre einfacher ohne
engine_state |= (1<<5)

oder das hier
*this->engineDDRx |= (1<enginePin)
wäre einfacher ohne
engineDDRx |= (1<<enginePin)

oder das hier
this->enginePin=5
wäre einfacher ohne
enginePin=5

Was mir persönlich auch nie gefällt ist der Mischmasch der Datentypschreibweise. Alles durcheinander was nur geht. Wer das Arduino Framework ausblendet sollte dann auch ohne auskommen. :slight_smile:

Bsp.
this->engine_state |= (1<<5)
wäre einfacher ohne
engine_state |= (1<<5)

Die Dereferenzierung über this stammt aus der alten Zeit, als es noch nicht C++ hieß, sondern noch "C mit Klassen". Damals war das ein MUSS. Es gab keine Alternative dazu.

Heute macht es auch noch Sinn, wenn man explizit sein möchte.

this->engine_state
Macht völlig klar, dass engine_state eine Eigenschaft des aktuellen Objektes ist. Es besteht noch nicht mal im Ansatz die Gefahr, dass versehentlich auf was externes zugegriffen wird und das wäre ein sehr schwer zu findender Fehler.

Also:
Ein besserer Schutz gegen Tippfehler!
Unerwünschte/Unbeabsichtigte Seiteneffekte werden so wirksam eingegrenzt.
Außerdem kostet es nichts, nur zusätzliche Tipparbeit.

Das ist der Grund, warum man das so häufig in Büchern findet.
Warum auch so mancher "Coding Style Guide" das so vehement einfordert.

Es ist also für uns Arduinojünger etwas ungewohnt zu sehen, mehr aber auch nicht.

Auch der Unterstrich in this->engine_state deutet auf ein älteres Paradigma.
Moderner wäre wohl > this->engineState

Doc_Arduino

das es ohne "this" geht wusste ich noch nicht !

Ich habe mit einen Zeiger gearbeitet das ich die Speicher Adresse von denn DDRx Register bekomme.
mit der Referenz bekam ich eine Fehler meldungen:
Severity Code Description Project File Line
Error invalid conversion from 'volatile uint8_t* {aka volatile unsigned char*}' to 'uint8_t {aka unsigned char}' [-fpermissive]

*this->engineDDRx |= (1<<this->enginePin)
wäre einfacher ohne
engineDDRx |= (1<<enginePin)

philaadro:

*this->engineDDRx |= (1<<this->enginePin)

wäre einfacher ohne
engineDDRx |= (1<<enginePin)

Ist aber nicht äquivalent. Du hast einen '*' im Teil ohne this verloren.

Brauchst du wirklich die zusätzliche Geschwindigkeit?

Ich fände ein pinMode* deutlich lesbarer und es wäre portabler.
Wie oft wird die Funktion ausgeführt?

* dann natürlich auf dem wirklichen Pin und nicht dem Offset in einem Register.

Die DDRx Register werden nur einmal gesetzt.
Aber in der State Maschine werden die PORTx register
Extrem oft genutzt für die Stepper Motorn.

Und nicht nur wegen der portabilität(eventuell umstieg auf anderen microcontroller) möchte ich auf adruino Befehle verzichten, sondern auch rein am interesse daran.
Auch wenn der Weg so etwas schwierig ist.

philaadro:
Und nicht nur wegen der portabilität(eventuell umstieg auf anderen microcontroller) möchte ich auf adruino Befehle verzichten, sondern auch rein am interesse daran.
Auch wenn der Weg so etwas schwierig ist.

Vor allem geht der Weg in die falsche Richtung.

Direkter Zugriff auf die Hardware ist das Gegenteil von Portabilität
und IMHO nur gerechtfertigt, wenn man die Geschwindigkeit wirklich braucht.
Das ist bei pinMode regelmäßig nicht der Fall.

Interesse ist selten geworden, das begrüße ich immer, aber jetzt weisst du doch wie es funktioniert, oder?

Eine Library für eine schöne Statemachine würde ich auf andere Platformen mitnehmen wollen.

Im Grunde verstehe ich sowieso nicht, was I/O in einer Statemachine zu suchen hat.

Mehr oder weniger ,der Fehler ist heute auf einmal nicht mehr da was ich mir nicht erklären kann.

m Grunde verstehe ich sowieso nicht, was I/O in einer Statemachine zu suchen hat.

aber wie würdest du die I/Os schalten ,einen um weg über eine Function also wie digitalWrite?

Was hat digitalWrite mit einer Statemachine zu tun?

Völlig ungeachtet der Implementierung der Funktionalität von digitalWrite.

Das I/O Handling liegt in einer weiteren Bibliothek, die nach Bedarf (Geräte...) austauschbar ist.