Go Down

Topic: Contnuous PWM Output while monitoring Input Changes (Read 167 times) previous topic - next topic

tofday

hey folks I am wondering if this code will give me a clean PWM output while I watch for CNC input value changes.
I am having the A Axis change height values (simulate axis movement) to control the signal being sent to a little blue laser controller that is looking for PWM signal.
My concern is that the incoming signal from the computer printer port will not be seen by the arduino or that the PWM will not be steady and will mess up the signal to the laser and in turn mess up the lasers output strength

Thanks for your help.

Duewy

TonyWilk

Hi,
I gather you are trying to read the A axis drive (Enable, Dir, Step) to adjust a value 0..255 to drive PWM on an output pin.

Having Serial.print()'s and delay(5000) in your loop() will make it miss steps.

Your decoding of the drive signals looks a bit suspect...
Once Enable is HIGH, I guess you want to read the Direction pin when the Step pin pulses, not before.

Something like:
Code: [Select]
loop(){
  if( Step is HIGH and Enable is HIGH ){
    read Direction
    adjust Step_Count_Val
    output PWM
    wait for Step to go Low again
  }
}


If you have control over Step pulse width, you want to set it to, say, 500uS with max. 500 steps/sec 


Yours,
  TonyWilk


tofday

#2
Jan 16, 2018, 11:19 pm Last Edit: Jan 16, 2018, 11:34 pm by tofday Reason: Modified Attached Code and Clarified Questions
Hi,
I gather you are trying to read the A axis drive (Enable, Dir, Step) to adjust a value 0..255 to drive PWM on an output pin.

Having Serial.print()'s and delay(5000) in your loop() will make it miss steps.

Your decoding of the drive signals looks a bit suspect...
Once Enable is HIGH, I guess you want to read the Direction pin when the Step pin pulses, not before.

Something like:
Code: [Select]
loop(){
  if( Step is HIGH and Enable is HIGH ){
    read Direction
    adjust Step_Count_Val
    output PWM
    wait for Step to go Low again
  }
}


If you have control over Step pulse width, you want to set it to, say, 500uS with max. 500 steps/sec  


Yours,
  TonyWilk


Hey Tony
Thanks for the suggestions....
The wait 5000 is just there so the arduino is not working when the A axis is not enabled and the Laser is not connected
Yes the main purpose is to take an increase or decrease (direction pin high or low) and read the number of pulse from the step pin.
Then take the information and send a continuous PWM signal to the laser controller from 0% to 100%

This way as the laser goes over the work in the X and Y directions the laser can increase and decrease the intensity of the burn to match the 0 to 255 gray scale of the image it is printing/burning onto the work.

My issue is that the incoming signal from the computer printer port is 5 uS (0.000005) seconds
The communication rate of the MACH 3 CNC program is 25000 baud

So can the Arduino capture the incoming signals?
Can the Arduino send out a constant PWM while it is reading the 3 inputs and calculating the PWM value?

The portion of the code for the printing of the information will be removed for the actual running code.
It will look something like the attached file.

If you or someone has a better bit of code that will make this happen then Please post it.

Thanks for your time and Help
Any information will be greatly appretiated

Duewy



TonyWilk

Assuming you have an Arduino UNO, try this:

Code: [Select]

//
// Example program to capture STEP pulses in interrupt
// - assumes STEP is active on rising edge
// - assumes DIR is stable after STEP edge
// - assumes DIR == HIGH is a +ve step
//
// accumulates a total Step_Count_Val 0..255
// outputs value to fast PWM (62KHz)
//
// TonyWilk



// This must be the PWM output pin
//
const int Laser_PWM_Pin = 9;      // Laser Board connected to PWM pin 9

const int A_Enable_Pin = 4;   // A Axis Enable connected to digital pin 4
const int A_Dri_Pin = 3;      // A Axis Dir connected to digital pin 3
#define DIR_PIN_BITMASK 0x08  // bit 3 of PORTD

// This must be an interrupt-capable pin
//
const int A_Step_Pin = 2;  // A Axis Step connected to digital pin 2

int16_t isr_step_count= 0;

// Interrupt routine called on A_Step_Pin
//
void step_ISR()
{
  if( PIND & DIR_PIN_BITMASK )
    ++isr_step_count;
  else
    --isr_step_count;
}


