Arduino Mega 2560 bekommt input von CNC

Hallo liebe Gemeinde, ich habe für meine CNC eine externe Komponente zu steuern da diese nur PWM versteht und meine CNC Steuerung keins ausgeben kann nutze ich ein Mega2560 um die Step und Dir zu empfangen und anschließend in PWM auszugeben.

der Code funktioniert recht gut… naja relativ.

Leider lässt der Arduino viele Impulse “unter den Tisch fallen.”

irgendwie habe ich das Gefühl das ich Interrupt benutzen muss, nur leider habe ich 0 Plan von und die Beispiele helfen mir nicht weiter.

Daher wende ich mich nun an euch.

hier mal der Code:

int LaserPWMPin = 13;
int DirPin = 12;
int StepPin = 11;

int counter = 0;
int DirPinState = 0;
int StepPinState = 0;
int DirPinStateHIGH = 0;
int StepPinStateHIGH = 0;
int LaserPWMOUT = 0;

void setup()
{
Serial.begin(9600);
pinMode(DirPin, INPUT);
pinMode(StepPin, INPUT);
pinMode(LaserPWMPin, OUTPUT);
}

void loop()
{
// CNC-Puls Input / Counter zählt +
DirPinState = digitalRead(DirPin);
StepPinState = digitalRead(StepPin);
if (DirPinState == HIGH && StepPinState == LOW)
{ // read two switches
counter++;
DirPinStateHIGH = 1;
StepPinStateHIGH = 0;
}
// CNC-Puls Input / Counter zählt -
if (DirPinState == HIGH && StepPinState == HIGH)
{ // read two switches
counter–;
DirPinStateHIGH = 1;
StepPinStateHIGH = 1;
}
{
LaserPWMOUT = map(counter, 0, 255, 255, 0);
// change the analog out value:
analogWrite(LaserPWMPin, LaserPWMOUT);
}
// pwm begrenzen
if (LaserPWMOUT<0)
{
LaserPWMOUT = 0;
}
if (LaserPWMOUT>255)
{
LaserPWMOUT = 255;
}
// Ausgabe Terminal
{
Serial.print(“CNC in = " );
Serial.print(counter);
Serial.print(”\t LASER output = ");
Serial.println(LaserPWMOUT);
}

}

wie kann ich den Code so umstellen das der auch alle Impulse mit zählt?

Aja

Du musst statt dem Zustand des StepPin dessen Wechsel erfassen.
Das hängt jetzt etwas von der Geschwindigkeit ab, normalerweise sollte es so einfach gehen...

void loop()
{
    static boolean altStep;  // der vorige Zustand
    stepPinState=digitalRead(StepPin);
    if (stepPinState==HIGH && altStep == LOW)
    {
        // Kommende Flanke
        dirPinState = digitalRead(DirPin); 
        if (dirPinState == HIGH) counter++;
        else counter--; 
    }
    altStep = stepPinState;
...

}

Hmm das funzt nicht, hab aber was gefunden und mir das so geändert wie ich das brauche.

Klappt gut… bin gespannt ob das auch dann bei der Lasergravur klappt, die Schritte / Änderungen kommen extrem schnell hintereinander.

const int inStep = 2; // Step Eingang (Interupt 0)
const int inDirection = 3; // Richtungs Eingang
const int outPower = 9; // TTL-Ausgang - für Laser-Treiber
const int Endpinmax = 13;
const int Endpinmin = 12;

// Maximalwerte
const int minPower = 0; // Minimale Laser-Leistung
const int maxPower = 255; // Maximale Laser-Leistung

// Variablen
int Power = 0; // Laser-Power Level
int Powercount = 0; // Laser-Power Level Counter
int Powergrenz = 0; // Laser-Power Level Begrenzung
int Direction = 0; // Richtungs Handler

void setup()
{
Serial.begin(9600);
pinMode(inStep, INPUT);
pinMode(inDirection, INPUT);
pinMode(outPower, OUTPUT);
analogWrite(outPower, Power);
attachInterrupt(0, step, RISING);
}

void loop()
{
// 20 steps für C-0,0256 wert auf 8 bit = 255 mappen
Power, Powergrenz = map (Powercount, 0, 20, 0, 255);

//Maximalberenzung Laser-Power Level
if (Powergrenz > 255);
{
Power = 255;

// Wenn Power = 255 dann Enschalter emulieren
digitalWrite(Endpinmax, HIGH);
}

// Wenn Power = < 255 dann Enschalter nicht mehr emulieren
if(Powergrenz < 255);
{
digitalWrite(Endpinmax, LOW);
}

//Minimalberenzung Laser-Power Level
if (Powergrenz < 0);
{
Power = 0;

// Wenn Power = 0 dann Enschalter emulieren
digitalWrite(Endpinmin, HIGH);
}

// Wenn Power = > 0 dann Enschalter nicht mehr emulieren
if(Powergrenz > 0);
{
digitalWrite(Endpinmin, LOW);
}

// Ausgabe PWM
analogWrite(outPower, Power);

// Ausgabe über Serieleschnittstelle von Werten
Serial.print("Powercount = “);
Serial.print(Powercount);
Serial.print(”\t Direction = “);
Serial.print(Direction);
Serial.print(”\t Powerlevel = ");
Serial.println(Power);
}

void step()
{
Direction = digitalRead(inDirection);

// Powercounter + zählen
if ( Direction == HIGH)
{
Powercount++;
}

// Powercounter - zählen
if ( Direction == LOW )
{
Powercount–;
}
}

Hallo,

wenn der Takt bzw. Eingangsänderung wirklich sehr hoch ist, wenige ms, dann kannst Du schon Pech haben wenn Du mit Serial.print arbeitest. Die Ausgabe dauert auch eine gewissen Zeit. Könnte man vielleicht mit einer Displayausgabe schneller machen.

Ok das Serial.print kann ich weglassen ist nur ne Kontrolle um wie viel schneller würde das den dann laufen?

Hardware - Serial.print dauert keine Zeit, wenn der Ausgabepuffer ( 64 Zeichen ) nicht voll läuft.
50 Zeichen in mindestens 50 ms geht sogar bei 9600 Baud. Das ist mehr als man lesen kann.

Bleibt Powercount in den vorgesehenen Grenzen 0 .. 20 ??? Ich sehe keine Möglichkeit, den Wert irgendwie wieder zurückzusetzen ...

volatile byte Powercount; wäre übrigens besser als int Powercount

Muss es nicht

 Power = Powergrenz = map (Powercount, 0, 20, 0, 255);

heissen ???

Hallo,

aber 50ms sind doch schon Welten. Da macht eine kurze loop während dessen hunderte Durchläufe ...

Wenn mein großer 40kB Sketch keine Dallas Sensoren auslesen muß und keine SD Karte bedient, dauert eine loop 1 bis 2ms.

Die loop bleibt zwar mit serial nicht stehen, die loop dauert aber schon etwas länger wenn serial gerade aktiv ist. Oder irre ich micht gerade komplett?

michael_x:
Bleibt Powercount in den vorgesehenen Grenzen 0 .. 20 ??? Ich sehe keine Möglichkeit, den Wert irgendwie wieder zurückzusetzen ...

Muss auch nicht, die CNC sendet so oder so nur 20 Impulse für die Koordinate "C-0,0256" für "C0" zählt der dann anhand des Dir-Signal auf 0 zurück. Weiter als "C-0,0256" werde ich auch nicht gehen können da die andere Software das nicht mit macht.....

michael_x:
volatile byte Powercount; wäre übrigens besser als int Powercount

Warum?
So genau kenne ich mich nicht aus, deshalb würde ich das gern wissen.... man lernt ja nie aus :slight_smile:

michael_x:
Muss es nicht

 Power = Powergrenz = map (Powercount, 0, 20, 0, 255);

heissen

Macht das nicht das selbe? dachte das beide den selben Wert bekommen das Komma zwischen ist ja wie eine Aufzählung oder irre ich da?

Power, Powergrenz = map (Powercount, 0, 20, 0, 255);

Macht das nicht das selbe? dachte das beide den selben Wert bekommen das Komma zwischen ist ja wie eine Aufzählung oder irre ich da?

Habs grade mal ausprobiert: Nein -->

power , powergrenz = 123;  // lässt power unverändert

power; // ist auch erlaubt, aber sinnlos

volatile sagt dem Compiler, dass die Variable gleichzeitig irgendwo anders verändert werden kann, und verhindert so falsche Optimierungen.
byte reicht für eine Zahl 0 .. 20 aus und kann vom 8bit-Controller in einem einzigen Befehl verarbeitet werden. int sind 2 byte, die im Extremfall während des Umkopierens auf eine andere Variable in der ISR inkonsistent verändert werden könnten. Das passiert bei dir ( 0 .. 20 ) nicht, aber man sollte sich bei jedem int fragen, ob man das nur verwendet, weil es so schön schnell zu tippen ist :wink:

Ahh also sollte das bedeuten das

// Variablen
int Power = 0;                                // Laser-Power Level
volatile byte Powercount = 0;           // Laser-Power Level Counter
int Powergrenz = 0;                       // Laser-Power Level Begrenzung
int Direction = 0;                          // Richtungs Handler

erst mal sicherer ist wegen der Unterdrückung von falschen Optimierungen.

und

// Variablen
Power = Powergrenz = map (Powercount, 0, 20, 0, 255);

Ups, stimmt hab noch mal die Referenz im Handbuch gelesen :sweat_smile:

ok das bedeutet das der ganze code dann so aussehen sollte:

const int  inStep = 2;        // Step Eingang (Interupt 0)
const int  inDirection = 3;     // Richtungs Eingang
const int  outPower = 9;   // TTL-Ausgang - für Laser-Treiber
const int  Endpinmax = 13;
const int  Endpinmin = 12;

// Maximalwerte
const int  minPower = 0;      // Minimale Laser-Leistung
const int  maxPower = 255;    // Maximale Laser-Leistung

// Variablen
int Power = 0;                // Laser-Power Level
volatile byte Powercount = 0;           // Laser-Power Level Counter;           // Laser-Power Level Counter
int Powergrenz = 0;           // Laser-Power Level Begrenzung
int Direction = 0;            // Richtungs Handler

void setup() 
{
 Serial.begin(9600);
 pinMode(inStep, INPUT);
 pinMode(inDirection, INPUT);
 pinMode(outPower, OUTPUT);
 analogWrite(outPower, Power);
 attachInterrupt(0, step, RISING);
}


void loop() 
{
// 20 steps für C-0,0256 wert auf 8 bit = 255 mappen
  Power = Powergrenz = map (Powercount, 0, 20, 0, 255);
   
//Maximalberenzung Laser-Power Level
  if (Powergrenz > 255);
   {
     Power = 255;
     
// Wenn Power = 255 dann Enschalter emulieren 
    digitalWrite(Endpinmax, HIGH);
   }
     
// Wenn Power = < 255 dann Enschalter nicht mehr emulieren 
    if(Powergrenz < 255);
    { 
      digitalWrite(Endpinmax, LOW);
    }
    
//Minimalberenzung Laser-Power Level
  if (Powergrenz < 0);
  {
    Power = 0;
    
// Wenn Power = 0 dann Enschalter emulieren 
   digitalWrite(Endpinmin, HIGH);
  }
  
// Wenn Power = > 0 dann Enschalter nicht mehr emulieren 
    if(Powergrenz > 0);
    { 
      digitalWrite(Endpinmin, LOW);
    }

// Ausgabe PWM  
   analogWrite(outPower, Power);
   
// Ausgabe über Serieleschnittstelle von Werten   
   Serial.print("Powercount = ");
   Serial.print(Powercount);
   Serial.print("\t Direction = ");
   Serial.print(Direction);
   Serial.print("\t Powerlevel = ");
   Serial.println(Power);
 }

void step() 
{
   Direction = digitalRead(inDirection);
   
// Powercounter + zählen 
   if ( Direction == HIGH) 
   {
   Powercount++;
   }
   
// Powercounter - zählen   
   if ( Direction == LOW ) 
   {
   Powercount--;
   }
}

Ja, stört nur dass deine Serielle Ausgabe sehr oft drankommt.

static unsigned long lastprint;
if (millis() - lastprint > 1000)  // 1 Ausgabe je Sekunde
{
    Serial.println("Testausgabe ...");  // hier deine Ausgabe
    lastprint +=1000;
}

Oder du merkst dir den alten Wert von Powercount und gibst bei Änderung was aus.

Super :smiley:
wenn alles so klappt wie ich das will fliegt das ganze serial.print so oder so raus, ist ja nur das ich das erst mal kontrollieren und sehen kann. also gleich mal probieren