Proxxon IBS/E PWM Drehzahlregelung

Hallo,

ich möchte bei einem Proxxon Bohrschleifer IBS/E per PWM die Drehzahl mit eine Arduino regeln.
Der Bohrschleifer soll allerdings auch ohne angeschlossenes PWM-Signal funktionieren. Dazu habe ich folgendes gefunden:
Ich bin umgezogen.
Die Drehzahl soll mit einem Hallsensor erfasst werden und somit die Ist-Geschwindigkeit zur Soll-GeschwindigkeitGeregelt werden.

Hier ein paar Zeichnungen der Schaltung:

Bohrschleifer und PWM Eingangsschaltung:


Fritzing Sketch:

Dazu habe ich versucht folgende Codes zu vereinen:

PWM-Code:

int sensorPin = 0;
int pwmPin = 9;
int sensorValue = 0;

void setup() {
  pinMode(pwmPin, OUTPUT);
  // initialize serial communication at 9600 bits per second:
  TCCR1B = TCCR1B & 0b11111000 | 0x01;
  Serial.begin(9600);
}

// the loop routine runs over and over again forever:
void loop() {
  // read the input on analog pin 0:
  sensorValue = analogRead(sensorPin);
  // print out the value you read:
  Serial.println(sensorValue);
  analogWrite(pwmPin,sensorValue / 4);
  delay(1);        // delay in between reads for stability
}

Drehzahlerfassung:

volatile short rpmcount;
volatile int status;

unsigned int rpm;

unsigned long timeold;
void rpm_fun(){
  rpmcount++;    
  if (status == LOW) {
    status = HIGH;
  }else{
     status = LOW;
  }
   //digitalWrite(statusPin, status);
 }

void setup(){
  Serial.begin(9600);
  //Interrupt 0 is digital pin 2, so that is where the IR detector is connected
  //Triggers on FALLING (change from HIGH to LOW)
  attachInterrupt(0, rpm_fun, RISING);
  
  rpmcount = 0;
  rpm = 0;
  timeold = 0;
  status = LOW;
 }
 void loop() {
   //Update RPM every second
   delay(1000);
   detachInterrupt(0);
   rpm = 30*1000/(millis() - timeold)*rpmcount;
   timeold = millis();
   rpmcount = 0;

   Serial.print(rpm,DEC);
   Serial.print(" =U/min\n");

   attachInterrupt(0, rpm_fun, RISING);
  }

PID-Regelung: Arduino Playground - PIDLibrary

/********************************************************
 * PID Basic Example
 * Reading analog input 0 to control analog PWM output 3
 ********************************************************/

#include <PID_v1.h>

//Define Variables we'll be connecting to
double Setpoint, Input, Output;

//Specify the links and initial tuning parameters
PID myPID(&Input, &Output, &Setpoint,2,5,1, DIRECT);

void setup()
{
  //initialize the variables we're linked to
  Input = analogRead(0);
  Setpoint = 100;

  //turn the PID on
  myPID.SetMode(AUTOMATIC);
}

void loop()
{
  Input = analogRead(0);
  myPID.Compute();
  analogWrite(3,Output);
}

Mein Versuch dieses zu vereinen:

#include <PID_v1.h>

// pins
const int PWMpin = 9;   // PWM Output Pin
const int RPMint = 0;  // RPM Input Interupt (INT 0 pin 2)

//RPM Variablen
volatile short rpmcount;
volatile int state;
double rpm;

//PID Variablen
double setrpm, output, Kp = 1, Ki = 1, Kd = 0;
unsigned long timeold;

//Specify the links and initial tuning parameters
PID myPID(&rpm, &output, &setrpm, Kp,Ki,Kd, DIRECT);

void rpm_fun(){
  rpmcount++;    
  if (state == LOW) {
    state = HIGH;
  }else{
     state = LOW;
  }
   //digitalWrite(statusPin, state);
 }

void setup(){
  Serial.begin(9600); //Serial Conection
  
  //Set Pin Modes
  pinMode(PWMpin, OUTPUT);
  
  // set PWM frequncy for bin 9 to 31.250 kHz
  TCCR1B = (TCCR1B & 0b11111000) | 0x02;
  
  //Triggers on FALLING (change from HIGH to LOW)
  attachInterrupt(RPMint, rpm_fun, FALLING);
  
  rpmcount = 0;
  rpm = 0;
  timeold = 0;
  state = LOW;
  
  setrpm = 0;
  
  //turn the PID on
  myPID.SetMode(AUTOMATIC);
  
  
  
}
void loop() {
  
  // Get Set RPM per Serial Conection
  if (Serial.available() > 0) {
    setrpm = Serial.read();
  } else {
    setrpm = 0;
  }
  
  delay(1000);
  detachInterrupt(RPMint);
  rpm = 30*1000/(millis() - timeold)*rpmcount;
  timeold = millis();
  rpmcount = 0;
  
  Serial.print("Soll: ");
  Serial.print(setrpm);
  Serial.print(" U/min | ");
  
  Serial.print("Ist: ");
  Serial.print(rpm);
  Serial.print(" U/min \n");
  
  myPID.Compute();
  
  analogWrite(PWMpin,255-output);
  
  attachInterrupt(RPMint, rpm_fun, FALLING);
  }