void setup() {
  cli();    // interrupts off while we set stuff up

  pinMode(Laser_PWM_Pin, OUTPUT);    // sets the pin as output
  pinMode(A_Enable_Pin, INPUT_PULLUP);     // sets the pin as input
  pinMode(A_Dri_Pin, INPUT_PULLUP);        // sets the pin as input
  pinMode(A_Step_Pin, INPUT_PULLUP);       // sets the pin as input

  //pinMode(TEST_PIN, OUTPUT);

  // Set timer1 for 8-bit fast PWM output
  pinMode(9, OUTPUT); // Make timer's PWM pin an output

  TCCR1B = (1 << CS10);     // Set prescaler to full 16MHz
  TCCR1A |= (1 << COM1A1);  // Pin low when TCNT1=OCR1A
  TCCR1A |= (1 << WGM10);   // Use 8-bit fast PWM mode
  TCCR1B |= (1 << WGM12);

  attachInterrupt(digitalPinToInterrupt(A_Step_Pin), step_ISR, RISING );

  sei();      // Enable interrupts to generate waveform!

  Serial.begin( 9600 );   // ********* DEBUG ONLY ***********
}

int Step_Count_Val = 0;      // store the value of cummulated Step_Count_Val  max 255 min 0

void loop() {
  // put your main code here, to run repeatedly:

  if( digitalRead( A_Enable_Pin ) == LOW )
  {
    cli();                // not enabled, zero the isr step count
    isr_step_count= 0;
    sei();

    // Turn off PWM if not enabled ???
    // OCR1AL= 0;
   
  }else{
    // enabled...
    if( isr_step_count != 0 )
    {
      // copy any stepping from isr
      cli();       
      Step_Count_Val+= isr_step_count;
      isr_step_count= 0;
      sei();

      // Pass value to PWM
      Step_Count_Val = constrain(Step_Count_Val, 0, 255);
      OCR1AL= (uint8_t)Step_Count_Val;

      Serial.println( Step_Count_Val );
    }
  }

}



Since it appears you don't have much control over MACH3's step pulse width, then the only chance with an Arduino is to capture the transition in interrupt.

Notice that the pins have had to change.

If it works at all, you should see output on the serial monitor showing the step value.
(this is only printed when steps are detected).


I've tested this on the bench, but I've no idea what your signals are like, what the polarity is etc. etc. etc.

Good luck.

Yours,
  TonyWilk

tofday

#4
Today at 05:15 pm Last Edit: Today at 06:17 pm by tofday Reason: Add information
Too Good
Thank you so much

I will try this today.
I take it you are using another code language,,,, "C"?

So many languages ,,, so little grey matter.
I have a heck of a time with this jumbled up mess we call English.

Humbly in your debt

Duewy


I take it that removing the serial command lines will help speed up the arduino uno during the actual operations of the CNC?
sei();      // Enable interrupts to generate waveform!

  //Serial.begin( 9600 );   // ********* DEBUG ONLY ***********
}

int Step_Count_Val = 0;      // store the value of cummulated Step_Count_Val  max 255 min 0

void loop() {
  // put your main code here, to run repeatedly:

  if( digitalRead( A_Enable_Pin ) == LOW )
  {
    cli();                // not enabled, zero the isr step count
    isr_step_count= 0;
    sei();

    // Turn off PWM if not enabled ???
    // OCR1AL= 0;
   
  }else{
    // enabled...
    if( isr_step_count != 0 )
    {
      // copy any stepping from isr
      cli();       
      Step_Count_Val+= isr_step_count;
      isr_step_count= 0;
      sei();

      // Pass value to PWM
      Step_Count_Val = constrain(Step_Count_Val, 0, 255);
      OCR1AL= (uint8_t)Step_Count_Val;

     // Serial.println( Step_Count_Val );

TonyWilk

I take it that removing the serial command lines will help speed up the arduino uno during the actual operations of the CNC?
Correct.

Not only does Serial take time, it also uses an interrupt so response of the pin interrupt will vary a bit.

If it works at all, it still might miss the odd step due to another Arduino interrupt (which we can disable if need be).

Yours,
  TonyWilk

Go Up