Nur ist der Versuch mit wenig Erfolg gekrönt, da nun periodisch PWM Signale von 0 bzw. 255 erzeugt werd, die den Proxxon immer nur kurz voll beschleunigen und dann wieder austruddeln lassen.
Vielleicht kann mir hier im Forum jemand auf die Sprünge helfen.

Gruß
borsti87

Kann mir denn keiner Helfen? :frowning:

  if (Serial.available() > 0) {
    setrpm = Serial.read();
  } else {
    setrpm = 0;
  }

Das passt so irgendwie nicht. Das setzt setpwm gleich wieder zurück wenn nichts mehr im Eingangspuffer steht.

Außerdem liest du damit nur ein Zeichen aus. Du kannst da zwar z.B. 122 eingeben wenn du 'z' schickst, aber du kannst nicht "122" in den Monitor eintippen.

Ersetzte die Sollwert-Vorgabe vielleicht erstmal durch ein Poti dass du mit analogRead() ausliest und mit map() auf den PWM Bereich umsetzt.

borsti87:
Kann mir denn keiner Helfen? :frowning:

Es gibt wohl nicht so viele Arduino-Bastler, die ohne Not bei einem Gerät von einem erfahrenen Maschinenhersteller mit jahrzehntelanger Erfahrung die elektronische Drehzahlregelung rausreißen und durch eine eigene Arduino-Frickelei ersetzen möchten.

Arduino-Bastler, die sich und ihre Fähigkeiten überschätzen, produzieren sonst nämlich eher Elektroschrott als eine Maschine mit verbesserter Drehzahlreglung.

Ok die Regelung funktioniert jetzt soweit

#include <PID_v1.h>


// pins
const int PWMpin = 9;   // PWM Output Pin
const int RPMint = 0;  // RPM Input Interupt (INT 0 pin 2)

//RPM Variablen
volatile short rpmcount;
volatile int state;
double rpm;
unsigned long timeold;

//PID Variablen
double setrpm, output, Kp = 0.01, Ki = 0.1, Kd = 0;

//Specify the links and initial tuning parameters
PID myPID(&rpm, &output, &setrpm, Kp,Ki,Kd, DIRECT);

void rpm_fun(){
  rpmcount++;    
  if (state == LOW) {
    state = HIGH;
  }else{
     state = LOW;
  }
   //digitalWrite(statusPin, state);
 }

void setup(){
  Serial.begin(9600); //Serial Conection
  
  //Set Pin Modes
  pinMode(PWMpin, OUTPUT);
  
  // set PWM frequncy for bin 9 to 31.250 kHz
  TCCR1B = (TCCR1B & 0b11111000) | 0x01;
  
  //Triggers on FALLING (change from HIGH to LOW)
  attachInterrupt(RPMint, rpm_fun, FALLING);
  
  rpmcount = 0;
  rpm = 0;
  timeold = 0;
  state = LOW;
  
  setrpm = 5000; // Fixwert
  
  myPID.SetSampleTime(10);
  //turn the PID on
  myPID.SetMode(AUTOMATIC);
  
  
  
}
void loop() {
  
  delay(100);
  detachInterrupt(RPMint);
  rpm = 30*1000/(millis() - timeold)*rpmcount;
  timeold = millis();
  rpmcount = 0;
  
  Serial.print("Soll: ");
  Serial.print(setrpm);
  Serial.print(" U/min | ");
  
  Serial.print("Ist: ");
  Serial.print(rpm);
  Serial.print(" U/min \n");
  
  myPID.Compute();
  
  analogWrite(PWMpin,255-output);
  
  attachInterrupt(RPMint, rpm_fun, FALLING);
  }

nun möchte ich gerne von einem Arduino MEGA 2560 aus über I²C einen Arduino UNO MEGA 328P mit Daten wie Status ON/OFF und der Solldrehzahl füttern.
Ich habe mir das Sende-Script ungefähr so vorgestellt:

...
void TurnSpindelOn(int speed)
{
	Wire.beginTransmission(SPINDEL_I2C_ADDR);
	Wire.write("ON");	
	Wire.write(lowByte(speed));
	Wire.write(highByte(speed));
	Wire.endTransmission();
}

void TurnSpindelOff()
{
	Wire.beginTransmission(SPINDEL_I2C_ADDR);
	Wire.write("OFF");
	Wire.endTransmission();	
}

Nur bin ich mir jetzt nicht ganz schlüßig wie ich das am UNO verarbeite.
Werde aus den ganzen Beispielen die ich gefunden habe nich so schlau.
(z.B. http://arduino.cc/en/Tutorial/MasterWriter)